models: Painstakingly converted half the model package to a models & repostiry stucture. All binaries are probably dead at this point.
the build failed
the build failed
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package models
|
||||
|
||||
// A Channel represents information abount an IRC RP channel, and whether it should be logged
|
||||
type Channel struct {
|
||||
Name string `bson:"_id"`
|
||||
Logged bool `bson:"logged"`
|
||||
Hub bool `bson:"hub"`
|
||||
EventName string `bson:"event,omitempty"`
|
||||
LocationName string `bson:"location,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package channels
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
// ErrInvalidName is an error for an invalid channel name.
|
||||
var ErrInvalidName = errors.New("Invalid channel name")
|
||||
|
||||
// Add creates a new channel.
|
||||
func Add(name string, logged, hub bool, event, location string) (models.Channel, error) {
|
||||
if len(name) < 3 && !strings.HasPrefix(name, "#") {
|
||||
return models.Channel{}, ErrInvalidName
|
||||
}
|
||||
|
||||
channel := models.Channel{
|
||||
Name: name,
|
||||
Logged: logged,
|
||||
Hub: hub,
|
||||
EventName: event,
|
||||
LocationName: location,
|
||||
}
|
||||
|
||||
err := collection.Insert(channel)
|
||||
if err != nil {
|
||||
return models.Channel{}, err
|
||||
}
|
||||
|
||||
return channel, nil
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package channels
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/internal/store"
|
||||
"github.com/globalsign/mgo"
|
||||
)
|
||||
|
||||
var collection *mgo.Collection
|
||||
|
||||
func init() {
|
||||
store.HandleInit(func(db *mgo.Database) {
|
||||
collection = db.C("common.channels")
|
||||
|
||||
collection.EnsureIndexKey("logged")
|
||||
collection.EnsureIndexKey("hub")
|
||||
collection.EnsureIndexKey("event")
|
||||
collection.EnsureIndexKey("location")
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package channels
|
||||
|
||||
import "git.aiterp.net/rpdata/api/models"
|
||||
|
||||
// FindName finds a channel by its id (its name).
|
||||
func FindName(name string) (models.Channel, error) {
|
||||
channel := models.Channel{}
|
||||
err := collection.FindId(name).One(&channel)
|
||||
|
||||
return channel, err
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package channels
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// Filter for searching
|
||||
type Filter struct {
|
||||
Logged *bool `json:"logged"`
|
||||
EventName string `json:"eventName"`
|
||||
LocationName string `json:"locationName"`
|
||||
}
|
||||
|
||||
// List finds channels, if logged is true it will be limited to logged
|
||||
// channels
|
||||
func List(filter *Filter) ([]models.Channel, error) {
|
||||
query := bson.M{}
|
||||
|
||||
if filter != nil {
|
||||
if filter.Logged != nil {
|
||||
query["logged"] = *filter.Logged
|
||||
}
|
||||
if filter.EventName != "" {
|
||||
query["eventName"] = filter.EventName
|
||||
}
|
||||
if filter.LocationName != "" {
|
||||
query["locationName"] = filter.LocationName
|
||||
}
|
||||
}
|
||||
|
||||
channels := make([]models.Channel, 0, 128)
|
||||
err := collection.Find(query).All(&channels)
|
||||
|
||||
return channels, err
|
||||
}
|
||||
|
||||
// ListNames finds channels by the names provided
|
||||
func ListNames(names ...string) ([]models.Channel, error) {
|
||||
query := bson.M{"_id": bson.M{"$in": names}}
|
||||
|
||||
channels := make([]models.Channel, 0, 32)
|
||||
err := collection.Find(query).All(&channels)
|
||||
|
||||
return channels, err
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
// Character is a common data model representing an RP character or NPC.
|
||||
type Character struct {
|
||||
ID string `json:"id" bson:"_id"`
|
||||
Nicks []string `json:"nicks" bson:"nicks"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
ShortName string `json:"shortName" bson:"shortName"`
|
||||
Author string `json:"author" bson:"author"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
}
|
||||
|
||||
// Nick gets the character's nick.
|
||||
func (character *Character) Nick() *string {
|
||||
if len(character.Nicks[0]) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &character.Nicks[0]
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package characters
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/model/counter"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
// Add creates a Character and pushes it to the database. It does some validation
|
||||
// on nick, name, shortName and author. It will generate a shortname from the first
|
||||
// name if a blank one is provided.
|
||||
func Add(nick, name, shortName, author, description string) (models.Character, error) {
|
||||
if len(nick) < 1 || len(name) < 1 || len(author) < 1 {
|
||||
return models.Character{}, errors.New("Nick, name, or author name too short or empty")
|
||||
}
|
||||
if shortName == "" {
|
||||
shortName = strings.SplitN(name, " ", 2)[0]
|
||||
}
|
||||
|
||||
char, err := FindNick(nick)
|
||||
if err == nil && char.ID != "" {
|
||||
return models.Character{}, errors.New("Nick is occupied")
|
||||
}
|
||||
|
||||
nextID, err := counter.Next("auto_increment", "models.Character")
|
||||
if err != nil {
|
||||
return models.Character{}, err
|
||||
}
|
||||
|
||||
character := models.Character{
|
||||
ID: "C" + strconv.Itoa(nextID),
|
||||
Nicks: []string{nick},
|
||||
Name: name,
|
||||
ShortName: shortName,
|
||||
Author: author,
|
||||
Description: description,
|
||||
}
|
||||
|
||||
err = collection.Insert(character)
|
||||
if err != nil {
|
||||
return models.Character{}, err
|
||||
}
|
||||
|
||||
return character, nil
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package characters
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"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.Character, error) {
|
||||
character := models.Character{}
|
||||
err := collection.Find(query).One(&character)
|
||||
if err != nil {
|
||||
return models.Character{}, err
|
||||
}
|
||||
|
||||
return character, nil
|
||||
}
|
||||
|
||||
func list(query interface{}) ([]models.Character, error) {
|
||||
characters := make([]models.Character, 0, 64)
|
||||
err := collection.Find(query).All(&characters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return characters, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
store.HandleInit(func(db *mgo.Database) {
|
||||
collection = db.C("common.characters")
|
||||
|
||||
collection.EnsureIndexKey("name")
|
||||
collection.EnsureIndexKey("shortName")
|
||||
collection.EnsureIndexKey("author")
|
||||
err := collection.EnsureIndex(mgo.Index{
|
||||
Key: []string{"nicks"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalln("init common.characters:", err)
|
||||
}
|
||||
err = collection.EnsureIndex(mgo.Index{
|
||||
Key: []string{"$text:description"},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalln("init common.characters:", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package characters
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// FindID finds a character by id.
|
||||
func FindID(id string) (models.Character, error) {
|
||||
return find(bson.M{"_id": id})
|
||||
}
|
||||
|
||||
// FindNick finds a character by nick
|
||||
func FindNick(nick string) (models.Character, error) {
|
||||
return find(bson.M{"nicks": nick})
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package characters
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// Filter is used to filter the list of characters
|
||||
type Filter struct {
|
||||
IDs []string `json:"ids"`
|
||||
Nicks []string `json:"nicks"`
|
||||
Names []string `json:"names"`
|
||||
Author *string `json:"author"`
|
||||
Search *string `json:"search"`
|
||||
Logged *bool `json:"logged"`
|
||||
}
|
||||
|
||||
// List lists all characters
|
||||
func List(filter *Filter) ([]models.Character, error) {
|
||||
query := bson.M{}
|
||||
|
||||
if filter != nil {
|
||||
if len(filter.IDs) > 1 {
|
||||
query["_id"] = bson.M{"$in": filter.IDs}
|
||||
} else if len(filter.IDs) == 1 {
|
||||
query["_id"] = filter.IDs[0]
|
||||
}
|
||||
|
||||
if len(filter.Nicks) > 1 {
|
||||
query["nicks"] = bson.M{"$in": filter.Nicks}
|
||||
} else if len(filter.Nicks) == 1 {
|
||||
query["nicks"] = filter.Nicks[0]
|
||||
}
|
||||
|
||||
if len(filter.Names) > 1 {
|
||||
query["$or"] = bson.M{
|
||||
"name": bson.M{"$in": filter.Names},
|
||||
"shortName": bson.M{"$in": filter.Names},
|
||||
}
|
||||
} else if len(filter.Names) == 1 {
|
||||
query["$or"] = bson.M{
|
||||
"name": filter.Names[0],
|
||||
"shortName": filter.Names[0],
|
||||
}
|
||||
}
|
||||
|
||||
if filter.Logged != nil {
|
||||
query["logged"] = *filter.Logged
|
||||
}
|
||||
|
||||
if filter.Author != nil {
|
||||
query["author"] = *filter.Author
|
||||
}
|
||||
|
||||
if filter.Search != nil {
|
||||
query["$text"] = bson.M{"$search": *filter.Search}
|
||||
}
|
||||
}
|
||||
|
||||
return list(query)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// Log is the header/session for a log file.
|
||||
type Log struct {
|
||||
ID string `bson:"_id"`
|
||||
ShortID string `bson:"shortId"`
|
||||
Date time.Time `bson:"date"`
|
||||
ChannelName string `bson:"channel"`
|
||||
EventName string `bson:"event,omitempty"`
|
||||
Title string `bson:"title,omitempty"`
|
||||
Description string `bson:"description,omitempty"`
|
||||
Open bool `bson:"open"`
|
||||
CharacterIDs []string `bson:"characterIds"`
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/internal/store"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo"
|
||||
)
|
||||
|
||||
var collection *mgo.Collection
|
||||
var postCollection *mgo.Collection
|
||||
|
||||
func find(query interface{}) (models.Log, error) {
|
||||
log := models.Log{}
|
||||
err := collection.Find(query).One(&log)
|
||||
if err != nil {
|
||||
return models.Log{}, err
|
||||
}
|
||||
|
||||
return log, nil
|
||||
}
|
||||
|
||||
func list(query interface{}, limit int) ([]models.Log, error) {
|
||||
logs := make([]models.Log, 0, 64)
|
||||
err := collection.Find(query).Limit(limit).Sort("-date").All(&logs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
func iter(query interface{}, limit int) *mgo.Iter {
|
||||
return collection.Find(query).Sort("-date").Limit(limit).Batch(8).Iter()
|
||||
}
|
||||
|
||||
func makeLogID(date time.Time, channel string) string {
|
||||
return fmt.Sprintf("%s%03d_%s", date.UTC().Format("2006-01-02_150405"), (date.Nanosecond() / int(time.Millisecond/time.Nanosecond)), channel[1:])
|
||||
}
|
||||
|
||||
func init() {
|
||||
store.HandleInit(func(db *mgo.Database) {
|
||||
collection = db.C("logbot3.logs")
|
||||
postCollection = db.C("logbo3.posts")
|
||||
|
||||
collection.EnsureIndexKey("date")
|
||||
collection.EnsureIndexKey("channel")
|
||||
collection.EnsureIndexKey("characterIds")
|
||||
collection.EnsureIndexKey("event")
|
||||
collection.EnsureIndex(mgo.Index{
|
||||
Key: []string{"channel", "open"},
|
||||
})
|
||||
err := collection.EnsureIndex(mgo.Index{
|
||||
Key: []string{"shortId"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalln("init logbot3.logs:", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// FindID finds a log either by it's ID or short ID.
|
||||
func FindID(id string) (models.Log, error) {
|
||||
return find(bson.M{
|
||||
"$or": []bson.M{
|
||||
bson.M{"_id": id},
|
||||
bson.M{"shortId": id},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// Filter for the List() function
|
||||
type Filter struct {
|
||||
Search *string
|
||||
Characters *[]string
|
||||
Channels *[]string
|
||||
Events *[]string
|
||||
Open *bool
|
||||
Limit int
|
||||
}
|
||||
|
||||
// List lists all logs
|
||||
func List(filter *Filter) ([]models.Log, error) {
|
||||
query := bson.M{}
|
||||
limit := 0
|
||||
|
||||
if filter != nil {
|
||||
// Run a text search
|
||||
if filter.Search != nil {
|
||||
searchResults, err := search(*filter.Search)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Posts always use shortId to refer to the log
|
||||
query["shortId"] = bson.M{"$in": searchResults}
|
||||
}
|
||||
|
||||
// Find logs including any of the specified events and channels
|
||||
if filter.Channels != nil {
|
||||
query["channel"] = bson.M{"$in": *filter.Channels}
|
||||
}
|
||||
if filter.Events != nil {
|
||||
query["event"] = bson.M{"$in": *filter.Events}
|
||||
}
|
||||
|
||||
// Find logs including all of the specified character IDs.
|
||||
if filter.Characters != nil {
|
||||
query["characterIds"] = bson.M{"$all": *filter.Characters}
|
||||
}
|
||||
|
||||
// Limit to only open logs
|
||||
if filter.Open != nil {
|
||||
query["open"] = *filter.Open
|
||||
}
|
||||
|
||||
// Set the limit from the filter
|
||||
limit = filter.Limit
|
||||
}
|
||||
|
||||
return list(query, limit)
|
||||
}
|
||||
|
||||
func search(text string) ([]string, error) {
|
||||
query := bson.M{
|
||||
"$text": bson.M{"$search": text},
|
||||
"logId": bson.M{"$ne": nil},
|
||||
}
|
||||
|
||||
ids := make([]string, 0, 64)
|
||||
err := postCollection.Find(query).Distinct("logId", ids)
|
||||
|
||||
return ids, err
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// A Post is a part of a log file.
|
||||
type Post struct {
|
||||
ID string `bson:"_id"`
|
||||
LogID string `bson:"logId"`
|
||||
Time time.Time `bson:"time"`
|
||||
Kind string `bson:"kind"`
|
||||
Nick string `bson:"nick"`
|
||||
Text string `bson:"text"`
|
||||
Position int `bson:"position"`
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package posts
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"git.aiterp.net/rpdata/api/internal/store"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo"
|
||||
)
|
||||
|
||||
var collection *mgo.Collection
|
||||
var mutex sync.RWMutex
|
||||
|
||||
func find(query interface{}) (models.Post, error) {
|
||||
post := models.Post{}
|
||||
err := collection.Find(query).One(&post)
|
||||
if err != nil {
|
||||
return models.Post{}, err
|
||||
}
|
||||
|
||||
return post, nil
|
||||
}
|
||||
|
||||
func list(query interface{}, limit int, sort ...string) ([]models.Post, error) {
|
||||
size := 64
|
||||
if limit > 0 {
|
||||
size = limit
|
||||
}
|
||||
posts := make([]models.Post, 0, size)
|
||||
|
||||
err := collection.Find(query).Limit(limit).Sort(sort...).All(&posts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return posts, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
store.HandleInit(func(db *mgo.Database) {
|
||||
collection = db.C("logbot3.posts")
|
||||
|
||||
collection.EnsureIndexKey("logId")
|
||||
collection.EnsureIndexKey("time")
|
||||
collection.EnsureIndexKey("kind")
|
||||
collection.EnsureIndexKey("position")
|
||||
|
||||
err := collection.EnsureIndex(mgo.Index{
|
||||
Key: []string{"$text:text"},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalln("init logbot3.logs:", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package posts
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// FindID finds a log post by ID.
|
||||
func FindID(id string) (models.Post, error) {
|
||||
mutex.RLock()
|
||||
defer mutex.RUnlock()
|
||||
|
||||
return find(bson.M{"_id": id})
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package posts
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// Filter is used to generate a query to the database.
|
||||
type Filter struct {
|
||||
ID []string
|
||||
Kind []string
|
||||
LogID *string
|
||||
Search *string
|
||||
Limit int
|
||||
}
|
||||
|
||||
// List lists the posts according to the filter
|
||||
func List(filter *Filter) ([]models.Post, error) {
|
||||
mutex.RLock()
|
||||
defer mutex.RUnlock()
|
||||
|
||||
limit := 256
|
||||
query := bson.M{}
|
||||
|
||||
if filter != nil {
|
||||
if filter.LogID != nil {
|
||||
query["logId"] = filter.LogID
|
||||
}
|
||||
|
||||
if len(filter.ID) > 1 {
|
||||
query["_id"] = bson.M{"$in": filter.ID}
|
||||
} else if len(filter.ID) == 1 {
|
||||
query["_id"] = filter.ID[0]
|
||||
}
|
||||
|
||||
if len(filter.Kind) > 1 {
|
||||
for i := range filter.Kind {
|
||||
filter.Kind[i] = strings.ToLower(filter.Kind[i])
|
||||
}
|
||||
|
||||
query["kind"] = bson.M{"$in": filter.Kind}
|
||||
} else if len(filter.Kind) == 1 {
|
||||
query["kind"] = strings.ToLower(filter.Kind[0])
|
||||
}
|
||||
|
||||
limit = filter.Limit
|
||||
}
|
||||
|
||||
posts, err := list(query, limit, "position")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return posts, nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package posts
|
||||
@@ -0,0 +1,28 @@
|
||||
package scalars
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
)
|
||||
|
||||
// MarshalDate marshals time into gql Date type
|
||||
func MarshalDate(t time.Time) graphql.Marshaler {
|
||||
return graphql.WriterFunc(func(w io.Writer) {
|
||||
w.Write([]byte(`"` + t.Format(time.RFC3339Nano) + `"`))
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalDate unmarshals time from gql Date type
|
||||
func UnmarshalDate(v interface{}) (time.Time, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return time.Parse(time.RFC3339Nano, v)
|
||||
case int:
|
||||
return time.Unix(0, int64(v)*1000000), nil
|
||||
default:
|
||||
return time.Time{}, fmt.Errorf("%T is not a valid time", v)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// TagKind represents the kind of tags.
|
||||
type TagKind string
|
||||
|
||||
const (
|
||||
// TagKindOrganization is a tag kind, see GraphQL documentation.
|
||||
TagKindOrganization TagKind = "Organization"
|
||||
|
||||
// TagKindCharacter is a tag kind, see GraphQL documentation.
|
||||
TagKindCharacter TagKind = "Character"
|
||||
|
||||
// TagKindLocation is a tag kind, see GraphQL documentation.
|
||||
TagKindLocation TagKind = "Location"
|
||||
|
||||
// TagKindEvent is a tag kind, see GraphQL documentation.
|
||||
TagKindEvent TagKind = "Event"
|
||||
|
||||
// TagKindSeries is a tag kind, see GraphQL documentation.
|
||||
TagKindSeries TagKind = "Series"
|
||||
)
|
||||
|
||||
// UnmarshalGQL unmarshals
|
||||
func (e *TagKind) UnmarshalGQL(v interface{}) error {
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("enums must be strings")
|
||||
}
|
||||
|
||||
*e = TagKind(str)
|
||||
switch *e {
|
||||
case TagKindOrganization, TagKindCharacter, TagKindLocation, TagKindEvent, TagKindSeries:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("%s is not a valid TagKind", str)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalGQL turns it into a JSON string
|
||||
func (e TagKind) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, "\""+string(e), "\"")
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package models
|
||||
|
||||
// A Tag associates a story with other content, like other stories, logs and more.
|
||||
type Tag struct {
|
||||
Kind TagKind `bson:"kind"`
|
||||
Name string `bson:"name"`
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package tags
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/internal/store"
|
||||
"github.com/globalsign/mgo"
|
||||
)
|
||||
|
||||
var storyCollection *mgo.Collection
|
||||
|
||||
func init() {
|
||||
store.HandleInit(func(db *mgo.Database) {
|
||||
storyCollection = db.C("story.stories")
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package tags
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// List lists all tags
|
||||
func List() ([]models.Tag, error) {
|
||||
tags := make([]models.Tag, 0, 64)
|
||||
err := storyCollection.Find(bson.M{"listed": true, "tags": bson.M{"$ne": nil}}).Distinct("tags", &tags)
|
||||
|
||||
sort.Slice(tags, func(i, j int) bool {
|
||||
kindCmp := strings.Compare(string(tags[i].Kind), string(tags[j].Kind))
|
||||
if kindCmp != 0 {
|
||||
return kindCmp < 0
|
||||
}
|
||||
|
||||
return strings.Compare(tags[i].Name, tags[j].Name) < 0
|
||||
})
|
||||
|
||||
return tags, err
|
||||
}
|
||||
Reference in New Issue
Block a user