graph2: Added Story type and queries.

This commit is contained in:
2018-09-16 12:55:14 +02:00
parent bac57bc378
commit 79171bf9a2
11 changed files with 429 additions and 0 deletions
+59
View File
@@ -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")
})
}
+11
View File
@@ -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})
}
+67
View File
@@ -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)
}
+43
View File
@@ -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)+"\"")
}
+18
View File
@@ -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"`
}