graph2: Added Story type and queries.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package stories
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"strconv"
|
||||
|
||||
"git.aiterp.net/rpdata/api/internal/store"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo"
|
||||
)
|
||||
|
||||
var collection *mgo.Collection
|
||||
|
||||
func find(query interface{}) (models.Story, error) {
|
||||
story := models.Story{}
|
||||
err := collection.Find(query).One(&story)
|
||||
|
||||
return story, err
|
||||
}
|
||||
|
||||
func list(query interface{}, limit int) ([]models.Story, error) {
|
||||
stories := make([]models.Story, 0, 64)
|
||||
err := collection.Find(query).Limit(limit).Sort("-updatedDate").All(&stories)
|
||||
|
||||
return stories, err
|
||||
}
|
||||
|
||||
// makeStoryID makes a random story ID that's 16 characters long
|
||||
func makeStoryID() string {
|
||||
result := "S"
|
||||
offset := 0
|
||||
data := make([]byte, 32)
|
||||
|
||||
rand.Read(data)
|
||||
for len(result) < 16 {
|
||||
result += strconv.FormatUint(binary.LittleEndian.Uint64(data[offset:]), 36)
|
||||
offset += 8
|
||||
|
||||
if offset >= 32 {
|
||||
rand.Read(data)
|
||||
offset = 0
|
||||
}
|
||||
}
|
||||
|
||||
return result[:16]
|
||||
}
|
||||
|
||||
func init() {
|
||||
store.HandleInit(func(db *mgo.Database) {
|
||||
collection = db.C("story.stories")
|
||||
|
||||
collection.EnsureIndexKey("tags")
|
||||
collection.EnsureIndexKey("author")
|
||||
collection.EnsureIndexKey("updatedDate")
|
||||
collection.EnsureIndexKey("fictionalDate")
|
||||
collection.EnsureIndexKey("listed")
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package stories
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// FindID finds a story by ID
|
||||
func FindID(id string) (models.Story, error) {
|
||||
return find(bson.M{"_id": id})
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package stories
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// Filter for stories.List
|
||||
type Filter struct {
|
||||
Author *string
|
||||
Tags []models.Tag
|
||||
EarliestFictionalDate time.Time
|
||||
LatestFictionalDate time.Time
|
||||
Category *models.StoryCategory
|
||||
Open *bool
|
||||
Unlisted *bool
|
||||
Limit int
|
||||
}
|
||||
|
||||
// List lists stories by any non-zero criteria passed with it.
|
||||
func List(filter *Filter) ([]models.Story, error) {
|
||||
query := bson.M{"listed": true}
|
||||
limit := 0
|
||||
|
||||
if filter != nil {
|
||||
if filter.Author != nil {
|
||||
query["author"] = *filter.Author
|
||||
}
|
||||
|
||||
if len(filter.Tags) > 0 {
|
||||
query["tags"] = bson.M{"$in": filter.Tags}
|
||||
}
|
||||
|
||||
if !filter.EarliestFictionalDate.IsZero() && !filter.LatestFictionalDate.IsZero() {
|
||||
query["fictionalDate"] = bson.M{
|
||||
"$gte": filter.EarliestFictionalDate,
|
||||
"$lt": filter.LatestFictionalDate,
|
||||
}
|
||||
} else if !filter.LatestFictionalDate.IsZero() {
|
||||
query["fictionalDate"] = bson.M{
|
||||
"$lt": filter.LatestFictionalDate,
|
||||
}
|
||||
} else if !filter.EarliestFictionalDate.IsZero() {
|
||||
query["fictionalDate"] = bson.M{
|
||||
"$gte": filter.EarliestFictionalDate,
|
||||
}
|
||||
}
|
||||
|
||||
if filter.Category != nil {
|
||||
query["category"] = *filter.Category
|
||||
}
|
||||
|
||||
if filter.Open != nil {
|
||||
query["open"] = *filter.Open
|
||||
}
|
||||
|
||||
if filter.Unlisted != nil {
|
||||
query["listed"] = !*filter.Unlisted
|
||||
}
|
||||
|
||||
limit = filter.Limit
|
||||
}
|
||||
|
||||
return list(query, limit)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// StoryCategory represents the category of a story.
|
||||
type StoryCategory string
|
||||
|
||||
const (
|
||||
// StoryCategoryInfo is a story category, see GraphQL documentation.
|
||||
StoryCategoryInfo StoryCategory = "Info"
|
||||
// StoryCategoryNews is a story category, see GraphQL documentation.
|
||||
StoryCategoryNews StoryCategory = "News"
|
||||
// StoryCategoryDocument is a story category, see GraphQL documentation.
|
||||
StoryCategoryDocument StoryCategory = "Document"
|
||||
// StoryCategoryBackground is a story category, see GraphQL documentation.
|
||||
StoryCategoryBackground StoryCategory = "Background"
|
||||
// StoryCategoryStory is a story category, see GraphQL documentation.
|
||||
StoryCategoryStory StoryCategory = "Story"
|
||||
)
|
||||
|
||||
// UnmarshalGQL unmarshals
|
||||
func (e *StoryCategory) UnmarshalGQL(v interface{}) error {
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("enums must be strings")
|
||||
}
|
||||
|
||||
*e = StoryCategory(str)
|
||||
switch *e {
|
||||
case StoryCategoryInfo, StoryCategoryNews, StoryCategoryDocument, StoryCategoryBackground, StoryCategoryStory:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("%s is not a valid StoryCategory", str)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalGQL turns it into a JSON string
|
||||
func (e StoryCategory) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, "\""+string(e)+"\"")
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// A Story is user content that does not have a wiki-suitable format. Documents, new stories, short stories, and so on.
|
||||
// The story model is a container for multiple chapters this time, in contrast to the previous version.
|
||||
type Story struct {
|
||||
ID string `bson:"_id"`
|
||||
Author string `bson:"author"`
|
||||
Name string `bson:"name"`
|
||||
Category StoryCategory `bson:"category"`
|
||||
Open bool `bson:"open"`
|
||||
Listed bool `bson:"listed"`
|
||||
Tags []Tag `bson:"tags"`
|
||||
CreatedDate time.Time `bson:"createdDate"`
|
||||
FictionalDate time.Time `bson:"fictionalDate,omitempty"`
|
||||
UpdatedDate time.Time `bson:"updatedDate"`
|
||||
}
|
||||
Reference in New Issue
Block a user