This commit is contained in:
@@ -8,6 +8,8 @@ import (
|
||||
"runtime/debug"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/internal/loader"
|
||||
"git.aiterp.net/rpdata/api/internal/store"
|
||||
logModel "git.aiterp.net/rpdata/api/model/log"
|
||||
"github.com/99designs/gqlgen/handler"
|
||||
@@ -20,7 +22,15 @@ func main() {
|
||||
}
|
||||
|
||||
http.Handle("/", handler.Playground("RPData API", "/query"))
|
||||
http.Handle("/query", handler.GraphQL(
|
||||
http.Handle("/query", queryHandler())
|
||||
|
||||
go updateCharacters()
|
||||
|
||||
log.Fatal(http.ListenAndServe(":8081", nil))
|
||||
}
|
||||
|
||||
func queryHandler() http.HandlerFunc {
|
||||
handler := handler.GraphQL(
|
||||
graph2.New(),
|
||||
handler.RecoverFunc(func(ctx context.Context, err interface{}) error {
|
||||
// send this panic somewhere
|
||||
@@ -29,11 +39,16 @@ func main() {
|
||||
|
||||
return fmt.Errorf("shit")
|
||||
}),
|
||||
))
|
||||
)
|
||||
|
||||
go updateCharacters()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
l := loader.New()
|
||||
r = r.WithContext(l.ToContext(r.Context()))
|
||||
|
||||
log.Fatal(http.ListenAndServe(":8081", nil))
|
||||
r = auth.RequestWithToken(r)
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func updateCharacters() {
|
||||
|
||||
@@ -23,5 +23,9 @@ models:
|
||||
model: git.aiterp.net/rpdata/api/model/channel.Filter
|
||||
Post:
|
||||
model: git.aiterp.net/rpdata/api/model/log.Post
|
||||
Log:
|
||||
model: git.aiterp.net/rpdata/api/model/log.Log
|
||||
LogsFilter:
|
||||
model: git.aiterp.net/rpdata/api/model/log.Filter
|
||||
Date:
|
||||
model: git.aiterp.net/rpdata/api/model/scalars.Date
|
||||
@@ -0,0 +1,34 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.aiterp.net/rpdata/api/internal/loader"
|
||||
"git.aiterp.net/rpdata/api/model/log"
|
||||
)
|
||||
|
||||
func (r *resolver) Log(ctx context.Context, id string) (log.Log, error) {
|
||||
return log.FindID(id)
|
||||
}
|
||||
|
||||
func (r *resolver) Logs(ctx context.Context, filter *log.Filter) ([]log.Log, error) {
|
||||
logs, err := log.List(filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(logs) >= 100 {
|
||||
loader := loader.FromContext(ctx)
|
||||
if loader == nil {
|
||||
return nil, errors.New("no loader")
|
||||
}
|
||||
|
||||
for _, log := range logs {
|
||||
loader.PrimeCharacters("id", log.CharacterIDs...)
|
||||
loader.PrimeChannels("name", log.ChannelName)
|
||||
}
|
||||
}
|
||||
|
||||
return logs, nil
|
||||
}
|
||||
@@ -25,9 +25,17 @@ type Query {
|
||||
posts(ids: [String!]!): [Post!]!
|
||||
|
||||
|
||||
# Find log by ID
|
||||
log(id: String!): Log!
|
||||
|
||||
# Find logs
|
||||
logs(filter: LogsFilter): [Log!]!
|
||||
|
||||
|
||||
# Find all distinct tags used in stories
|
||||
tags: [Tag!]!
|
||||
}
|
||||
|
||||
# A Date represents a RFC3339 encoded date with up to millisecond precision.
|
||||
scalar Date
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# A Log is the "file" of an RP session
|
||||
type Log {
|
||||
# A unique identifier for the log.
|
||||
id: String!
|
||||
|
||||
# A secondary unique identifier for the log. This is a lot shorter and more suitable for storage when
|
||||
# the link doesn't need to be as expressive.
|
||||
shortId: String!
|
||||
|
||||
# The date for a log.
|
||||
date: Date!
|
||||
|
||||
# The channel of a log.
|
||||
channelName: String!
|
||||
|
||||
# Information about the channel this log is in.
|
||||
channel: Channel!
|
||||
|
||||
# The session's title.
|
||||
title: String!
|
||||
|
||||
# The log's event, which is the same as the tags in the previous logbot site.
|
||||
# Empty string means that it's no event.
|
||||
event: String!
|
||||
|
||||
# The description of a session, which is empty if unset.
|
||||
description: String!
|
||||
|
||||
# Whether the log session is open.
|
||||
open: Boolean!
|
||||
|
||||
# The characters involved in the log file.
|
||||
characters: [Character!]!
|
||||
|
||||
# The posts of the logfile, which can be filtered by kinds.
|
||||
posts(kinds:[String!]): [Post!]!
|
||||
}
|
||||
|
||||
# Filter for logs query
|
||||
input LogsFilter {
|
||||
# Channels to limit results to (inclusive)
|
||||
channels: [String!]
|
||||
|
||||
# Events to limit results to (inclusive)
|
||||
events: [String!]
|
||||
|
||||
# Characters to limit results to (exclusive)
|
||||
characters: [String!]
|
||||
|
||||
# Search post content
|
||||
search: String
|
||||
|
||||
# Limit by whether it's open or not
|
||||
open: Boolean
|
||||
|
||||
# Limit the amount of results you get back
|
||||
limit: Int
|
||||
}
|
||||
|
||||
# Input for addLog mutation
|
||||
input LogAddInput {
|
||||
# The date of the log.
|
||||
date: Date!
|
||||
|
||||
# The channel where the log is set
|
||||
channel: String!
|
||||
|
||||
# Optional: The log title
|
||||
title: String
|
||||
|
||||
# Optional: Whether the log is open
|
||||
open: Boolean
|
||||
|
||||
# Optional: The log event name
|
||||
event: String
|
||||
|
||||
# Optional: A short description of the log
|
||||
description: String
|
||||
}
|
||||
|
||||
# Input for addLog mutation
|
||||
input LogEditInput {
|
||||
# The id of the log
|
||||
id: String!
|
||||
|
||||
# The log title
|
||||
title: String
|
||||
|
||||
# The log event name
|
||||
event: String
|
||||
|
||||
# A short description of the log
|
||||
description: String
|
||||
|
||||
# Open/close the log
|
||||
open: Boolean
|
||||
}
|
||||
+1
-22
@@ -7,26 +7,5 @@ type Filter struct {
|
||||
Channels *[]string
|
||||
Events *[]string
|
||||
Open *bool
|
||||
Limit *int32
|
||||
}
|
||||
|
||||
// NewFilter makes a new filter
|
||||
func NewFilter() *Filter {
|
||||
return &Filter{}
|
||||
}
|
||||
|
||||
// WithLimit adds a max amount of results to be returned.
|
||||
func (filter *Filter) WithLimit(limit int) *Filter {
|
||||
limitPtr := int32(limit)
|
||||
filter.Limit = &limitPtr
|
||||
|
||||
return filter
|
||||
}
|
||||
|
||||
// WithOpen filters on whether a log is open.
|
||||
func (filter *Filter) WithOpen(limit int) *Filter {
|
||||
limitPtr := int32(limit)
|
||||
filter.Limit = &limitPtr
|
||||
|
||||
return filter
|
||||
Limit int
|
||||
}
|
||||
|
||||
+52
-40
@@ -31,7 +31,7 @@ type Log struct {
|
||||
ID string `bson:"_id"`
|
||||
ShortID string `bson:"shortId"`
|
||||
Date time.Time `bson:"date"`
|
||||
Channel string `bson:"channel"`
|
||||
ChannelName string `bson:"channel"`
|
||||
Title string `bson:"title,omitempty"`
|
||||
Event string `bson:"event,omitempty"`
|
||||
Description string `bson:"description,omitempty"`
|
||||
@@ -55,7 +55,7 @@ func New(date time.Time, channelName, title, event, description string, open boo
|
||||
ID: MakeLogID(date, channelName),
|
||||
ShortID: "L" + strconv.Itoa(nextID),
|
||||
Date: date,
|
||||
Channel: channelName,
|
||||
ChannelName: channelName,
|
||||
Title: title,
|
||||
Event: event,
|
||||
Description: description,
|
||||
@@ -84,43 +84,44 @@ func FindID(id string) (Log, error) {
|
||||
// List lists all logs
|
||||
func List(filter *Filter) ([]Log, error) {
|
||||
query := bson.M{}
|
||||
|
||||
// Run a text search
|
||||
if filter.Search != nil {
|
||||
searchResults := make([]string, 0, 32)
|
||||
|
||||
postMutex.RLock()
|
||||
err := postCollection.Find(bson.M{"$text": bson.M{"$search": *filter.Search}}).Distinct("logId", &searchResults)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postMutex.RUnlock()
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
limit := 0
|
||||
if filter.Limit != nil {
|
||||
limit = int(*filter.Limit)
|
||||
|
||||
if filter != nil {
|
||||
// Run a text search
|
||||
if filter.Search != nil {
|
||||
searchResults := make([]string, 0, 32)
|
||||
|
||||
postMutex.RLock()
|
||||
err := postCollection.Find(bson.M{"$text": bson.M{"$search": *filter.Search}}).Distinct("logId", &searchResults)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postMutex.RUnlock()
|
||||
|
||||
// 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 listLog(query, limit)
|
||||
@@ -168,9 +169,20 @@ func (log *Log) Edit(title *string, event *string, description *string, open *bo
|
||||
return nil
|
||||
}
|
||||
|
||||
// Characters get all the characters for the character IDs stored in the
|
||||
// log file.
|
||||
func (log *Log) Characters() ([]character.Character, error) {
|
||||
return character.ListIDs(log.CharacterIDs...)
|
||||
}
|
||||
|
||||
// Channel gets the channel.
|
||||
func (log *Log) Channel() (channel.Channel, error) {
|
||||
return channel.FindName(log.ChannelName)
|
||||
}
|
||||
|
||||
// Posts gets all the posts under the log. If no kinds are specified, it
|
||||
// will get all posts
|
||||
func (log *Log) Posts(kinds ...string) ([]Post, error) {
|
||||
func (log *Log) Posts(kinds []string) ([]Post, error) {
|
||||
postMutex.RLock()
|
||||
defer postMutex.RUnlock()
|
||||
|
||||
@@ -238,7 +250,7 @@ func (log *Log) UpdateCharacters() error {
|
||||
characterUpdateMutex.Lock()
|
||||
defer characterUpdateMutex.Unlock()
|
||||
|
||||
posts, err := log.Posts()
|
||||
posts, err := log.Posts([]string{"action", "text", "chars"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user