Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
947765884e | ||
|
|
ffec008820 | ||
|
|
138b3e3eab | ||
|
|
929abfdbe4 | ||
|
|
a8cd595876 | ||
|
|
9ed3b32b42 | ||
|
|
6bae52d652 | ||
|
|
cee370c2ac | ||
|
|
9affdbd20e | ||
|
|
cf545cde3b | ||
|
|
b414cf118f | ||
|
|
4979b02104 | ||
|
|
b7d5059d60 | ||
|
|
9fbdc767ad | ||
|
|
daeaaf5fa9 | ||
|
|
d3277c7476 | ||
|
|
90681c67b0 | ||
|
|
bebd99833b | ||
|
|
34f86d5037 | ||
|
|
8a85313762 | ||
|
|
017e68eae7 | ||
|
|
1955ad0517 | ||
|
|
34ba5d5d3a | ||
|
|
8c8a251080 | ||
|
|
73fe125870 | ||
|
|
04ec85aadf | ||
|
|
59233ee549 | ||
|
|
7aa0de9135 | ||
|
|
6dfbee7ff2 | ||
|
|
8a07c2ffdb | ||
|
|
0e9536b0a8 | ||
|
|
b8e5ed5813 | ||
|
|
2317f66920 | ||
|
|
fc488b938d | ||
|
|
ceb2617571 | ||
|
|
aeb5b26627 | ||
|
|
6aafc67790 | ||
|
|
c6f8fd9faa | ||
|
|
efa98b80cc | ||
|
|
707dcb43eb | ||
|
|
9bcc28a0ea | ||
|
|
2fceaa62ed | ||
|
|
86125c7ce9 | ||
|
|
bb28795cd5 | ||
|
|
815f30597e | ||
|
|
cd1f122502 | ||
|
|
0e0d802a32 | ||
|
|
3c42043ab6 | ||
|
|
8388ee2446 | ||
|
|
260c2e7f76 | ||
|
|
a4034b0faa | ||
|
|
c3a6798050 | ||
|
|
2ab933149e | ||
|
|
07b94b3cab | ||
|
|
79171bf9a2 | ||
|
|
bac57bc378 | ||
|
|
875dac9ecb | ||
|
|
0768cfd0bd | ||
|
|
2b05d90f4a | ||
|
|
0444911e73 | ||
|
|
1be4088a8f | ||
|
|
9978d7380b | ||
|
|
2e5162a29b | ||
|
|
dac0060155 | ||
|
|
9d7fd498a9 | ||
|
|
e0af2685ee | ||
|
|
3184b60310 | ||
|
|
675c09ef04 | ||
|
|
9707320960 | ||
|
|
20e53b4f5e | ||
|
|
8bb4dea358 | ||
|
|
75b2382f09 | ||
|
|
1ca25eff8e | ||
|
|
bf10ed1fe3 | ||
|
|
54136be912 | ||
|
|
228c2bfeb4 | ||
|
|
2f98be5747 | ||
|
|
2a40f97282 | ||
|
|
e5b4184106 | ||
|
|
c348a90b70 | ||
|
|
132cf28f0f | ||
|
|
d5df624188 | ||
|
|
ca98648274 | ||
|
|
4642a8abec | ||
|
|
0ec923d686 | ||
|
|
388d5378e7 | ||
|
|
67e9e8f1e6 | ||
|
|
06bc7e5a1b | ||
|
|
237190e498 | ||
|
|
b9f0fef966 | ||
|
|
ba1c1e0a4b | ||
|
|
18e77b8205 | ||
|
|
d8871259a1 | ||
|
|
26d7e36631 | ||
|
|
51489ed901 |
+4
-4
@@ -6,16 +6,16 @@ pipeline:
|
|||||||
docker-release:
|
docker-release:
|
||||||
image: plugins/docker
|
image: plugins/docker
|
||||||
repo: vmaple/rpdata
|
repo: vmaple/rpdata
|
||||||
tags: latest
|
|
||||||
auto_tag: true
|
auto_tag: true
|
||||||
secrets: [ docker_username, docker_password ]
|
secrets: [ docker_username, docker_password ]
|
||||||
when:
|
when:
|
||||||
event: tag
|
event: tag
|
||||||
ref: refs/tags/*
|
ref: refs/tags/*
|
||||||
docker-dev:
|
docker-release-latest:
|
||||||
image: plugins/docker
|
image: plugins/docker
|
||||||
repo: vmaple/rpdata
|
repo: vmaple/rpdata
|
||||||
tags: trunk
|
tags: latest
|
||||||
secrets: [ docker_username, docker_password ]
|
secrets: [ docker_username, docker_password ]
|
||||||
when:
|
when:
|
||||||
event: push
|
event: tag
|
||||||
|
ref: refs/tags/*
|
||||||
+7
-1
@@ -1,7 +1,13 @@
|
|||||||
vendor
|
vendor
|
||||||
schema/bindata.go
|
graphql/schema/bindata.go
|
||||||
config.json
|
config.json
|
||||||
api
|
api
|
||||||
debug
|
debug
|
||||||
build
|
build
|
||||||
|
rpdata-graphiql
|
||||||
|
rpdata-*
|
||||||
|
!rpdata-*/
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
generated.gql
|
||||||
|
generated.go
|
||||||
+9
-22
@@ -1,41 +1,29 @@
|
|||||||
## 1. Server
|
## 1. Build Server
|
||||||
# Use Go 1.10
|
# Use Go 1.10
|
||||||
FROM golang:1.10 AS build-server
|
FROM golang:1.11 AS build-server
|
||||||
|
|
||||||
# Load repository into docker
|
# Load repository into docker
|
||||||
WORKDIR /go/src/git.aiterp.net/rpdata/api/
|
WORKDIR /go/src/git.aiterp.net/rpdata/api/
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN rm -rf ./vendor
|
||||||
|
|
||||||
# Load build tools and dependencies
|
# Load build tools and dependencies
|
||||||
RUN go get -u github.com/golang/dep/cmd/dep
|
RUN go get -u github.com/golang/dep/cmd/dep
|
||||||
|
RUN go get -u github.com/vektah/gorunpkg
|
||||||
RUN go get -u github.com/jteeuwen/go-bindata/...
|
RUN go get -u github.com/jteeuwen/go-bindata/...
|
||||||
RUN dep ensure
|
RUN dep ensure
|
||||||
RUN go generate ./...
|
RUN go generate ./...
|
||||||
|
|
||||||
# Build server and tools (CGO disabled to make them 100% static)
|
# Build server and tools (CGO disabled to make them 100% static)
|
||||||
ENV CGO_ENABLED 0
|
ENV CGO_ENABLED 0
|
||||||
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-graphiql ./cmd/rpdata-graphiql
|
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-server ./cmd/rpdata-server
|
||||||
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-lb2charimport ./cmd/rpdata-lb2charimport
|
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-lb2charimport ./cmd/rpdata-lb2charimport
|
||||||
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-lb2logimport ./cmd/rpdata-lb2logimport
|
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-lb2logimport ./cmd/rpdata-lb2logimport
|
||||||
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-wikifileimport ./cmd/rpdata-wikifileimport
|
# TODO: RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-wikifileimport ./cmd/rpdata-wikifileimport
|
||||||
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-ensurechannels ./cmd/rpdata-ensurechannels
|
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-ensurechannels ./cmd/rpdata-ensurechannels
|
||||||
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-as2storyimport ./cmd/rpdata-as2storyimport
|
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-as2storyimport ./cmd/rpdata-as2storyimport
|
||||||
|
|
||||||
## 2. React UI
|
## 2. Distribute
|
||||||
# Use Node.JS 18
|
|
||||||
FROM node:10.5-alpine AS build-id
|
|
||||||
|
|
||||||
# The content is already there
|
|
||||||
WORKDIR /rpdata-ui
|
|
||||||
COPY ./rpdata-ui /rpdata-ui
|
|
||||||
|
|
||||||
# Prepare dependencies
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
# Run build
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
## 3. Regroup
|
|
||||||
# Use alpine linux
|
# Use alpine linux
|
||||||
FROM alpine:3.7
|
FROM alpine:3.7
|
||||||
|
|
||||||
@@ -44,7 +32,6 @@ RUN apk add --no-cache ca-certificates
|
|||||||
|
|
||||||
# Copy build files into final container
|
# Copy build files into final container
|
||||||
COPY --from=build-server /binaries/* /usr/local/bin/
|
COPY --from=build-server /binaries/* /usr/local/bin/
|
||||||
COPY --from=build-id /rpdata-ui/build /var/www/
|
|
||||||
|
|
||||||
# TODO: Use proper server instead of grapihql server
|
# The server is the main entry point
|
||||||
CMD ["/usr/local/bin/rpdata-graphiql"]
|
CMD ["/usr/local/bin/rpdata-server"]
|
||||||
|
|||||||
Generated
+83
-7
@@ -2,10 +2,32 @@
|
|||||||
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
name = "github.com/99designs/gqlgen"
|
||||||
name = "git.aiterp.net/aiterp/wikiauth"
|
packages = [
|
||||||
|
".",
|
||||||
|
"cmd",
|
||||||
|
"codegen",
|
||||||
|
"codegen/templates",
|
||||||
|
"complexity",
|
||||||
|
"graphql",
|
||||||
|
"graphql/introspection",
|
||||||
|
"handler",
|
||||||
|
"internal/gopath"
|
||||||
|
]
|
||||||
|
revision = "636435b68700211441303f1a5ed92f3768ba5774"
|
||||||
|
version = "v0.5.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/agnivade/levenshtein"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "33860de804ddcec4fc17998745233b4ec477e7c2"
|
revision = "3d21ba515fe27b856f230847e856431ae1724adc"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/dgrijalva/jwt-go"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
|
||||||
|
version = "v3.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -37,6 +59,12 @@
|
|||||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
||||||
version = "v1.4.0"
|
version = "v1.4.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/gorilla/websocket"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "66b9c49e59c6c48f0ffce28c2d8b8a5678502c6d"
|
||||||
|
version = "v1.4.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/graph-gophers/dataloader"
|
name = "github.com/graph-gophers/dataloader"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
@@ -64,6 +92,15 @@
|
|||||||
]
|
]
|
||||||
revision = "9ebf33af539ab8cb832c7107bc0a978ca8dbc0de"
|
revision = "9ebf33af539ab8cb832c7107bc0a978ca8dbc0de"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/hashicorp/golang-lru"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"simplelru"
|
||||||
|
]
|
||||||
|
revision = "20f1fb78b0740ba8c3cb143a61e86ba5c8669768"
|
||||||
|
version = "v0.5.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/jmoiron/sqlx"
|
name = "github.com/jmoiron/sqlx"
|
||||||
@@ -103,10 +140,10 @@
|
|||||||
version = "v1.0.2"
|
version = "v1.0.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/sadbox/mediawiki"
|
name = "github.com/pkg/errors"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "39fea8a1336076a961a300d1d95765dcd17e8a3c"
|
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||||
version = "v0.1"
|
version = "v0.8.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/sirupsen/logrus"
|
name = "github.com/sirupsen/logrus"
|
||||||
@@ -114,6 +151,26 @@
|
|||||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||||
version = "v1.0.5"
|
version = "v1.0.5"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/urfave/cli"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
|
||||||
|
version = "v1.20.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/vektah/gqlparser"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"ast",
|
||||||
|
"gqlerror",
|
||||||
|
"lexer",
|
||||||
|
"parser",
|
||||||
|
"validator",
|
||||||
|
"validator/rules"
|
||||||
|
]
|
||||||
|
revision = "14e83ae06ec152e6d0afb9766a00e0c0918aa8fc"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
@@ -164,15 +221,34 @@
|
|||||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||||
version = "v0.3.0"
|
version = "v0.3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/tools"
|
||||||
|
packages = [
|
||||||
|
"go/ast/astutil",
|
||||||
|
"go/buildutil",
|
||||||
|
"go/internal/cgo",
|
||||||
|
"go/loader",
|
||||||
|
"imports",
|
||||||
|
"internal/fastwalk"
|
||||||
|
]
|
||||||
|
revision = "677d2ff680c188ddb7dcd2bfa6bc7d3f2f2f75b2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "google.golang.org/appengine"
|
name = "google.golang.org/appengine"
|
||||||
packages = ["cloudsql"]
|
packages = ["cloudsql"]
|
||||||
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
|
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "gopkg.in/yaml.v2"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||||
|
version = "v2.2.1"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "16fd84401bc5796ffeaa895f31d099e1a23b363b15b87386877de0829ac9575b"
|
inputs-digest = "3c9430afa8b9260026925c8f496af934e2e573a2bd4587bb634fd12a20ce6c2c"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
# go-tests = true
|
# go-tests = true
|
||||||
# unused-packages = true
|
# unused-packages = true
|
||||||
|
|
||||||
|
required = [ "github.com/99designs/gqlgen" ]
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/globalsign/mgo"
|
name = "github.com/globalsign/mgo"
|
||||||
|
|||||||
@@ -1,18 +1,5 @@
|
|||||||
# RPData API
|
# RPData API
|
||||||
|
|
||||||
Project RPData aims to centralize the AiteRP applications, and partially involve the wiki, into a common API. This will allow for easy linking and inlining between them. The primary consumers of this API will be the Logbot and the upcoming RPData website.
|
Project RPData aims to centralize the AiteRP applications, and partially involve the wiki into a common API. This will allow for easy linking and inlining between them. The primary consumers of this API will be the Logbot and the upcoming RPData website.
|
||||||
|
|
||||||
## Progress
|
There is some renovation going on, and the packages `model` and `graphql` are going to be superceded by `models` and `graph2`
|
||||||
|
|
||||||
### Complete
|
|
||||||
* Session
|
|
||||||
* Character
|
|
||||||
* Log
|
|
||||||
* Post
|
|
||||||
* File
|
|
||||||
|
|
||||||
### Remaining
|
|
||||||
* Story
|
|
||||||
|
|
||||||
### Future
|
|
||||||
* User (manual DB edits will suffice for now)
|
|
||||||
@@ -8,7 +8,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/internal/store"
|
"git.aiterp.net/rpdata/api/internal/store"
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/chapters"
|
||||||
|
"git.aiterp.net/rpdata/api/models/stories"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
)
|
)
|
||||||
@@ -71,14 +73,20 @@ func main() {
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tags := make([]story.Tag, 0, 8)
|
tags := make([]models.Tag, 0, 8)
|
||||||
for _, tagResult := range tagResults {
|
for _, tagResult := range tagResults {
|
||||||
if tagResult.PageID == result.ID {
|
if tagResult.PageID == result.ID {
|
||||||
tags = append(tags, story.Tag{Kind: tagResult.Type, Name: tagResult.Name})
|
tags = append(tags, models.Tag{Kind: models.TagKind(tagResult.Type), Name: tagResult.Name})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
story, err := story.New(result.Name, result.Author[5:], result.Category, false, false, tags, publishDate, fictionalDate)
|
category := models.StoryCategory(result.Category)
|
||||||
|
if !category.IsValid() {
|
||||||
|
log.Println(result.Name, "does not have a valid category:", result.Category)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err := stories.Add(result.Name, result.Author[5:], category, true, false, tags, publishDate, fictionalDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
@@ -96,19 +104,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chapter, err := story.AddChapter(title, result.Author[5:], result.Source, publishDate, fictionalDate)
|
chapter, err := chapters.Add(story, title, result.Author[5:], result.Source, publishDate, &fictionalDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.Unlisted {
|
|
||||||
listed := true
|
|
||||||
err := story.Edit(nil, nil, &listed, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(result.ID, "->", story.ID, chapter.ID)
|
fmt.Println(result.ID, "->", story.ID, chapter.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/model/channel"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/internal/store"
|
"git.aiterp.net/rpdata/api/internal/store"
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
"git.aiterp.net/rpdata/api/models/channels"
|
||||||
|
"git.aiterp.net/rpdata/api/models/logs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -17,7 +16,7 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logs, err := log.List(32768)
|
logs, err := logs.List(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
return
|
return
|
||||||
@@ -25,18 +24,18 @@ func main() {
|
|||||||
|
|
||||||
added := make(map[string]bool, 1024)
|
added := make(map[string]bool, 1024)
|
||||||
for _, log := range logs {
|
for _, log := range logs {
|
||||||
if added[log.Channel] {
|
if added[log.ChannelName] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := channel.Ensure(log.Channel, false)
|
_, err := channels.Ensure(log.ChannelName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, log.ID, err)
|
fmt.Fprintln(os.Stderr, log.ID, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
added[log.Channel] = true
|
added[log.ChannelName] = true
|
||||||
|
|
||||||
fmt.Println(log.Channel, "ensured")
|
fmt.Println(log.ChannelName, "ensured")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
config.json
|
|
||||||
debug
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/loader"
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver"
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/schema"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/store"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/file"
|
|
||||||
logModel "git.aiterp.net/rpdata/api/model/log"
|
|
||||||
graphql "github.com/graph-gophers/graphql-go"
|
|
||||||
"github.com/graph-gophers/graphql-go/relay"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
err := store.Init()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Failed to init store:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := logModel.UpdateAllCharacters()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Charcter updated stopped:", err)
|
|
||||||
}
|
|
||||||
log.Println("Updated characters on", n, "logs")
|
|
||||||
|
|
||||||
schema, err := graphql.ParseSchema(schema.String(), &resolver.Resolver{}, graphql.MaxParallelism(48))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Failed to parse schema:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
|
||||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Write(page)
|
|
||||||
}))
|
|
||||||
|
|
||||||
relayHandler := &relay.Handler{Schema: schema}
|
|
||||||
http.HandleFunc("/graphql", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
r = session.Load(w, r)
|
|
||||||
|
|
||||||
l := loader.New()
|
|
||||||
r = r.WithContext(l.ToContext(r.Context()))
|
|
||||||
|
|
||||||
relayHandler.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
|
|
||||||
http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
r = session.Load(w, r)
|
|
||||||
sess := session.FromContext(r.Context())
|
|
||||||
user := sess.User()
|
|
||||||
if user == nil || !user.Permitted("file.upload") {
|
|
||||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := r.ParseMultipartForm(16384); err != nil {
|
|
||||||
http.Error(w, "Internal (1): "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
formFile, header, err := r.FormFile("file")
|
|
||||||
if err != nil || header == nil || formFile == nil {
|
|
||||||
http.Error(w, "No file provided", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := file.Upload(r.Context(), header.Filename, header.Header.Get("Content-Type"), user.ID, header.Size, formFile)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Internal (2): "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
json, err := json.Marshal(file)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Internal (3): "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(json)
|
|
||||||
})
|
|
||||||
|
|
||||||
change.InitializeTimeline()
|
|
||||||
go func() {
|
|
||||||
index := int64(0)
|
|
||||||
|
|
||||||
for {
|
|
||||||
index++
|
|
||||||
ch, err := change.Timeline.Get(context.Background(), index)
|
|
||||||
if err == change.ErrExpired {
|
|
||||||
continue
|
|
||||||
} else if err != nil {
|
|
||||||
log.Println("Timeline:", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Change: time=%s model=%s op=%s id=%s author=%s\n", ch.Time.Local().Format("[Mon Jan 02 15:04 MST]"), ch.Model, ch.Op, ch.ObjectID, ch.Author)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(":17000", nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
var page = []byte(`
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/graphiql/0.10.2/graphiql.css" />
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/1.1.0/fetch.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/graphiql/0.10.2/graphiql.js"></script>
|
|
||||||
</head>
|
|
||||||
<body style="width: 100%; height: 100%; margin: 0; overflow: hidden;">
|
|
||||||
<div id="graphiql" style="height: 100vh;">Loading...</div>
|
|
||||||
<script>
|
|
||||||
function graphQLFetcher(graphQLParams) {
|
|
||||||
return fetch("/graphql", {
|
|
||||||
method: "post",
|
|
||||||
body: JSON.stringify(graphQLParams),
|
|
||||||
credentials: "include",
|
|
||||||
}).then(function (response) {
|
|
||||||
return response.text();
|
|
||||||
}).then(function (responseBody) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(responseBody);
|
|
||||||
} catch (error) {
|
|
||||||
return responseBody;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
ReactDOM.render(
|
|
||||||
React.createElement(GraphiQL, {fetcher: graphQLFetcher}),
|
|
||||||
document.getElementById("graphiql")
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`)
|
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/internal/store"
|
"git.aiterp.net/rpdata/api/internal/store"
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
"git.aiterp.net/rpdata/api/models/characters"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fileName = flag.String("file", "./characters.json", "json file to load")
|
var fileName = flag.String("file", "./characters.json", "json file to load")
|
||||||
@@ -31,12 +31,12 @@ func main() {
|
|||||||
nicksAdded, nicksFailed := 0, 0
|
nicksAdded, nicksFailed := 0, 0
|
||||||
|
|
||||||
for _, info := range infos {
|
for _, info := range infos {
|
||||||
char, err := character.New(info.Nicks[0], info.Name, info.ShortName, info.Author, "")
|
char, err := characters.Add(info.Nicks[0], info.Name, info.ShortName, info.Author, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(info.Nicks[0], "failed to insert:", err)
|
log.Println(info.Nicks[0], "failed to insert:", err)
|
||||||
charsFailed++
|
charsFailed++
|
||||||
|
|
||||||
char, err = character.FindNick(info.Nicks[0])
|
char, err = characters.FindNick(info.Nicks[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, alt := range info.Nicks[1:] {
|
for _, alt := range info.Nicks[1:] {
|
||||||
err := char.AddNick(alt)
|
char, err = characters.AddNick(char, alt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(info.Nicks[0], "failed to add nick", alt, "error:", err)
|
log.Println(info.Nicks[0], "failed to add nick", alt, "error:", err)
|
||||||
nicksFailed++
|
nicksFailed++
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/posts"
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/internal/store"
|
"git.aiterp.net/rpdata/api/internal/store"
|
||||||
logModel "git.aiterp.net/rpdata/api/model/log"
|
"git.aiterp.net/rpdata/api/models/logs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var prefixReplacer = strings.NewReplacer("+", "", "@", "", "!", "", "%", "")
|
var prefixReplacer = strings.NewReplacer("+", "", "@", "", "!", "", "%", "")
|
||||||
@@ -47,13 +49,13 @@ func main() {
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
l, err := logModel.New(date, channel, title, event, "", false)
|
l, err := logs.Add(date, channel, title, event, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = l.NewPost(time.Now(), "annotation.info", "rpdata-lb2logimport", "This logfile is imported from aitelogs2 and may contain errors or wrong timestamps.")
|
_, err = posts.Add(l, time.Now(), "annotation.info", "rpdata-lb2logimport", "This logfile is imported from aitelogs2 and may contain errors or wrong timestamps.")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
@@ -63,7 +65,7 @@ func main() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = l.NewPost(l.Date, "chars", prefixReplacer.Replace(line.Args[0]), line.Text)
|
_, err = posts.Add(l, l.Date, "chars", prefixReplacer.Replace(line.Args[0]), line.Text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
@@ -92,13 +94,13 @@ func main() {
|
|||||||
line.Verb = "SCENE"
|
line.Verb = "SCENE"
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = l.NewPost(postTime, strings.ToLower(line.Verb), prefixReplacer.Replace(line.Args[0]), line.Text)
|
_, err = posts.Add(l, postTime, strings.ToLower(line.Verb), prefixReplacer.Replace(line.Args[0]), line.Text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = l.UpdateCharacters()
|
l, err = logs.UpdateCharacters(l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/logs"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
"github.com/99designs/gqlgen/handler"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := store.Init()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Failed to init store:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Handle("/", handler.Playground("RPData API", "/graphql"))
|
||||||
|
http.Handle("/graphql", queryHandler())
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := logs.RunFullUpdate()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Characters updated")
|
||||||
|
}()
|
||||||
|
|
||||||
|
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
|
||||||
|
log.Println(err)
|
||||||
|
log.Println(string(debug.Stack()))
|
||||||
|
|
||||||
|
return fmt.Errorf("shit")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := loader.New()
|
||||||
|
r = r.WithContext(l.ToContext(r.Context()))
|
||||||
|
|
||||||
|
// >_>
|
||||||
|
if strings.HasPrefix(r.Header.Get("Authorization"), "Bearer of the curse") {
|
||||||
|
w.Header().Set("X-Emerald-Herald", "Seek souls. Larger, more powerful souls.")
|
||||||
|
w.Header().Add("X-Emerald-Herald", "Seek the king, that is the only way.")
|
||||||
|
w.Header().Add("X-Emerald-Herald", "Lest this land swallow you whole... As it has so many others.")
|
||||||
|
}
|
||||||
|
|
||||||
|
r = auth.RequestWithToken(r)
|
||||||
|
|
||||||
|
handler.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
"git.aiterp.net/rpdata/api/internal/config"
|
"git.aiterp.net/rpdata/api/internal/config"
|
||||||
"git.aiterp.net/rpdata/api/internal/store"
|
"git.aiterp.net/rpdata/api/internal/store"
|
||||||
"git.aiterp.net/rpdata/api/model/file"
|
"git.aiterp.net/rpdata/api/models/files"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -33,7 +33,7 @@ func main() {
|
|||||||
store.Init()
|
store.Init()
|
||||||
|
|
||||||
for _, info := range data.Query.Allimages {
|
for _, info := range data.Query.Allimages {
|
||||||
existing, err := file.FindName("wiki", info.Name, info.User)
|
existing, err := files.FindName("wiki", info.Name, info.User)
|
||||||
if err == nil && existing.ID != "" {
|
if err == nil && existing.ID != "" {
|
||||||
log.Println("Skipping", info.Name, "because it already exists")
|
log.Println("Skipping", info.Name, "because it already exists")
|
||||||
continue
|
continue
|
||||||
@@ -45,7 +45,7 @@ func main() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := file.Insert(info.Name, "wiki", info.Mime, info.User, ts, info.Size, info.URL)
|
file, err := files.Insert(info.Name, "wiki", info.Mime, info.User, ts, info.Size, info.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Skipping", info.Name, "error:", err)
|
log.Println("Skipping", info.Name, "error:", err)
|
||||||
continue
|
continue
|
||||||
|
|||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "# Generated by stiching together the files under schema/ – DO NOT EDIT" >generated.gql
|
||||||
|
cat schema/root.gql schema/**/*.gql >>generated.gql
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
schema: generated.gql
|
||||||
|
|
||||||
|
exec:
|
||||||
|
filename: generated.go
|
||||||
|
package: graph2
|
||||||
|
|
||||||
|
model:
|
||||||
|
filename: input/generated.go
|
||||||
|
package: input
|
||||||
|
|
||||||
|
models:
|
||||||
|
Tag:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Tag
|
||||||
|
TagInput: #It's the same as tags
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Tag
|
||||||
|
TagKind:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.TagKind
|
||||||
|
Character:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Character
|
||||||
|
CharactersFilter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models/characters.Filter
|
||||||
|
Channel:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Channel
|
||||||
|
ChannelsFilter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models/channels.Filter
|
||||||
|
Post:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Post
|
||||||
|
PostsFilter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models/posts.Filter
|
||||||
|
Log:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Log
|
||||||
|
LogsFilter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models/logs.Filter
|
||||||
|
Chapter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Chapter
|
||||||
|
fields:
|
||||||
|
fictionalDate:
|
||||||
|
resolver: true
|
||||||
|
Story:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Story
|
||||||
|
fields:
|
||||||
|
fictionalDate:
|
||||||
|
resolver: true
|
||||||
|
StoryCategory:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.StoryCategory
|
||||||
|
StoriesFilter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models/stories.Filter
|
||||||
|
File:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.File
|
||||||
|
FilesFilter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models/files.Filter
|
||||||
|
Change:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Change
|
||||||
|
ChangeModel:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.ChangeModel
|
||||||
|
ChangeKey:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.ChangeKey
|
||||||
|
ChangeKeyInput: # It's the same as ChangeKey
|
||||||
|
model: git.aiterp.net/rpdata/api/models.ChangeKey
|
||||||
|
ChangesFilter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models/changes.Filter
|
||||||
|
Token:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Token
|
||||||
|
User:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.User
|
||||||
|
Date:
|
||||||
|
model: git.aiterp.net/rpdata/api/models/scalars.Date
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package graph2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/queries"
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/types"
|
||||||
|
graphql "github.com/99designs/gqlgen/graphql"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate ./combine.sh
|
||||||
|
//go:generate gorunpkg github.com/99designs/gqlgen -v
|
||||||
|
|
||||||
|
// New creates a new GraphQL schema.
|
||||||
|
func New() graphql.ExecutableSchema {
|
||||||
|
return NewExecutableSchema(Config{
|
||||||
|
Resolvers: &rootResolver{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type rootResolver struct{}
|
||||||
|
|
||||||
|
func (r *rootResolver) Query() QueryResolver {
|
||||||
|
return &queries.Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Mutation() MutationResolver {
|
||||||
|
return queries.MutationResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Log() LogResolver {
|
||||||
|
return &types.LogResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Chapter() ChapterResolver {
|
||||||
|
return &types.ChapterResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Story() StoryResolver {
|
||||||
|
return &types.StoryResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) File() FileResolver {
|
||||||
|
return &types.FileResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Change() ChangeResolver {
|
||||||
|
return &types.ChangeResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Token() TokenResolver {
|
||||||
|
return &types.TokenResolver
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
)
|
||||||
|
|
||||||
|
/// Queries
|
||||||
|
|
||||||
|
func (r *resolver) Changes(ctx context.Context, filter *changes.Filter) ([]models.Change, error) {
|
||||||
|
return changes.List(filter)
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
"git.aiterp.net/rpdata/api/internal/auth"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
"git.aiterp.net/rpdata/api/models/channels"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Queries
|
||||||
|
|
||||||
|
func (r *resolver) Channel(ctx context.Context, name string) (models.Channel, error) {
|
||||||
|
return channels.FindName(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) Channels(ctx context.Context, filter *channels.Filter) ([]models.Channel, error) {
|
||||||
|
return channels.List(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutations
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddChannel(ctx context.Context, input input.ChannelAddInput) (models.Channel, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("channel.add") {
|
||||||
|
return models.Channel{}, errors.New("You are not permitted to add channels")
|
||||||
|
}
|
||||||
|
|
||||||
|
logged := false
|
||||||
|
if input.Logged != nil {
|
||||||
|
logged = *input.Logged
|
||||||
|
}
|
||||||
|
hub := false
|
||||||
|
if input.Hub != nil {
|
||||||
|
hub = *input.Hub
|
||||||
|
}
|
||||||
|
eventName := ""
|
||||||
|
if input.EventName != nil {
|
||||||
|
eventName = *input.EventName
|
||||||
|
}
|
||||||
|
locationName := ""
|
||||||
|
if input.LocationName != nil {
|
||||||
|
locationName = *input.LocationName
|
||||||
|
}
|
||||||
|
|
||||||
|
channel, err := channels.Add(input.Name, logged, hub, eventName, locationName)
|
||||||
|
if err != nil {
|
||||||
|
return models.Channel{}, errors.New("Failed to add channel: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Channel", "add", token.UserID, true, changekeys.Listed(channel), channel)
|
||||||
|
|
||||||
|
return channel, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) EditChannel(ctx context.Context, input input.ChannelEditInput) (models.Channel, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("channel.edit") {
|
||||||
|
return models.Channel{}, errors.New("You are not permitted to edit channels")
|
||||||
|
}
|
||||||
|
|
||||||
|
channel, err := channels.FindName(input.Name)
|
||||||
|
if err != nil {
|
||||||
|
return models.Channel{}, errors.New("Channel not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
channel, err = channels.Edit(channel, input.Logged, input.Hub, input.EventName, input.LocationName)
|
||||||
|
if err != nil {
|
||||||
|
return models.Channel{}, errors.New("Failed to edit channel: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Channel", "edit", token.UserID, true, changekeys.Listed(channel), channel)
|
||||||
|
|
||||||
|
return channel, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/internal/auth"
|
||||||
|
"git.aiterp.net/rpdata/api/models/stories"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/chapters"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Queries
|
||||||
|
|
||||||
|
func (r *resolver) Chapter(ctx context.Context, id string) (models.Chapter, error) {
|
||||||
|
return chapters.FindID(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutations
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAddInput) (models.Chapter, error) {
|
||||||
|
story, err := stories.FindID(input.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Permitted("member", "story.add") {
|
||||||
|
return models.Chapter{}, errors.New("Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
author := token.UserID
|
||||||
|
if input.Author != nil && *input.Author != author {
|
||||||
|
if !token.Permitted("story.add") {
|
||||||
|
return models.Chapter{}, errors.New("False pretender")
|
||||||
|
}
|
||||||
|
|
||||||
|
author = *input.Author
|
||||||
|
}
|
||||||
|
|
||||||
|
if !story.Open && story.Author != author {
|
||||||
|
return models.Chapter{}, errors.New("Story is not open")
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err := chapters.Add(story, input.Title, author, input.Source, time.Now(), input.FictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Failed to create chapter: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Chapter", "add", token.UserID, story.Listed, changekeys.Listed(story, chapter), story, chapter)
|
||||||
|
|
||||||
|
return chapter, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) MoveChapter(ctx context.Context, input input.ChapterMoveInput) (models.Chapter, error) {
|
||||||
|
chapter, err := chapters.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.move") {
|
||||||
|
return models.Chapter{}, errors.New("You are not allowed to move this chapter")
|
||||||
|
}
|
||||||
|
|
||||||
|
target, err := stories.FindID(input.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Target story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !target.Open && !token.PermittedUser(target.Author, "member", "chapter.move") {
|
||||||
|
return models.Chapter{}, errors.New("You are not permitted to move chapters to this story")
|
||||||
|
}
|
||||||
|
|
||||||
|
oldStoryID := chapter.StoryID
|
||||||
|
chapter, err = chapters.Move(chapter, target)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Failed to move chapter: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
story, err := stories.FindID(chapter.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
story.ID = chapter.StoryID
|
||||||
|
}
|
||||||
|
|
||||||
|
oldStory, err := stories.FindID(oldStoryID)
|
||||||
|
if err != nil {
|
||||||
|
oldStory.ID = oldStoryID
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Chapter", "move-out", chapter.Author, oldStory.Listed, changekeys.Many(oldStory, chapter), chapter)
|
||||||
|
changes.Submit("Chapter", "move-in", token.UserID, story.Listed, changekeys.Listed(story, chapter), story, chapter)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return chapter, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) EditChapter(ctx context.Context, input input.ChapterEditInput) (models.Chapter, error) {
|
||||||
|
chapter, err := chapters.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.edit") {
|
||||||
|
return models.Chapter{}, errors.New("Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.ClearFictionalDate != nil && *input.ClearFictionalDate == true {
|
||||||
|
input.FictionalDate = &time.Time{}
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err = chapters.Edit(chapter, input.Title, input.Source, input.FictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Failed to edit chapter: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
story, err := stories.FindID(chapter.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
story.ID = chapter.StoryID
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Chapter", "edit", token.UserID, story.Listed, changekeys.Many(story, chapter), chapter)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return chapter, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) RemoveChapter(ctx context.Context, input input.ChapterRemoveInput) (models.Chapter, error) {
|
||||||
|
chapter, err := chapters.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.remove") {
|
||||||
|
return models.Chapter{}, errors.New("Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err = chapters.Remove(chapter)
|
||||||
|
if err != nil {
|
||||||
|
return models.Chapter{}, errors.New("Failed to remove chapter: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
story, err := stories.FindID(chapter.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
story.ID = chapter.StoryID
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Chapter", "remove", token.UserID, story.Listed, changekeys.Many(story, chapter), chapter)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return chapter, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
"git.aiterp.net/rpdata/api/internal/auth"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
"git.aiterp.net/rpdata/api/models/characters"
|
||||||
|
"git.aiterp.net/rpdata/api/models/logs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Queries
|
||||||
|
|
||||||
|
func (r *resolver) Character(ctx context.Context, id *string, nick *string) (models.Character, error) {
|
||||||
|
if id != nil {
|
||||||
|
return characters.FindID(*id)
|
||||||
|
} else if nick != nil {
|
||||||
|
return characters.FindNick(*nick)
|
||||||
|
} else {
|
||||||
|
return models.Character{}, errors.New("You must specify either an ID or a nick")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) Characters(ctx context.Context, filter *characters.Filter) ([]models.Character, error) {
|
||||||
|
return characters.List(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutations
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddCharacter(ctx context.Context, input input.CharacterAddInput) (models.Character, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Permitted("member", "character.add") {
|
||||||
|
return models.Character{}, errors.New("You are not permitted to add characters")
|
||||||
|
}
|
||||||
|
if len(input.Name) < 2 || len(input.Nick) < 2 {
|
||||||
|
return models.Character{}, errors.New("You need to provide a name and a nick (min length: 2)")
|
||||||
|
}
|
||||||
|
|
||||||
|
shortName := ""
|
||||||
|
if input.ShortName != nil {
|
||||||
|
shortName = *input.ShortName
|
||||||
|
} else {
|
||||||
|
shortName = strings.SplitN(input.Name, " ", 2)[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
description := ""
|
||||||
|
if input.Description != nil {
|
||||||
|
description = *input.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
author := token.UserID
|
||||||
|
if input.Author != nil && *input.Author != author {
|
||||||
|
if !token.Permitted("character.add") {
|
||||||
|
return models.Character{}, errors.New("You are only permitted to add your own characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
author = *input.Author
|
||||||
|
}
|
||||||
|
|
||||||
|
logs.ScheduleFullUpdate()
|
||||||
|
|
||||||
|
character, err := characters.Add(input.Nick, input.Name, shortName, author, description)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Adding character failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Character", "add", token.UserID, true, changekeys.Listed(character), character)
|
||||||
|
|
||||||
|
return character, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddCharacterNick(ctx context.Context, input input.CharacterNickInput) (models.Character, error) {
|
||||||
|
character, err := characters.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Character not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(input.Nick) < 2 {
|
||||||
|
return models.Character{}, errors.New("You need to provide a valid nick (min length: 2)")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.PermittedUser(character.Author, "member", "character.edit") {
|
||||||
|
return models.Character{}, errors.New("You are not permitted to edit this character")
|
||||||
|
}
|
||||||
|
|
||||||
|
logs.ScheduleFullUpdate()
|
||||||
|
|
||||||
|
character, err = characters.AddNick(character, input.Nick)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Failed to add nick: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go logs.ScheduleFullUpdate()
|
||||||
|
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||||
|
|
||||||
|
return character, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input input.CharacterNickInput) (models.Character, error) {
|
||||||
|
character, err := characters.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Character not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.PermittedUser(character.Author, "member", "character.edit") {
|
||||||
|
return models.Character{}, errors.New("You are not permitted to edit this character")
|
||||||
|
}
|
||||||
|
|
||||||
|
character, err = characters.RemoveNick(character, input.Nick)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Failed to remove nick: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go logs.ScheduleFullUpdate()
|
||||||
|
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||||
|
|
||||||
|
return character, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) EditCharacter(ctx context.Context, input input.CharacterEditInput) (models.Character, error) {
|
||||||
|
character, err := characters.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Character not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.Name != nil && len(*input.Name) < 2 {
|
||||||
|
return models.Character{}, errors.New("You need to provide a valid name (min length: 2)")
|
||||||
|
}
|
||||||
|
if input.ShortName != nil && len(*input.ShortName) < 2 {
|
||||||
|
return models.Character{}, errors.New("You need to provide a valid short name (min length: 2)")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.PermittedUser(character.Author, "member", "character.edit") {
|
||||||
|
return models.Character{}, errors.New("You are not permitted to edit this character")
|
||||||
|
}
|
||||||
|
|
||||||
|
character, err = characters.Edit(character, input.Name, input.ShortName, input.Description)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Failed to edit character: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||||
|
|
||||||
|
return character, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) RemoveCharacter(ctx context.Context, input input.CharacterRemoveInput) (models.Character, error) {
|
||||||
|
character, err := characters.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Character not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.PermittedUser(character.Author, "member", "character.remove") {
|
||||||
|
return models.Character{}, errors.New("You are not permitted to remove this character")
|
||||||
|
}
|
||||||
|
|
||||||
|
character, err = characters.Remove(character)
|
||||||
|
if err != nil {
|
||||||
|
return models.Character{}, errors.New("Failed to remove character: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Character", "remove", token.UserID, true, changekeys.Listed(character), character)
|
||||||
|
|
||||||
|
return character, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/internal/auth"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/files"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *resolver) File(ctx context.Context, id string) (models.File, error) {
|
||||||
|
return files.FindID(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) Files(ctx context.Context, filter *files.Filter) ([]models.File, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
|
||||||
|
if filter == nil {
|
||||||
|
filter = &files.Filter{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only allow users to view public files that are not their own.
|
||||||
|
if token != nil {
|
||||||
|
if filter.Public == nil || *filter.Public == false {
|
||||||
|
filter.Author = &token.UserID
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filter.Public = &trueValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return files.List(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
var trueValue = true
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/channels"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
"git.aiterp.net/rpdata/api/internal/auth"
|
||||||
|
"git.aiterp.net/rpdata/api/internal/loader"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
"git.aiterp.net/rpdata/api/models/logs"
|
||||||
|
"github.com/99designs/gqlgen/graphql"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Queries
|
||||||
|
|
||||||
|
func (r *resolver) Log(ctx context.Context, id string) (models.Log, error) {
|
||||||
|
return logs.FindID(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) Logs(ctx context.Context, filter *logs.Filter) ([]models.Log, error) {
|
||||||
|
logs, err := logs.List(filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reqCtx := graphql.GetRequestContext(ctx)
|
||||||
|
maybeCharacters := strings.Contains(reqCtx.RawQuery, "characters")
|
||||||
|
maybeChannels := strings.Contains(reqCtx.RawQuery, "channels")
|
||||||
|
|
||||||
|
if len(logs) >= 100 && (maybeCharacters || maybeChannels) {
|
||||||
|
loader := loader.FromContext(ctx)
|
||||||
|
if loader == nil {
|
||||||
|
return nil, errors.New("no loader")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, log := range logs {
|
||||||
|
if maybeChannels {
|
||||||
|
loader.PrimeChannels("name", log.ChannelName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maybeCharacters {
|
||||||
|
loader.PrimeCharacters("id", log.CharacterIDs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return logs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutations
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput) (models.Log, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("log.add") {
|
||||||
|
return models.Log{}, errors.New("You are not permitted to add logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
open := input.Open != nil && *input.Open == true
|
||||||
|
title := ""
|
||||||
|
if input.Title != nil {
|
||||||
|
title = *input.Title
|
||||||
|
}
|
||||||
|
event := ""
|
||||||
|
if input.Event != nil {
|
||||||
|
event = *input.Event
|
||||||
|
}
|
||||||
|
description := ""
|
||||||
|
if input.Description != nil {
|
||||||
|
description = *input.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
existingChannel, _ := channels.FindName(input.Channel)
|
||||||
|
|
||||||
|
log, err := logs.Add(input.Date, input.Channel, title, event, description, open)
|
||||||
|
if !token.Authenticated() || !token.Permitted("log.add") {
|
||||||
|
return models.Log{}, errors.New("Failed to create log: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if existingChannel.Name == "" {
|
||||||
|
channel, err := channels.FindName(input.Channel)
|
||||||
|
if err == nil {
|
||||||
|
changes.Submit("Channel", "add", token.UserID, true, changekeys.Listed(channel), channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Log", "add", token.UserID, true, changekeys.Listed(log), log)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return log, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) EditLog(ctx context.Context, input input.LogEditInput) (models.Log, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("log.edit") {
|
||||||
|
return models.Log{}, errors.New("You are not permitted to edit logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err := logs.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Log{}, errors.New("Log not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err = logs.Edit(log, input.Title, input.Event, input.Description, input.Open)
|
||||||
|
if err != nil {
|
||||||
|
return models.Log{}, errors.New("Failed to edit log: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Log", "edit", token.UserID, true, changekeys.Listed(log), log)
|
||||||
|
|
||||||
|
return log, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) RemoveLog(ctx context.Context, input input.LogRemoveInput) (models.Log, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("log.remove") {
|
||||||
|
return models.Log{}, errors.New("You are not permitted to remove logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err := logs.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Log{}, errors.New("Log not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err = logs.Remove(log)
|
||||||
|
if err != nil {
|
||||||
|
return models.Log{}, errors.New("Failed to remove log: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Log", "remove", token.UserID, true, changekeys.Listed(log), log)
|
||||||
|
|
||||||
|
return log, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
"git.aiterp.net/rpdata/api/models/logs"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
"git.aiterp.net/rpdata/api/internal/auth"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/posts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Queries
|
||||||
|
|
||||||
|
func (r *resolver) Post(ctx context.Context, id string) (models.Post, error) {
|
||||||
|
return posts.FindID(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) Posts(ctx context.Context, filter *posts.Filter) ([]models.Post, error) {
|
||||||
|
// Some sanity checks to avoid querying an insame amount of posts.
|
||||||
|
if filter == nil {
|
||||||
|
filter = &posts.Filter{Limit: 256}
|
||||||
|
} else {
|
||||||
|
if (filter.Limit <= 0 || filter.Limit > 256) && filter.LogID == nil {
|
||||||
|
return nil, errors.New("a limit of 0 (no limit) or >256 without a logId is not allowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(filter.Kind) > 32 {
|
||||||
|
return nil, errors.New("You cannot specify more than 32 kinds")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(filter.ID) > 32 {
|
||||||
|
return nil, errors.New("You cannot specify more than 32 IDs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return posts.List(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutation
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddPost(ctx context.Context, input input.PostAddInput) (models.Post, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("post.add") {
|
||||||
|
return models.Post{}, errors.New("You are not permitted to edit logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err := logs.FindID(input.LogID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Post{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err := posts.Add(log, input.Time, input.Kind, input.Nick, input.Text)
|
||||||
|
if err != nil {
|
||||||
|
return models.Post{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go logs.UpdateCharacters(log)
|
||||||
|
go changes.Submit("Post", "add", token.UserID, true, changekeys.Many(log, post), post)
|
||||||
|
|
||||||
|
return post, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInput) (models.Post, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("post.edit") {
|
||||||
|
return models.Post{}, errors.New("You are not permitted to edit logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err := posts.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Post{}, errors.New("Post not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.Nick != nil {
|
||||||
|
go func() {
|
||||||
|
log, err := logs.FindID(post.LogID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logs.UpdateCharacters(log)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err = posts.Edit(post, input.Time, input.Kind, input.Nick, input.Text)
|
||||||
|
if err != nil {
|
||||||
|
return models.Post{}, errors.New("Adding post failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
log, err := logs.FindID(post.LogID)
|
||||||
|
if err != nil {
|
||||||
|
log = models.Log{ID: post.LogID}
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Post", "edit", token.UserID, true, changekeys.Many(log, post), post)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return post, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) MovePost(ctx context.Context, input input.PostMoveInput) ([]models.Post, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("post.move") {
|
||||||
|
return nil, errors.New("You are not permitted to edit logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err := posts.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Post not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
posts, err := posts.Move(post, input.ToPosition)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Moving posts failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
log, err := logs.FindID(post.LogID)
|
||||||
|
if err != nil {
|
||||||
|
log = models.Log{ID: post.LogID}
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Post", "move", token.UserID, true, changekeys.Many(log, posts), posts)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return posts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemoveInput) (models.Post, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("post.remove") {
|
||||||
|
return models.Post{}, errors.New("You are not permitted to edit logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err := posts.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Post{}, errors.New("Post not found (before removing, of course)")
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err = posts.Remove(post)
|
||||||
|
if err != nil {
|
||||||
|
return models.Post{}, errors.New("Could not remove post: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
log, err := logs.FindID(post.LogID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logs.UpdateCharacters(log)
|
||||||
|
changes.Submit("Post", "remove", token.UserID, true, changekeys.Many(log, post), post)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return post, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
type resolver struct{}
|
||||||
|
type mutationResolver struct{}
|
||||||
|
|
||||||
|
// Resolver has all the queries
|
||||||
|
var Resolver resolver
|
||||||
|
|
||||||
|
// MutationResolver brings the mutagens.
|
||||||
|
var MutationResolver *mutationResolver
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
"git.aiterp.net/rpdata/api/internal/auth"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/chapters"
|
||||||
|
"git.aiterp.net/rpdata/api/models/stories"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *resolver) Story(ctx context.Context, id string) (models.Story, error) {
|
||||||
|
return stories.FindID(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) Stories(ctx context.Context, filter *stories.Filter) ([]models.Story, error) {
|
||||||
|
if filter != nil {
|
||||||
|
if filter.Unlisted != nil && *filter.Unlisted == true {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() {
|
||||||
|
return nil, errors.New("You are not permitted to view unlisted stories")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !token.Permitted("story.unlisted") {
|
||||||
|
filter.Author = &token.UserID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stories.List(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutations
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddStory(ctx context.Context, input input.StoryAddInput) (models.Story, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if token == nil || !token.Permitted("member", "story.add") {
|
||||||
|
return models.Story{}, errors.New("Permission denied")
|
||||||
|
}
|
||||||
|
|
||||||
|
author := token.UserID
|
||||||
|
if input.Author != nil && *input.Author != author {
|
||||||
|
if !token.Permitted("story.add") {
|
||||||
|
return models.Story{}, errors.New("You are not permitted to add a story in another author's name")
|
||||||
|
}
|
||||||
|
|
||||||
|
author = *input.Author
|
||||||
|
}
|
||||||
|
|
||||||
|
fictionalDate := time.Time{}
|
||||||
|
if input.FictionalDate != nil {
|
||||||
|
fictionalDate = *input.FictionalDate
|
||||||
|
}
|
||||||
|
|
||||||
|
listed := input.Listed != nil && *input.Listed
|
||||||
|
open := input.Open != nil && *input.Open
|
||||||
|
|
||||||
|
story, err := stories.Add(input.Name, author, input.Category, listed, open, input.Tags, time.Now(), fictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Failed to add story: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Story", "add", token.UserID, story.Listed, changekeys.Listed(story), story)
|
||||||
|
|
||||||
|
return story, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTagAddInput) (models.Story, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
|
||||||
|
story, err := stories.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !token.PermittedUser(story.Author, "member", "story.edit") {
|
||||||
|
return models.Story{}, errors.New("You are not permitted to edit this story")
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err = stories.AddTag(story, input.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Failed to add story: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Story", "tag", token.UserID, story.Listed, changekeys.Listed(story), story, input.Tag)
|
||||||
|
|
||||||
|
return story, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.StoryTagRemoveInput) (models.Story, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
|
||||||
|
story, err := stories.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !token.PermittedUser(story.Author, "member", "story.edit") {
|
||||||
|
return models.Story{}, errors.New("You are not permitted to edit this story")
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err = stories.RemoveTag(story, input.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Failed to add story: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Story", "untag", token.UserID, story.Listed, changekeys.Listed(story), story, input.Tag)
|
||||||
|
|
||||||
|
return story, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditInput) (models.Story, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
|
||||||
|
story, err := stories.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !token.PermittedUser(story.Author, "member", "story.edit") {
|
||||||
|
return models.Story{}, errors.New("You are not permitted to remove this story")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.ClearFictionalDate != nil && *input.ClearFictionalDate {
|
||||||
|
input.FictionalDate = &time.Time{}
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err = stories.Edit(story, input.Name, input.Category, input.Listed, input.Open, input.FictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Failed to add story: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Story", "edit", token.UserID, story.Listed, changekeys.Listed(story), story)
|
||||||
|
|
||||||
|
return story, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) RemoveStory(ctx context.Context, input input.StoryRemoveInput) (models.Story, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
|
||||||
|
story, err := stories.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !token.PermittedUser(story.Author, "member", "story.remove") {
|
||||||
|
return models.Story{}, errors.New("You are not permitted to remove this story")
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err = stories.Remove(story)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = chapters.RemoveStory(story)
|
||||||
|
if err != nil {
|
||||||
|
return models.Story{}, errors.New("Failed to remove chapters, but story is removed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go changes.Submit("Story", "remove", token.UserID, story.Listed, changekeys.Listed(story), story)
|
||||||
|
|
||||||
|
return story, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/tags"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *resolver) Tags(ctx context.Context) ([]models.Tag, error) {
|
||||||
|
return tags.List()
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/internal/auth"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *resolver) Token(ctx context.Context) (models.Token, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() {
|
||||||
|
return models.Token{}, errors.New("No (valid) token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return *token, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
schema {
|
||||||
|
query: Query
|
||||||
|
mutation: Mutation
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
# Find character by either an ID or a nick.
|
||||||
|
character(id: String, nick: String): Character!
|
||||||
|
|
||||||
|
# Find characters
|
||||||
|
characters(filter: CharactersFilter): [Character!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find channel by name
|
||||||
|
channel(name: String!): Channel!
|
||||||
|
|
||||||
|
# Find channels
|
||||||
|
channels(filter: ChannelsFilter): [Channel!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find post by ID.
|
||||||
|
post(id: String!): Post!
|
||||||
|
|
||||||
|
# Find posts
|
||||||
|
posts(filter: PostsFilter): [Post!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find log by ID
|
||||||
|
log(id: String!): Log!
|
||||||
|
|
||||||
|
# Find logs
|
||||||
|
logs(filter: LogsFilter): [Log!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find story chapter by ID
|
||||||
|
chapter(id: String!): Chapter!
|
||||||
|
|
||||||
|
|
||||||
|
# Find all distinct tags used in stories
|
||||||
|
tags: [Tag!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find story by ID
|
||||||
|
story(id: String!): Story!
|
||||||
|
|
||||||
|
# Find stories
|
||||||
|
stories(filter: StoriesFilter): [Story!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find file by ID
|
||||||
|
file(id: String!): File!
|
||||||
|
|
||||||
|
# Find files
|
||||||
|
files(filter: FilesFilter): [File!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find changes
|
||||||
|
changes(filter: ChangesFilter): [Change!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Get information about the token, useful for debugging.
|
||||||
|
token: Token!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
# Add a story
|
||||||
|
addStory(input: StoryAddInput!): Story!
|
||||||
|
|
||||||
|
# Add a story tag
|
||||||
|
addStoryTag(input: StoryTagAddInput!): Story!
|
||||||
|
|
||||||
|
# Remove a story tag
|
||||||
|
removeStoryTag(input: StoryTagRemoveInput!): Story!
|
||||||
|
|
||||||
|
# Edit a story
|
||||||
|
editStory(input: StoryEditInput!): Story!
|
||||||
|
|
||||||
|
# Remove a story
|
||||||
|
removeStory(input: StoryRemoveInput!): Story!
|
||||||
|
|
||||||
|
|
||||||
|
# Add a chapter to a story
|
||||||
|
addChapter(input: ChapterAddInput!): Chapter!
|
||||||
|
|
||||||
|
# Edit a chapter
|
||||||
|
editChapter(input: ChapterEditInput!): Chapter!
|
||||||
|
|
||||||
|
# Move a chapter
|
||||||
|
moveChapter(input: ChapterMoveInput!): Chapter!
|
||||||
|
|
||||||
|
# Remove a chapter
|
||||||
|
removeChapter(input: ChapterRemoveInput!): Chapter!
|
||||||
|
|
||||||
|
|
||||||
|
# Add a new log
|
||||||
|
addLog(input: LogAddInput!): Log!
|
||||||
|
|
||||||
|
# Edit a log
|
||||||
|
editLog(input: LogEditInput!): Log!
|
||||||
|
|
||||||
|
# Remove a log
|
||||||
|
removeLog(input: LogRemoveInput!): Log!
|
||||||
|
|
||||||
|
|
||||||
|
# Add a post
|
||||||
|
addPost(input: PostAddInput!): Post!
|
||||||
|
|
||||||
|
# Edit a post
|
||||||
|
editPost(input: PostEditInput!): Post!
|
||||||
|
|
||||||
|
# Move a post. All affected posts will be returned.
|
||||||
|
movePost(input: PostMoveInput!): [Post!]!
|
||||||
|
|
||||||
|
# Remove a post
|
||||||
|
removePost(input: PostRemoveInput!): Post!
|
||||||
|
|
||||||
|
|
||||||
|
# Add a new character
|
||||||
|
addCharacter(input: CharacterAddInput!): Character!
|
||||||
|
|
||||||
|
# Add nick to character
|
||||||
|
addCharacterNick(input: CharacterNickInput!): Character!
|
||||||
|
|
||||||
|
# Remove nick from character
|
||||||
|
removeCharacterNick(input: CharacterNickInput!): Character!
|
||||||
|
|
||||||
|
# Edit character
|
||||||
|
editCharacter(input: CharacterEditInput!): Character!
|
||||||
|
|
||||||
|
# Remove a character
|
||||||
|
removeCharacter(input: CharacterRemoveInput!): Character!
|
||||||
|
|
||||||
|
|
||||||
|
# Add a channel
|
||||||
|
addChannel(input: ChannelAddInput!): Channel!
|
||||||
|
|
||||||
|
# Edit a channel
|
||||||
|
editChannel(input: ChannelEditInput!): Channel!
|
||||||
|
}
|
||||||
|
|
||||||
|
# A Date represents a RFC3339 encoded date with up to millisecond precision.
|
||||||
|
scalar Date
|
||||||
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
"""
|
||||||
|
A change represents a a change in the history.
|
||||||
|
"""
|
||||||
|
type Change {
|
||||||
|
"A unique ID of the change."
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
"The model of the changed object."
|
||||||
|
model: ChangeModel!
|
||||||
|
|
||||||
|
"The operation performed."
|
||||||
|
op: String!
|
||||||
|
|
||||||
|
"The author that performed the change."
|
||||||
|
author: String!
|
||||||
|
|
||||||
|
"Whether the change will be listed without a matching key."
|
||||||
|
listed: Boolean!
|
||||||
|
|
||||||
|
"The keys indexing this change."
|
||||||
|
keys: [ChangeKey!]!
|
||||||
|
|
||||||
|
"The date when the change happened."
|
||||||
|
date: Date
|
||||||
|
|
||||||
|
"The changed objects."
|
||||||
|
objects: [ChangeObject!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
union ChangeObject = Character | Channel | Log | Post | Story | Tag | Chapter
|
||||||
|
|
||||||
|
"""
|
||||||
|
A change key is a key associated with a change, used for filtering
|
||||||
|
and subscription. A log post edit has keys for both the log and post,
|
||||||
|
making it suitable to use it to patch an active log file.
|
||||||
|
"""
|
||||||
|
type ChangeKey {
|
||||||
|
"The model the key is for."
|
||||||
|
model: ChangeModel!
|
||||||
|
|
||||||
|
"The model's id, or * if it's a key indicating a model list should be updated."
|
||||||
|
id: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
See ChangeKey
|
||||||
|
"""
|
||||||
|
input ChangeKeyInput {
|
||||||
|
"The model the key is for."
|
||||||
|
model: ChangeModel!
|
||||||
|
|
||||||
|
"The model's id, or * if it's a key indicating a model list should be updated."
|
||||||
|
id: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
A model related to the change.
|
||||||
|
"""
|
||||||
|
enum ChangeModel {
|
||||||
|
Character
|
||||||
|
Channel
|
||||||
|
Log
|
||||||
|
Post
|
||||||
|
Story
|
||||||
|
Tag
|
||||||
|
Chapter
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Optional filter for the changes query.
|
||||||
|
"""
|
||||||
|
input ChangesFilter {
|
||||||
|
"The keys to query for."
|
||||||
|
keys: [ChangeKeyInput!]
|
||||||
|
|
||||||
|
"Only show changes more recent than this date."
|
||||||
|
earliestDate: Date
|
||||||
|
|
||||||
|
"Limit the amount of results."
|
||||||
|
limit: Int
|
||||||
|
}
|
||||||
@@ -16,6 +16,18 @@ type Channel {
|
|||||||
locationName: String
|
locationName: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Filters for the channels query
|
||||||
|
input ChannelsFilter {
|
||||||
|
# Filter to either logged or unlogged channels
|
||||||
|
logged: Boolean
|
||||||
|
|
||||||
|
# Filter by event name
|
||||||
|
eventName: String
|
||||||
|
|
||||||
|
# Filter by location name
|
||||||
|
locationName: String
|
||||||
|
}
|
||||||
|
|
||||||
input ChannelAddInput {
|
input ChannelAddInput {
|
||||||
# The channel's name
|
# The channel's name
|
||||||
name: String!
|
name: String!
|
||||||
@@ -13,13 +13,13 @@ type Chapter {
|
|||||||
source: String!
|
source: String!
|
||||||
|
|
||||||
# When the chapter was posted initialy
|
# When the chapter was posted initialy
|
||||||
createdDate: String!
|
createdDate: Date!
|
||||||
|
|
||||||
# The in-universe date and time of the chapter
|
# The in-universe date and time of the chapter
|
||||||
fictionalDate: String!
|
fictionalDate: Date
|
||||||
|
|
||||||
# The date of edit.
|
# The date of edit.
|
||||||
editedDate: String!
|
editedDate: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
# Input for addChapter mutation
|
# Input for addChapter mutation
|
||||||
@@ -40,7 +40,7 @@ input ChapterAddInput {
|
|||||||
source: String!
|
source: String!
|
||||||
|
|
||||||
# Optionally, assign a fictional date for the chapter
|
# Optionally, assign a fictional date for the chapter
|
||||||
fictionalDate: String
|
fictionalDate: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
# Input for editChapter mutation
|
# Input for editChapter mutation
|
||||||
@@ -55,5 +55,23 @@ input ChapterEditInput {
|
|||||||
source: String
|
source: String
|
||||||
|
|
||||||
# Set the fictional date for a chapter
|
# Set the fictional date for a chapter
|
||||||
fictionalDate: String
|
fictionalDate: Date
|
||||||
|
|
||||||
|
# Remove the fictional date for a chapter
|
||||||
|
clearFictionalDate: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
# Input for moveChapter mutation
|
||||||
|
input ChapterMoveInput {
|
||||||
|
# The chapter to move
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
# The story to move it to
|
||||||
|
storyId: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Input for removeChapter mutation
|
||||||
|
input ChapterRemoveInput {
|
||||||
|
# The chapter to remove
|
||||||
|
id: String!
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,24 @@ type Character {
|
|||||||
description: String!
|
description: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Filter for characters query
|
||||||
|
input CharactersFilter {
|
||||||
|
# Filter by character IDs
|
||||||
|
ids: [String!]
|
||||||
|
|
||||||
|
# Filter by nicks
|
||||||
|
nicks: [String!]
|
||||||
|
|
||||||
|
# Filter by names
|
||||||
|
names: [String!]
|
||||||
|
|
||||||
|
# Filter by author
|
||||||
|
author: String
|
||||||
|
|
||||||
|
# Filter by text search matching against the character's description
|
||||||
|
search: String
|
||||||
|
}
|
||||||
|
|
||||||
# Input for adding characters
|
# Input for adding characters
|
||||||
input CharacterAddInput {
|
input CharacterAddInput {
|
||||||
# The primary IRC nick name to recognize this character by
|
# The primary IRC nick name to recognize this character by
|
||||||
@@ -50,6 +68,7 @@ input CharacterNickInput {
|
|||||||
nick: String!
|
nick: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Inpuit for editCharacter mutation
|
||||||
input CharacterEditInput {
|
input CharacterEditInput {
|
||||||
# The id for the character to edit
|
# The id for the character to edit
|
||||||
id: String!
|
id: String!
|
||||||
@@ -63,3 +82,10 @@ input CharacterEditInput {
|
|||||||
# A short description for the character
|
# A short description for the character
|
||||||
description: String
|
description: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Input for removeCharacter mutation
|
||||||
|
input CharacterRemoveInput {
|
||||||
|
# The id for the character to edit
|
||||||
|
id: String!
|
||||||
|
}
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ type File {
|
|||||||
kind: String!
|
kind: String!
|
||||||
|
|
||||||
# The time of uploading
|
# The time of uploading
|
||||||
time: String!
|
time: Date!
|
||||||
|
|
||||||
# Whether the file is publicly listable. Someone with knowledge of the ID
|
# Whether the file is publicly listable. Someone with knowledge of the ID
|
||||||
# will still be able to view it, however.
|
# will still be able to view it, however.
|
||||||
@@ -29,6 +29,15 @@ type File {
|
|||||||
url: String
|
url: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Filter for the files quiery.
|
||||||
|
input FilesFilter {
|
||||||
|
# If set, this will limit the results to either public or private files.
|
||||||
|
public: Boolean
|
||||||
|
|
||||||
|
# Limit the MIME types of the files.
|
||||||
|
mimeType: [String!]
|
||||||
|
}
|
||||||
|
|
||||||
# Input for editFile mutation
|
# Input for editFile mutation
|
||||||
input EditFileInput {
|
input EditFileInput {
|
||||||
# The file's unique ID
|
# The file's unique ID
|
||||||
@@ -8,7 +8,7 @@ type Log {
|
|||||||
shortId: String!
|
shortId: String!
|
||||||
|
|
||||||
# The date for a log.
|
# The date for a log.
|
||||||
date: String!
|
date: Date!
|
||||||
|
|
||||||
# The channel of a log.
|
# The channel of a log.
|
||||||
channelName: String!
|
channelName: String!
|
||||||
@@ -21,7 +21,7 @@ type Log {
|
|||||||
|
|
||||||
# The log's event, which is the same as the tags in the previous logbot site.
|
# The log's event, which is the same as the tags in the previous logbot site.
|
||||||
# Empty string means that it's no event.
|
# Empty string means that it's no event.
|
||||||
event: String!
|
eventName: String!
|
||||||
|
|
||||||
# The description of a session, which is empty if unset.
|
# The description of a session, which is empty if unset.
|
||||||
description: String!
|
description: String!
|
||||||
@@ -50,17 +50,17 @@ input LogsFilter {
|
|||||||
# Search post content
|
# Search post content
|
||||||
search: String
|
search: String
|
||||||
|
|
||||||
# Limit to only open logs
|
# Limit by whether it's open or not
|
||||||
open: Boolean
|
open: Boolean
|
||||||
|
|
||||||
# Limit the amount of posts
|
# Limit the amount of results you get back
|
||||||
limit: Int
|
limit: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
# Input for addLog mutation
|
# Input for addLog mutation
|
||||||
input LogAddInput {
|
input LogAddInput {
|
||||||
# The date of the log, in RFC3339 format with up to nanosecond precision
|
# The date of the log.
|
||||||
date: String!
|
date: Date!
|
||||||
|
|
||||||
# The channel where the log is set
|
# The channel where the log is set
|
||||||
channel: String!
|
channel: String!
|
||||||
@@ -96,37 +96,8 @@ input LogEditInput {
|
|||||||
open: Boolean
|
open: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
# A LogHeader is a cut-down version of Log that does not allow getting the actual posts.
|
# Input for removeLog mutation
|
||||||
type LogHeader {
|
input LogRemoveInput {
|
||||||
# A unique identifier for the log.
|
# The id of the log to remove
|
||||||
id: String!
|
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: String!
|
|
||||||
|
|
||||||
# The channel name 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!]!
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ type Post {
|
|||||||
logId: String!
|
logId: String!
|
||||||
|
|
||||||
# The date and time of posting
|
# The date and time of posting
|
||||||
time: String!
|
time: Date!
|
||||||
|
|
||||||
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'.
|
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'.
|
||||||
kind: String!
|
kind: String!
|
||||||
@@ -23,12 +23,12 @@ type Post {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Input for the addPost mutation
|
# Input for the addPost mutation
|
||||||
input AddPostInput {
|
input PostAddInput {
|
||||||
# The log's ID that this post should be a part of
|
# The log's ID that this post should be a part of
|
||||||
logId: String!
|
logId: String!
|
||||||
|
|
||||||
# The date and time of posting, in a RFC3339 format with up to a nanosecond's precision
|
# The date and time of posting, in a RFC3339 format with up to a nanosecond's precision
|
||||||
time: String!
|
time: Date!
|
||||||
|
|
||||||
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'.
|
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'.
|
||||||
kind: String!
|
kind: String!
|
||||||
@@ -41,12 +41,12 @@ input AddPostInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Input for the editPost mutation
|
# Input for the editPost mutation
|
||||||
input EditPostInput {
|
input PostEditInput {
|
||||||
# The Post ID
|
# The Post ID
|
||||||
id: String!
|
id: String!
|
||||||
|
|
||||||
# The date and time of posting, in a RFC3339 format with up to a nanosecond's precision
|
# The date and time of posting, in a RFC3339 format with up to a nanosecond's precision
|
||||||
time: String
|
time: Date
|
||||||
|
|
||||||
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'.
|
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'.
|
||||||
kind: String
|
kind: String
|
||||||
@@ -59,10 +59,24 @@ input EditPostInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Input for the movePost mutation
|
# Input for the movePost mutation
|
||||||
input MovePostInput {
|
input PostMoveInput {
|
||||||
# The Post ID
|
# The Post ID
|
||||||
id: String!
|
id: String!
|
||||||
|
|
||||||
# Target index
|
# Target index
|
||||||
toPosition: Int!
|
toPosition: Int!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Input for the removePost mutation
|
||||||
|
input PostRemoveInput {
|
||||||
|
# The Post ID
|
||||||
|
id: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Filter for posts query
|
||||||
|
input PostsFilter {
|
||||||
|
id: [String!]
|
||||||
|
kind: [String!]
|
||||||
|
logId: String
|
||||||
|
limit: Int
|
||||||
|
}
|
||||||
@@ -25,14 +25,14 @@ type Story {
|
|||||||
# The chapters of this story
|
# The chapters of this story
|
||||||
chapters: [Chapter!]!
|
chapters: [Chapter!]!
|
||||||
|
|
||||||
# The date the story was created (RFC3339 format).
|
# The date the story was created.
|
||||||
createdDate: String!
|
createdDate: Date!
|
||||||
|
|
||||||
# The date the story is set in (RFC3339 format).
|
# The date the story is set in.
|
||||||
fictionalDate: String!
|
fictionalDate: Date
|
||||||
|
|
||||||
# The date of the last major update to the story (RFC3339 format). This being bumped means a new chapter has been added.
|
# The date of the last major update to the story. This being bumped means a new chapter has been added.
|
||||||
updatedDate: String!
|
updatedDate: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
# Filter for stories query.
|
# Filter for stories query.
|
||||||
@@ -40,14 +40,23 @@ input StoriesFilter {
|
|||||||
# What author to query for
|
# What author to query for
|
||||||
author: String
|
author: String
|
||||||
|
|
||||||
|
# What category to query for
|
||||||
|
category: StoryCategory
|
||||||
|
|
||||||
# What tags to query for
|
# What tags to query for
|
||||||
tags: [TagInput!]
|
tags: [TagInput!]
|
||||||
|
|
||||||
|
# If true, it will only show unlisted page you have access to
|
||||||
|
unlisted: Boolean
|
||||||
|
|
||||||
|
# Whether the page is open for additions by other users
|
||||||
|
open: Boolean
|
||||||
|
|
||||||
# The earliest fictionalDate
|
# The earliest fictionalDate
|
||||||
earliestFictionalDate: String
|
earliestFictionalDate: Date
|
||||||
|
|
||||||
# The latest fictionalDate
|
# The latest fictionalDate
|
||||||
latestFictionalDate: String
|
latestFictionalDate: Date
|
||||||
|
|
||||||
# The max amount of stories to get (default: 30)
|
# The max amount of stories to get (default: 30)
|
||||||
limit: Int
|
limit: Int
|
||||||
@@ -75,8 +84,8 @@ input StoryAddInput {
|
|||||||
# Set which tags the story should have.
|
# Set which tags the story should have.
|
||||||
tags: [TagInput!]
|
tags: [TagInput!]
|
||||||
|
|
||||||
# Set the fictional date of the story (RFC3339 format).
|
# Set the fictional date of the story.
|
||||||
fictionalDate: String
|
fictionalDate: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
# Input for the editStory mutation
|
# Input for the editStory mutation
|
||||||
@@ -101,8 +110,11 @@ input StoryEditInput {
|
|||||||
# Change whether to show this story in the list and search results
|
# Change whether to show this story in the list and search results
|
||||||
listed: Boolean
|
listed: Boolean
|
||||||
|
|
||||||
# Set the fictional date of the story (RFC3339 format).
|
# Set the fictional date of the story.
|
||||||
fictionalDate: String
|
fictionalDate: Date
|
||||||
|
|
||||||
|
# Clear the fictional date of the story.
|
||||||
|
clearFictionalDate: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
# Input for the addStoryTag mutation
|
# Input for the addStoryTag mutation
|
||||||
@@ -123,20 +135,26 @@ input StoryTagRemoveInput {
|
|||||||
tag: TagInput!
|
tag: TagInput!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Input for the removeStory mutation
|
||||||
|
input StoryRemoveInput {
|
||||||
|
# What story to remove.
|
||||||
|
id: String!
|
||||||
|
}
|
||||||
|
|
||||||
# Possible values for Story.category
|
# Possible values for Story.category
|
||||||
enum StoryCategory {
|
enum StoryCategory {
|
||||||
# Description and content of a document or item
|
# General information
|
||||||
Document
|
Info
|
||||||
|
|
||||||
# News stories
|
# News stories
|
||||||
News
|
News
|
||||||
|
|
||||||
|
# Description and content of a document or item
|
||||||
|
Document
|
||||||
|
|
||||||
# Information about something going on in the background that may or may not inform RP
|
# Information about something going on in the background that may or may not inform RP
|
||||||
Background
|
Background
|
||||||
|
|
||||||
# General information
|
|
||||||
Info
|
|
||||||
|
|
||||||
# A short story
|
# A short story
|
||||||
Story
|
Story
|
||||||
}
|
}
|
||||||
@@ -34,3 +34,4 @@ enum TagKind {
|
|||||||
# None of the above, but it does still tie multiple stories together. The new story/chapter format may obsolete this tag kind.
|
# None of the above, but it does still tie multiple stories together. The new story/chapter format may obsolete this tag kind.
|
||||||
Series
|
Series
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Token represents the data parsed and validated from the bearer token.
|
||||||
|
type Token {
|
||||||
|
# The user represented in the token.
|
||||||
|
user: User!
|
||||||
|
|
||||||
|
# The permissions for the token.
|
||||||
|
permissions: [String!]!
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# A user represents a member on the RPData platform.
|
||||||
|
type User {
|
||||||
|
# The user's unique ID / username
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
# What the user is permitted to do.
|
||||||
|
permissions: [String!]!
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type changeResolver struct{}
|
||||||
|
|
||||||
|
func (r *changeResolver) Objects(ctx context.Context, obj *models.Change) ([]input.ChangeObject, error) {
|
||||||
|
objects := obj.Objects()
|
||||||
|
|
||||||
|
results := make([]input.ChangeObject, len(objects))
|
||||||
|
for i := range objects {
|
||||||
|
results[i] = objects[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeResolver is a resolver
|
||||||
|
var ChangeResolver changeResolver
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type chapterResolver struct{}
|
||||||
|
|
||||||
|
func (r *chapterResolver) FictionalDate(ctx context.Context, chapter *models.Chapter) (*time.Time, error) {
|
||||||
|
if chapter.FictionalDate.IsZero() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &chapter.FictionalDate, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChapterResolver is a resolver
|
||||||
|
var ChapterResolver chapterResolver
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fileResolver struct{}
|
||||||
|
|
||||||
|
func (r *fileResolver) Size(ctx context.Context, file *models.File) (int, error) {
|
||||||
|
return int(file.Size), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileResolver is a resolver
|
||||||
|
var FileResolver fileResolver
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/internal/loader"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/posts"
|
||||||
|
)
|
||||||
|
|
||||||
|
type logResolver struct{}
|
||||||
|
|
||||||
|
func (r *logResolver) Channel(ctx context.Context, log *models.Log) (models.Channel, error) {
|
||||||
|
loader := loader.FromContext(ctx)
|
||||||
|
if loader == nil {
|
||||||
|
return models.Channel{}, errors.New("no loader")
|
||||||
|
}
|
||||||
|
|
||||||
|
return loader.Channel("name", log.ChannelName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *logResolver) Characters(ctx context.Context, log *models.Log) ([]models.Character, error) {
|
||||||
|
loader := loader.FromContext(ctx)
|
||||||
|
if loader == nil {
|
||||||
|
return nil, errors.New("no loader")
|
||||||
|
}
|
||||||
|
|
||||||
|
return loader.Characters("id", log.CharacterIDs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *logResolver) Posts(ctx context.Context, log *models.Log, kinds []string) ([]models.Post, error) {
|
||||||
|
return posts.List(&posts.Filter{
|
||||||
|
LogID: &log.ShortID,
|
||||||
|
Kind: kinds,
|
||||||
|
Limit: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogResolver is a resolver
|
||||||
|
var LogResolver logResolver
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/chapters"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type storyResolver struct{}
|
||||||
|
|
||||||
|
func (r *storyResolver) FictionalDate(ctx context.Context, story *models.Story) (*time.Time, error) {
|
||||||
|
if story.FictionalDate.IsZero() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &story.FictionalDate, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *storyResolver) Chapters(ctx context.Context, story *models.Story) ([]models.Chapter, error) {
|
||||||
|
return chapters.ListStoryID(story.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoryResolver is a resolver
|
||||||
|
var StoryResolver storyResolver
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/users"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tokenResolver struct{}
|
||||||
|
|
||||||
|
func (r *tokenResolver) User(ctx context.Context, token *models.Token) (models.User, error) {
|
||||||
|
return users.Find(token.UserID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TokenResolver is a resolver
|
||||||
|
var TokenResolver tokenResolver
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/channel"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChannelAddArgs is input for the addChannel mutation
|
|
||||||
type ChannelAddArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
Name string
|
|
||||||
Logged *bool
|
|
||||||
Hub *bool
|
|
||||||
EventName *string
|
|
||||||
LocationName *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddChannel resolves the addChannel mutation
|
|
||||||
func (r *MutationResolver) AddChannel(ctx context.Context, args *ChannelAddArgs) (*types.ChannelResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("channel.add") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
logged := input.Logged != nil && *input.Logged
|
|
||||||
|
|
||||||
hub := input.Hub != nil && *input.Hub
|
|
||||||
|
|
||||||
eventName := ""
|
|
||||||
if input.EventName != nil {
|
|
||||||
eventName = *input.EventName
|
|
||||||
}
|
|
||||||
|
|
||||||
locationName := ""
|
|
||||||
if input.LocationName != nil {
|
|
||||||
locationName = *input.LocationName
|
|
||||||
}
|
|
||||||
|
|
||||||
channel, err := channel.New(input.Name, logged, hub, eventName, locationName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Channel", "add", user.ID, channel.Name, map[string]interface{}{
|
|
||||||
"logged": channel.Logged,
|
|
||||||
"hub": channel.Hub,
|
|
||||||
"location": input.LocationName,
|
|
||||||
"event": input.EventName,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.ChannelResolver{C: channel}, nil
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddChapterArgs is args for the addChapter mutation
|
|
||||||
type AddChapterArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
StoryID string
|
|
||||||
Title string
|
|
||||||
Author *string
|
|
||||||
Source string
|
|
||||||
FictionalDate *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddChapter resolves the addChapter mutation
|
|
||||||
func (r *MutationResolver) AddChapter(ctx context.Context, args *AddChapterArgs) (*types.ChapterResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "chapter.add") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
story, err := story.FindID(input.StoryID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
author := user.ID
|
|
||||||
if input.Author != nil {
|
|
||||||
author = *input.Author
|
|
||||||
|
|
||||||
if user.ID != author && !user.Permitted("chapter.add") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fictionalDate := time.Time{}
|
|
||||||
if input.FictionalDate != nil {
|
|
||||||
fictionalDate, err = time.Parse(time.RFC3339Nano, *input.FictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chapter, err := story.AddChapter(input.Title, author, input.Source, time.Now(), fictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Chapter", "add", user.ID, chapter.ID, map[string]interface{}{
|
|
||||||
"title": input.Title,
|
|
||||||
"author": author,
|
|
||||||
"fictionalDate": fictionalDate,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.ChapterResolver{C: chapter}, nil
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddCharacterInput is args for the addCharacter mutation
|
|
||||||
type AddCharacterInput struct {
|
|
||||||
Nick string
|
|
||||||
Name string
|
|
||||||
ShortName *string
|
|
||||||
Author *string
|
|
||||||
Description *string
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddCharacter resolves the addCharacter mutation
|
|
||||||
func (r *MutationResolver) AddCharacter(ctx context.Context, args struct{ Input *AddCharacterInput }) (*types.CharacterResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "character.add") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
nick := input.Nick
|
|
||||||
|
|
||||||
name := input.Name
|
|
||||||
|
|
||||||
shortName := ""
|
|
||||||
if input.ShortName != nil {
|
|
||||||
shortName = *input.ShortName
|
|
||||||
} else {
|
|
||||||
shortName = strings.SplitN(input.Name, " ", 2)[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
author := user.ID
|
|
||||||
if input.Author != nil {
|
|
||||||
author = *input.Author
|
|
||||||
|
|
||||||
if author != user.ID && !user.Permitted("character.add") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
description := ""
|
|
||||||
if input.Description != nil {
|
|
||||||
description = *input.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
character, err := character.New(nick, name, shortName, author, description)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Character", "add", user.ID, character.ID, map[string]interface{}{
|
|
||||||
"name": character.Name,
|
|
||||||
"nick": character.Nicks[0],
|
|
||||||
"author": character.Author,
|
|
||||||
})
|
|
||||||
|
|
||||||
log.ScheduleCharacterUpdate()
|
|
||||||
|
|
||||||
return &types.CharacterResolver{C: character}, nil
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddCharacterNickInput is args for the addCharacterNick mutation
|
|
||||||
type AddCharacterNickInput struct {
|
|
||||||
ID string
|
|
||||||
Nick string
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddCharacterNick resolves the addCharacterNick mutation
|
|
||||||
func (r *MutationResolver) AddCharacterNick(ctx context.Context, args struct{ Input *AddCharacterNickInput }) (*types.CharacterResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
character, err := character.FindID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if character.Author != user.ID && !user.Permitted("character.edit") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
err = character.AddNick(input.Nick)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Character", "add.nick", user.ID, character.ID, map[string]interface{}{
|
|
||||||
"nick": input.Nick,
|
|
||||||
})
|
|
||||||
|
|
||||||
log.ScheduleCharacterUpdate()
|
|
||||||
|
|
||||||
return &types.CharacterResolver{C: character}, nil
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LogAddArgs is args for the addLog mutation
|
|
||||||
type LogAddArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
Date string
|
|
||||||
Channel string
|
|
||||||
Title *string
|
|
||||||
Open *bool
|
|
||||||
Event *string
|
|
||||||
Description *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddLog resolves the addLog mutation
|
|
||||||
func (r *MutationResolver) AddLog(ctx context.Context, args *LogAddArgs) (*types.LogResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("log.add") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
date, err := time.Parse(time.RFC3339Nano, args.Input.Date)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
title := ""
|
|
||||||
if input.Title != nil {
|
|
||||||
title = *input.Title
|
|
||||||
}
|
|
||||||
|
|
||||||
event := ""
|
|
||||||
if input.Event != nil {
|
|
||||||
event = *input.Event
|
|
||||||
}
|
|
||||||
|
|
||||||
description := ""
|
|
||||||
if input.Description != nil {
|
|
||||||
description = *input.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
open := input.Open != nil && *input.Open == true
|
|
||||||
|
|
||||||
log, err := log.New(date, input.Channel, title, event, description, open)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Log", "add", user.ID, log.ID, map[string]interface{}{
|
|
||||||
"channel": log.Channel,
|
|
||||||
"title": log.Title,
|
|
||||||
"event": log.Event,
|
|
||||||
"description": log.Description,
|
|
||||||
"open": log.Open,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.LogResolver{L: log}, nil
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostAddArgs is args for addPost mutation
|
|
||||||
type PostAddArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
LogID string
|
|
||||||
Time string
|
|
||||||
Kind string
|
|
||||||
Nick string
|
|
||||||
Text string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddPost resolves the addPost mutation
|
|
||||||
func (r *MutationResolver) AddPost(ctx context.Context, args *PostAddArgs) (*types.PostResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("post.add") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
postTime, err := time.Parse(time.RFC3339Nano, input.Time)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log, err := log.FindID(input.LogID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
post, err := log.NewPost(postTime, input.Kind, input.Nick, input.Text)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Post", "add", user.ID, post.ID, map[string]interface{}{
|
|
||||||
"logId": post.LogID,
|
|
||||||
"time": post.Time,
|
|
||||||
"kind": post.Kind,
|
|
||||||
"nick": post.Nick,
|
|
||||||
"text": post.Text,
|
|
||||||
"position": post.Position,
|
|
||||||
})
|
|
||||||
|
|
||||||
go log.UpdateCharacters()
|
|
||||||
|
|
||||||
return &types.PostResolver{P: post}, nil
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StoryAddArgs is args for the addStory mutation
|
|
||||||
type StoryAddArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
Name string
|
|
||||||
Category string
|
|
||||||
Author *string
|
|
||||||
Open *bool
|
|
||||||
Listed *bool
|
|
||||||
FictionalDate *string
|
|
||||||
Tags *[]struct {
|
|
||||||
Kind string
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddStory resolves the addStory mutation
|
|
||||||
func (r *MutationResolver) AddStory(ctx context.Context, args *StoryAddArgs) (*types.StoryResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "story.add") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
author := user.ID
|
|
||||||
if input.Author != nil {
|
|
||||||
author = *input.Author
|
|
||||||
|
|
||||||
if user.ID != author && !user.Permitted("story.add") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
listed := (input.Listed != nil && *input.Listed == true)
|
|
||||||
|
|
||||||
open := (input.Open != nil && *input.Open == true)
|
|
||||||
|
|
||||||
tags := make([]story.Tag, 0, 8)
|
|
||||||
if input.Tags != nil {
|
|
||||||
for _, tagInput := range *input.Tags {
|
|
||||||
tags = append(tags, story.Tag{
|
|
||||||
Kind: tagInput.Kind,
|
|
||||||
Name: tagInput.Name,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fictionalDate := time.Time{}
|
|
||||||
if input.FictionalDate != nil {
|
|
||||||
date, err := time.Parse(time.RFC3339Nano, *input.FictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fictionalDate = date
|
|
||||||
}
|
|
||||||
|
|
||||||
story, err := story.New(input.Name, author, input.Category, listed, open, tags, time.Now(), fictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Story", "add", user.ID, story.ID, map[string]interface{}{
|
|
||||||
"name": input.Name,
|
|
||||||
"category": input.Category,
|
|
||||||
"author": input.Author,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.StoryResolver{S: story}, nil
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StoryTagAddArgs is args for the addStoryTag mutation
|
|
||||||
type StoryTagAddArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
ID string
|
|
||||||
Tag struct {
|
|
||||||
Kind string
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddStoryTag resolves the addStoryTag mutation
|
|
||||||
func (r *MutationResolver) AddStoryTag(ctx context.Context, args *StoryTagAddArgs) (*types.StoryResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
tag := story.Tag{Kind: input.Tag.Kind, Name: input.Tag.Name}
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "story.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
story, err := story.FindID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if story.Author != user.ID && !user.Permitted("story.edit") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
err = story.AddTag(tag)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Story", "add.tag", user.ID, story.ID, map[string]interface{}{
|
|
||||||
"kind": tag.Kind,
|
|
||||||
"name": tag.Name,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.StoryResolver{S: story}, nil
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/channel"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChannelEditArgs is input for the editChannel mutation
|
|
||||||
type ChannelEditArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
Name string
|
|
||||||
Logged *bool
|
|
||||||
Hub *bool
|
|
||||||
EventName *string
|
|
||||||
LocationName *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditChannel resolves the editChannel mutation
|
|
||||||
func (r *MutationResolver) EditChannel(ctx context.Context, args *ChannelEditArgs) (*types.ChannelResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("channel.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
channel, err := channel.FindName(input.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = channel.Edit(input.Logged, input.Hub, input.EventName, input.LocationName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Channel", "edit", user.ID, channel.Name, map[string]interface{}{
|
|
||||||
"logged": input.Logged,
|
|
||||||
"hub": input.Hub,
|
|
||||||
"location": input.LocationName,
|
|
||||||
"event": input.EventName,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.ChannelResolver{C: channel}, nil
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EditChapterArgs is args for the editChapter mutation
|
|
||||||
type EditChapterArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
ID string
|
|
||||||
Title *string
|
|
||||||
Source *string
|
|
||||||
FictionalDate *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditChapter resolves the editChapter mutation
|
|
||||||
func (r *MutationResolver) EditChapter(ctx context.Context, args *EditChapterArgs) (*types.ChapterResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "chapter.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
chapter, err := story.FindChapterID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if chapter.Author != user.ID && !user.Permitted("chapter.edit") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
var fictionalDate *time.Time
|
|
||||||
if input.FictionalDate != nil {
|
|
||||||
date, err := time.Parse(time.RFC3339Nano, *input.FictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fictionalDate = &date
|
|
||||||
}
|
|
||||||
|
|
||||||
err = chapter.Edit(input.Title, input.Source, fictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Chapter", "edit", user.ID, chapter.ID, map[string]interface{}{
|
|
||||||
"title": input.Title,
|
|
||||||
"source": input.Source,
|
|
||||||
"fictionalDate": fictionalDate,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.ChapterResolver{C: chapter}, nil
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CharacterEditInput is args for mutation addCharacterNick/removeCharacterNick
|
|
||||||
type CharacterEditInput struct {
|
|
||||||
ID string
|
|
||||||
Name *string
|
|
||||||
ShortName *string
|
|
||||||
Description *string
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditCharacter resolves the editCharacter mutation
|
|
||||||
func (r *MutationResolver) EditCharacter(ctx context.Context, args struct{ Input *CharacterEditInput }) (*types.CharacterResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
character, err := character.FindID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if character.Author != user.ID && !user.Permitted("character.edit") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
name := ""
|
|
||||||
if input.Name != nil {
|
|
||||||
name = *input.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
shortName := ""
|
|
||||||
if input.ShortName != nil {
|
|
||||||
shortName = *input.ShortName
|
|
||||||
}
|
|
||||||
|
|
||||||
description := ""
|
|
||||||
if input.Description != nil {
|
|
||||||
description = *input.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
err = character.Edit(name, shortName, description)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Character", "edit", user.ID, character.ID, map[string]interface{}{
|
|
||||||
"name": character.Name,
|
|
||||||
"shortName": character.ShortName,
|
|
||||||
"description": character.Description,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.CharacterResolver{C: character}, nil
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/file"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileEditArgs is args for the editFile mutation
|
|
||||||
type FileEditArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
ID string
|
|
||||||
Name *string
|
|
||||||
Public *bool
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditFile resolves the editFile mutation
|
|
||||||
func (r *MutationResolver) EditFile(ctx context.Context, args *FileEditArgs) (*types.FileResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := file.FindID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if file.Author != user.ID && !user.Permitted("file.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
err = file.Edit(input.Name, input.Public)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.FileResolver{F: file}, nil
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LogEditArgs is args for the editLog mutation
|
|
||||||
type LogEditArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
ID string
|
|
||||||
Title *string
|
|
||||||
Event *string
|
|
||||||
Description *string
|
|
||||||
Open *bool
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditLog resolves the editLog mutation
|
|
||||||
func (r *MutationResolver) EditLog(ctx context.Context, args *LogEditArgs) (*types.LogResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("log.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
log, err := log.FindID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = log.Edit(input.Title, input.Event, input.Description, input.Open)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Log", "edit", user.ID, log.ID, map[string]interface{}{
|
|
||||||
"channel": log.Channel,
|
|
||||||
"title": input.Title,
|
|
||||||
"event": input.Event,
|
|
||||||
"description": input.Description,
|
|
||||||
"open": input.Open,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.LogResolver{L: log}, nil
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostEditArgs is args for the editPost mutation
|
|
||||||
type PostEditArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
ID string
|
|
||||||
Time *string
|
|
||||||
Kind *string
|
|
||||||
Nick *string
|
|
||||||
Text *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditPost resolves the editPost mutation
|
|
||||||
func (r *MutationResolver) EditPost(ctx context.Context, args *PostEditArgs) (*types.PostResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("post.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
postTime := (*time.Time)(nil)
|
|
||||||
if args.Input.Time != nil {
|
|
||||||
t, err := time.Parse(time.RFC3339Nano, *input.Time)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
postTime = &t
|
|
||||||
}
|
|
||||||
|
|
||||||
post, err := log.FindPostID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = post.Edit(postTime, input.Kind, input.Nick, input.Text)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Post", "edit", user.ID, post.ID, map[string]interface{}{
|
|
||||||
"time": postTime,
|
|
||||||
"kind": input.Kind,
|
|
||||||
"nick": input.Nick,
|
|
||||||
"text": input.Text,
|
|
||||||
})
|
|
||||||
|
|
||||||
go log.UpdateCharacters(post.LogID)
|
|
||||||
|
|
||||||
return &types.PostResolver{P: post}, nil
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StoryEditArgs is args for the addStory mutation
|
|
||||||
type StoryEditArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
ID string
|
|
||||||
Name *string
|
|
||||||
Category *string
|
|
||||||
Author *string
|
|
||||||
Open *bool
|
|
||||||
Listed *bool
|
|
||||||
FictionalDate *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditStory resolves the editStory mutation
|
|
||||||
func (r *MutationResolver) EditStory(ctx context.Context, args *StoryEditArgs) (*types.StoryResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "story.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
story, err := story.FindID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if story.Author != user.ID && !user.Permitted("story.edit") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
var fictionalDate *time.Time
|
|
||||||
if input.FictionalDate != nil {
|
|
||||||
date, err := time.Parse(time.RFC3339Nano, *input.FictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fictionalDate = &date
|
|
||||||
}
|
|
||||||
|
|
||||||
err = story.Edit(input.Name, input.Category, input.Listed, input.Open, fictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Story", "edit", user.ID, story.ID, map[string]interface{}{
|
|
||||||
"name": input.Name,
|
|
||||||
"category": input.Category,
|
|
||||||
"author": input.Author,
|
|
||||||
"open": input.Open,
|
|
||||||
"listed": input.Listed,
|
|
||||||
"fictionalDate": input.FictionalDate,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.StoryResolver{S: story}, nil
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LoginArgs is args for the login mutation
|
|
||||||
type LoginArgs struct {
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Login resolves the login mutation
|
|
||||||
func (r *MutationResolver) Login(ctx context.Context, args *LoginArgs) (*types.SessionResolver, error) {
|
|
||||||
session := session.FromContext(ctx)
|
|
||||||
|
|
||||||
err := session.Login(args.Username, args.Password)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.SessionResolver{S: session}, nil
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Logout resolves mutation.logout
|
|
||||||
func (r *MutationResolver) Logout(ctx context.Context) (*types.SessionResolver, error) {
|
|
||||||
session := session.FromContext(ctx)
|
|
||||||
session.Logout()
|
|
||||||
|
|
||||||
return &types.SessionResolver{S: session}, nil
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostMoveArgs is args for movePost mutation
|
|
||||||
type PostMoveArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
ID string
|
|
||||||
ToPosition int32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MovePost resolves the movePost mutation
|
|
||||||
func (r *MutationResolver) MovePost(ctx context.Context, args *PostMoveArgs) (*types.PostResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("post.move") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
post, err := log.FindPostID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = post.Move(int(input.ToPosition))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Post", "move", user.ID, post.ID, map[string]interface{}{
|
|
||||||
"logId": post.LogID,
|
|
||||||
"targetIndex": input.ToPosition,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.PostResolver{P: post}, nil
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/channel"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RemoveChannelArgs is args for removeChannels mutation
|
|
||||||
type RemoveChannelArgs struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveChannel resolves the editChannel mutation
|
|
||||||
func (r *MutationResolver) RemoveChannel(ctx context.Context, args RemoveChannelArgs) (*types.ChannelResolver, error) {
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("channel.remove") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
channel, err := channel.FindName(args.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = channel.Remove()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Channel", "remove", user.ID, channel.Name, nil)
|
|
||||||
|
|
||||||
return &types.ChannelResolver{C: channel}, nil
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RemoveChapterArgs is args for the addChapter mutation
|
|
||||||
type RemoveChapterArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveChapter resolves the removeChapter mutation
|
|
||||||
func (r *MutationResolver) RemoveChapter(ctx context.Context, args *RemoveChapterArgs) (*types.ChapterResolver, error) {
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "chapter.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
chapter, err := story.FindChapterID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = chapter.Remove()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Chapter", "remove", user.ID, chapter.ID, nil)
|
|
||||||
|
|
||||||
return &types.ChapterResolver{C: chapter}, nil
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RemoveCharacterArgs is args for the removeCharacter mutation
|
|
||||||
type RemoveCharacterArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveCharacter resolves the removeCharacter mutation
|
|
||||||
func (r *MutationResolver) RemoveCharacter(ctx context.Context, args RemoveCharacterArgs) (*types.CharacterResolver, error) {
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
character, err := character.FindID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if character.Author != user.ID && !user.Permitted("character.remove") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
err = character.Remove()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Character", "remove", user.ID, character.ID, map[string]interface{}{
|
|
||||||
"name": character.Name,
|
|
||||||
"author": character.Author,
|
|
||||||
"nicks": character.Nicks,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.CharacterResolver{C: character}, nil
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RemoveCharacterNick is args for the addCharacterNick mutation
|
|
||||||
type RemoveCharacterNick struct {
|
|
||||||
ID string
|
|
||||||
Nick string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveCharacterNick resolves the removeCharacterNick mutation
|
|
||||||
func (r *MutationResolver) RemoveCharacterNick(ctx context.Context, args struct{ Input *RemoveCharacterNick }) (*types.CharacterResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
character, err := character.FindID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if character.Author != user.ID && !user.Permitted("character.edit") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
err = character.RemoveNick(input.Nick)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Character", "remove.nick", user.ID, character.ID, map[string]interface{}{
|
|
||||||
"nick": input.Nick,
|
|
||||||
})
|
|
||||||
|
|
||||||
log.ScheduleCharacterUpdate()
|
|
||||||
|
|
||||||
return &types.CharacterResolver{C: character}, nil
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/file"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RemoveFileArgs is an arg
|
|
||||||
type RemoveFileArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveFile resolves the removeFIle mutation
|
|
||||||
func (r *MutationResolver) RemoveFile(ctx context.Context, args *RemoveFileArgs) (*types.FileResolver, error) {
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := file.FindID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if file.Author != user.ID && !user.Permitted("file.remove") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
err = file.Delete()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.FileResolver{F: file}, nil
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RemoveLogArgs is args for the removeLog mutation
|
|
||||||
type RemoveLogArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveLog resolves the removeLog mutation
|
|
||||||
func (r *MutationResolver) RemoveLog(ctx context.Context, args *RemoveLogArgs) (*types.LogResolver, error) {
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("log.remove") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
log, err := log.FindID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = log.Remove()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Log", "remove", user.ID, log.ID, nil)
|
|
||||||
|
|
||||||
return &types.LogResolver{L: log}, nil
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostRemoveArgs is args for the removePost mutation
|
|
||||||
type PostRemoveArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemovePost resolves the removePost mutation
|
|
||||||
func (r *MutationResolver) RemovePost(ctx context.Context, args PostRemoveArgs) (*types.PostResolver, error) {
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("post.remove") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
post, err := log.RemovePost(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Post", "remove", user.ID, post.ID, map[string]interface{}{
|
|
||||||
"logId": post.LogID,
|
|
||||||
})
|
|
||||||
|
|
||||||
go log.UpdateCharacters(post.LogID)
|
|
||||||
|
|
||||||
return &types.PostResolver{P: post}, nil
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StoryRemoveArgs is args for the removeStory mutation
|
|
||||||
type StoryRemoveArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveStory resolves the removeStory mutation
|
|
||||||
func (r *MutationResolver) RemoveStory(ctx context.Context, args *StoryRemoveArgs) (*types.StoryResolver, error) {
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "story.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
story, err := story.FindID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if story.Author != user.ID && !user.Permitted("story.remove") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
err = story.Remove()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Story", "remove", user.ID, story.ID, nil)
|
|
||||||
|
|
||||||
return &types.StoryResolver{S: story}, nil
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package mutations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/change"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StoryTagRemoveArgs is args for the removeStoryTag mutation
|
|
||||||
type StoryTagRemoveArgs struct {
|
|
||||||
Input *struct {
|
|
||||||
ID string
|
|
||||||
Tag struct {
|
|
||||||
Kind string
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveStoryTag resolves the removeStoryTag mutation
|
|
||||||
func (r *MutationResolver) RemoveStoryTag(ctx context.Context, args *StoryTagRemoveArgs) (*types.StoryResolver, error) {
|
|
||||||
input := args.Input
|
|
||||||
tag := story.Tag{Kind: input.Tag.Kind, Name: input.Tag.Name}
|
|
||||||
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
if user == nil || !user.Permitted("member", "story.edit") {
|
|
||||||
return nil, ErrUnauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
story, err := story.FindID(input.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if story.Author != user.ID && !user.Permitted("story.edit") {
|
|
||||||
return nil, ErrPermissionDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
err = story.RemoveTag(tag)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
go change.Submit("Story", "remove.tag", user.ID, story.ID, map[string]interface{}{
|
|
||||||
"kind": tag.Kind,
|
|
||||||
"name": tag.Name,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &types.StoryResolver{S: story}, nil
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
// Package mutations contains resolvers for individual GrahpQL mutations. They were previously mixed in with one another, but that caused
|
|
||||||
// difficulty seeking out specific mutations.
|
|
||||||
package mutations
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
// MutationResolver is a resolver for all mutations. The stuttery name is due to being embedded in the root resolver.
|
|
||||||
type MutationResolver struct{}
|
|
||||||
|
|
||||||
// ErrUnauthorized is when a guest acts like they own the place
|
|
||||||
var ErrUnauthorized = errors.New("Unauthorized")
|
|
||||||
|
|
||||||
// ErrPermissionDenied is returned when users act above their station
|
|
||||||
var ErrPermissionDenied = errors.New("Permission denied")
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/channel"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChannelArgs is args for channel query
|
|
||||||
type ChannelArgs struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Channel resolves the channel query
|
|
||||||
func (r *QueryResolver) Channel(ctx context.Context, args *ChannelArgs) (*types.ChannelResolver, error) {
|
|
||||||
channel, err := channel.FindName(args.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.ChannelResolver{C: channel}, nil
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/channel"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChannelsArgs is args for channel query
|
|
||||||
type ChannelsArgs struct {
|
|
||||||
Logged *bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Channels resolves the channels query
|
|
||||||
func (r *QueryResolver) Channels(ctx context.Context, args *ChannelsArgs) ([]*types.ChannelResolver, error) {
|
|
||||||
channels, err := channel.List(args.Logged != nil && *args.Logged)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*types.ChannelResolver, len(channels))
|
|
||||||
for i := range channels {
|
|
||||||
resolvers[i] = &types.ChannelResolver{C: channels[i]}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChapterArgs is args for chapter query
|
|
||||||
type ChapterArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chapter resolves the chapter query
|
|
||||||
func (r *QueryResolver) Chapter(ctx context.Context, args *ChapterArgs) (*types.ChapterResolver, error) {
|
|
||||||
chapter, err := story.FindChapterID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.ChapterResolver{C: chapter}, nil
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrIncorrectArguments is returned by character query.
|
|
||||||
var ErrIncorrectArguments = errors.New("You can only query character by ID or Nick")
|
|
||||||
|
|
||||||
// CharacterArgs is args for character query
|
|
||||||
type CharacterArgs struct {
|
|
||||||
ID *string
|
|
||||||
Nick *string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Character resolves the character query
|
|
||||||
func (r *QueryResolver) Character(ctx context.Context, args *CharacterArgs) (*types.CharacterResolver, error) {
|
|
||||||
var char character.Character
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if args.Nick != nil && args.ID != nil {
|
|
||||||
return nil, ErrIncorrectArguments
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case args.ID != nil:
|
|
||||||
char, err = character.FindID(*args.ID)
|
|
||||||
case args.Nick != nil:
|
|
||||||
char, err = character.FindNick(*args.Nick)
|
|
||||||
default:
|
|
||||||
err = ErrIncorrectArguments
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.CharacterResolver{C: char}, nil
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/loader"
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CharactersArgs is args for characters query
|
|
||||||
type CharactersArgs struct {
|
|
||||||
IDs *[]string
|
|
||||||
Nicks *[]string
|
|
||||||
Author *string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Characters resolves the characters query
|
|
||||||
func (r *QueryResolver) Characters(ctx context.Context, args *CharactersArgs) ([]*types.CharacterResolver, error) {
|
|
||||||
var chars []character.Character
|
|
||||||
var err error
|
|
||||||
|
|
||||||
loader := loader.FromContext(ctx)
|
|
||||||
if loader == nil {
|
|
||||||
return nil, errors.New("no loader")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case args.IDs != nil:
|
|
||||||
chars, err = character.ListIDs(*args.IDs...)
|
|
||||||
case args.Nicks != nil:
|
|
||||||
chars, err = character.ListNicks(*args.Nicks...)
|
|
||||||
case args.Author != nil:
|
|
||||||
chars, err = character.ListAuthor(*args.Author)
|
|
||||||
default:
|
|
||||||
chars, err = character.List()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*types.CharacterResolver, 0, len(chars))
|
|
||||||
for i := range chars {
|
|
||||||
if chars[i].ID == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers = append(resolvers, &types.CharacterResolver{C: chars[i]})
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/file"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileArgs is args for file query
|
|
||||||
type FileArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// File resolves the file query
|
|
||||||
func (r *QueryResolver) File(ctx context.Context, args *FileArgs) (*types.FileResolver, error) {
|
|
||||||
file, err := file.FindID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.FileResolver{F: file}, nil
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
"git.aiterp.net/rpdata/api/model/file"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FilesArgs is args for files query
|
|
||||||
type FilesArgs struct {
|
|
||||||
IncludePublic *bool
|
|
||||||
MimeTypes *[]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Files resolves the file query
|
|
||||||
func (r *QueryResolver) Files(ctx context.Context, args *FilesArgs) ([]*types.FileResolver, error) {
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
author := ""
|
|
||||||
if user != nil {
|
|
||||||
author = user.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
public := args.IncludePublic != nil && *args.IncludePublic == true
|
|
||||||
|
|
||||||
mimeTypes := []string(nil)
|
|
||||||
if args.MimeTypes != nil {
|
|
||||||
mimeTypes = *args.MimeTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
files, err := file.List(author, public, mimeTypes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*types.FileResolver, len(files))
|
|
||||||
for i := range files {
|
|
||||||
resolvers[i] = &types.FileResolver{F: files[i]}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LogArgs is args for log query
|
|
||||||
type LogArgs struct {
|
|
||||||
ID *string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log resolves the log query
|
|
||||||
func (r *QueryResolver) Log(ctx context.Context, args *LogArgs) (*types.LogResolver, error) {
|
|
||||||
var l log.Log
|
|
||||||
var err error
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case args.ID != nil:
|
|
||||||
l, err = log.FindID(*args.ID)
|
|
||||||
default:
|
|
||||||
err = ErrCannotResolve
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.LogResolver{L: l}, nil
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LogsArgs is args for the logs query
|
|
||||||
type LogsArgs struct {
|
|
||||||
Filter *struct {
|
|
||||||
Search *string
|
|
||||||
Characters *[]string
|
|
||||||
Channels *[]string
|
|
||||||
Events *[]string
|
|
||||||
Open *bool
|
|
||||||
Limit *int32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logs resolves the logs query
|
|
||||||
func (r *QueryResolver) Logs(ctx context.Context, args *LogsArgs) ([]*types.LogResolver, error) {
|
|
||||||
var logs []log.Log
|
|
||||||
var err error
|
|
||||||
|
|
||||||
filter := args.Filter
|
|
||||||
|
|
||||||
if filter != nil {
|
|
||||||
limit := 100
|
|
||||||
search := ""
|
|
||||||
|
|
||||||
if filter.Search != nil {
|
|
||||||
search = *filter.Search
|
|
||||||
limit = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
channels := []string(nil)
|
|
||||||
if filter.Channels != nil {
|
|
||||||
channels = *filter.Channels
|
|
||||||
limit = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
characters := []string(nil)
|
|
||||||
if filter.Characters != nil {
|
|
||||||
characters = *filter.Characters
|
|
||||||
limit = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
events := []string(nil)
|
|
||||||
if filter.Events != nil {
|
|
||||||
events = *filter.Events
|
|
||||||
limit = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if filter.Limit != nil {
|
|
||||||
limit = int(*filter.Limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
open := filter.Open != nil && *filter.Open == true
|
|
||||||
|
|
||||||
logs, err = log.ListSearch(search, channels, characters, events, open, limit)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logs, err = log.List(100)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*types.LogResolver, len(logs))
|
|
||||||
for i := range logs {
|
|
||||||
resolvers[i] = &types.LogResolver{L: logs[i]}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostArgs is args for the post query
|
|
||||||
type PostArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post resolves the post query
|
|
||||||
func (r *QueryResolver) Post(ctx context.Context, args *PostArgs) (*types.PostResolver, error) {
|
|
||||||
post, err := log.FindPostID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.PostResolver{P: post}, nil
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostsArgs is args for the posts query
|
|
||||||
type PostsArgs struct {
|
|
||||||
IDs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Posts resolves the posts query
|
|
||||||
func (r *QueryResolver) Posts(ctx context.Context, args *PostsArgs) ([]*types.PostResolver, error) {
|
|
||||||
posts, err := log.ListPostIDs(args.IDs...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*types.PostResolver, len(posts))
|
|
||||||
for i := range resolvers {
|
|
||||||
resolvers[i] = &types.PostResolver{P: posts[i]}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
// Package queries contains resolvers for individual GrahpQL queries. They were previously mixed in with one another, but that caused
|
|
||||||
// difficulty seeking out specific queries.
|
|
||||||
package queries
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
// QueryResolver is a resolver for all queries. The stuttery name is due to being embedded in the root resolver.
|
|
||||||
type QueryResolver struct{}
|
|
||||||
|
|
||||||
// ErrCannotResolve is returned when a resolver constructor is at its wit's end
|
|
||||||
var ErrCannotResolve = errors.New("Cannot resolve due to invalid arguments")
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Session resolves query.session
|
|
||||||
func (r *QueryResolver) Session(ctx context.Context) (*types.SessionResolver, error) {
|
|
||||||
return &types.SessionResolver{S: session.FromContext(ctx)}, nil
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StoriesArg is args for stories query
|
|
||||||
type StoriesArg struct {
|
|
||||||
Filter *struct {
|
|
||||||
Author *string
|
|
||||||
Tags *[]struct {
|
|
||||||
Kind string
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
EarliestFictionalDate *string
|
|
||||||
LatestFictionalDate *string
|
|
||||||
Limit *int32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stories resolves the stories query
|
|
||||||
func (r *QueryResolver) Stories(ctx context.Context, args *StoriesArg) ([]*types.StoryResolver, error) {
|
|
||||||
filter := args.Filter
|
|
||||||
|
|
||||||
author := ""
|
|
||||||
if filter != nil && filter.Author != nil {
|
|
||||||
author = *filter.Author
|
|
||||||
}
|
|
||||||
|
|
||||||
tags := make([]story.Tag, 0, 8)
|
|
||||||
if filter != nil && filter.Tags != nil {
|
|
||||||
for _, tagInput := range *filter.Tags {
|
|
||||||
tags = append(tags, story.Tag{
|
|
||||||
Kind: tagInput.Kind,
|
|
||||||
Name: tagInput.Name,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
earliest := time.Time{}
|
|
||||||
err := error(nil)
|
|
||||||
if filter != nil && filter.EarliestFictionalDate != nil {
|
|
||||||
earliest, err = time.Parse(time.RFC3339Nano, *filter.EarliestFictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
latest := time.Time{}
|
|
||||||
if filter != nil && filter.LatestFictionalDate != nil {
|
|
||||||
latest, err = time.Parse(time.RFC3339Nano, *filter.LatestFictionalDate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
limit := 30
|
|
||||||
if filter != nil && filter.Limit != nil {
|
|
||||||
limit = int(*filter.Limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
stories, err := story.List(author, tags, earliest, latest, limit)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*types.StoryResolver, len(stories))
|
|
||||||
for i, story := range stories {
|
|
||||||
resolvers[i] = &types.StoryResolver{S: story}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StoryArgs is args for story query
|
|
||||||
type StoryArgs struct {
|
|
||||||
ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Story resolves the story query
|
|
||||||
func (r *QueryResolver) Story(ctx context.Context, args *StoryArgs) (*types.StoryResolver, error) {
|
|
||||||
story, err := story.FindID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.StoryResolver{S: story}, nil
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Tags resolves the tags query
|
|
||||||
func (r *QueryResolver) Tags() ([]*types.TagResolver, error) {
|
|
||||||
tags, err := story.ListTags()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*types.TagResolver, len(tags))
|
|
||||||
for i, tag := range tags {
|
|
||||||
resolvers[i] = &types.TagResolver{T: tag}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/mutations"
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/queries"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The Resolver combines the query and mutation resolvers from the subpackages.
|
|
||||||
// This is the one to pass along with the schema.
|
|
||||||
type Resolver struct {
|
|
||||||
queries.QueryResolver
|
|
||||||
mutations.MutationResolver
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import "git.aiterp.net/rpdata/api/model/channel"
|
|
||||||
|
|
||||||
// ChannelResolver for the Channel graphql type
|
|
||||||
type ChannelResolver struct{ C channel.Channel }
|
|
||||||
|
|
||||||
// Name resolves channel.name
|
|
||||||
func (r *ChannelResolver) Name() string {
|
|
||||||
return r.C.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logged resolves channel.logged
|
|
||||||
func (r *ChannelResolver) Logged() bool {
|
|
||||||
return r.C.Logged
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hub resolves channel.hub
|
|
||||||
func (r *ChannelResolver) Hub() bool {
|
|
||||||
return r.C.Hub
|
|
||||||
}
|
|
||||||
|
|
||||||
// EventName resolves channel.eventName
|
|
||||||
func (r *ChannelResolver) EventName() *string {
|
|
||||||
if r.C.Event == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &r.C.Event
|
|
||||||
}
|
|
||||||
|
|
||||||
// LocationName resolves channel.locationName
|
|
||||||
func (r *ChannelResolver) LocationName() *string {
|
|
||||||
if r.C.Location == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &r.C.Location
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChapterResolver for the Chapter graphql type
|
|
||||||
type ChapterResolver struct{ C story.Chapter }
|
|
||||||
|
|
||||||
// ID resolves Chapter.id
|
|
||||||
func (r *ChapterResolver) ID() string {
|
|
||||||
return r.C.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// StoryID resolves Chapter.storyId
|
|
||||||
func (r *ChapterResolver) StoryID() string {
|
|
||||||
return r.C.StoryID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Title resolves Chapter.title
|
|
||||||
func (r *ChapterResolver) Title() string {
|
|
||||||
return r.C.Title
|
|
||||||
}
|
|
||||||
|
|
||||||
// Author resolves Chapter.author
|
|
||||||
func (r *ChapterResolver) Author() string {
|
|
||||||
return r.C.Author
|
|
||||||
}
|
|
||||||
|
|
||||||
// Source resolves Chapter.source
|
|
||||||
func (r *ChapterResolver) Source() string {
|
|
||||||
return r.C.Source
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreatedDate resolves Chapter.createdDate
|
|
||||||
func (r *ChapterResolver) CreatedDate() string {
|
|
||||||
return r.C.CreatedDate.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FictionalDate resolves Chapter.fictionalDate
|
|
||||||
func (r *ChapterResolver) FictionalDate() string {
|
|
||||||
return r.C.FictionalDate.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditedDate resolves Chapter.editedDate
|
|
||||||
func (r *ChapterResolver) EditedDate() string {
|
|
||||||
return r.C.EditedDate.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import "git.aiterp.net/rpdata/api/model/character"
|
|
||||||
|
|
||||||
// CharacterResolver for the Character graphql type
|
|
||||||
type CharacterResolver struct{ C character.Character }
|
|
||||||
|
|
||||||
// ID is a property resolver
|
|
||||||
func (r *CharacterResolver) ID() string {
|
|
||||||
return r.C.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nick is a property resolver
|
|
||||||
func (r *CharacterResolver) Nick() *string {
|
|
||||||
if len(r.C.Nicks) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &r.C.Nicks[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nicks is a property resolver
|
|
||||||
func (r *CharacterResolver) Nicks() []string {
|
|
||||||
return r.C.Nicks
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name is a property resolver
|
|
||||||
func (r *CharacterResolver) Name() string {
|
|
||||||
return r.C.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShortName is a property resolver
|
|
||||||
func (r *CharacterResolver) ShortName() string {
|
|
||||||
return r.C.ShortName
|
|
||||||
}
|
|
||||||
|
|
||||||
// Author is a property resolver
|
|
||||||
func (r *CharacterResolver) Author() string {
|
|
||||||
return r.C.Author
|
|
||||||
}
|
|
||||||
|
|
||||||
// Description is a property resolver
|
|
||||||
func (r *CharacterResolver) Description() string {
|
|
||||||
return r.C.Description
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/model/file"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileResolver for the File graphql type
|
|
||||||
type FileResolver struct{ F file.File }
|
|
||||||
|
|
||||||
// ID resolves File.id
|
|
||||||
func (f *FileResolver) ID() string {
|
|
||||||
return f.F.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Author resolves File.author
|
|
||||||
func (f *FileResolver) Author() string {
|
|
||||||
return f.F.Author
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kind resolves File.kind
|
|
||||||
func (f *FileResolver) Kind() string {
|
|
||||||
return f.F.Kind
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time resolves File.time
|
|
||||||
func (f *FileResolver) Time() string {
|
|
||||||
return f.F.Time.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public resolves File.public
|
|
||||||
func (f *FileResolver) Public() bool {
|
|
||||||
return f.F.Public
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name resolves File.name
|
|
||||||
func (f *FileResolver) Name() string {
|
|
||||||
return f.F.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// MimeType resolves File.mimeType
|
|
||||||
func (f *FileResolver) MimeType() string {
|
|
||||||
return f.F.MimeType
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size resolves File.size
|
|
||||||
func (f *FileResolver) Size() int32 {
|
|
||||||
return int32(f.F.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// URL resolves File.url
|
|
||||||
func (f *FileResolver) URL() *string {
|
|
||||||
if f.F.URL == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &f.F.URL
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/loader"
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LogResolver for the Log graphql type
|
|
||||||
type LogResolver struct{ L log.Log }
|
|
||||||
|
|
||||||
// ID resolves Log.id
|
|
||||||
func (r *LogResolver) ID() string {
|
|
||||||
return r.L.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShortID resolves Log.shortId
|
|
||||||
func (r *LogResolver) ShortID() string {
|
|
||||||
return r.L.ShortID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Date resolves Log.date
|
|
||||||
func (r *LogResolver) Date() string {
|
|
||||||
return r.L.Date.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChannelName resolves Log.channelName
|
|
||||||
func (r *LogResolver) ChannelName() string {
|
|
||||||
return r.L.Channel
|
|
||||||
}
|
|
||||||
|
|
||||||
// Channel resolves Log.channe
|
|
||||||
func (r *LogResolver) Channel(ctx context.Context) (*ChannelResolver, error) {
|
|
||||||
loader := loader.FromContext(ctx)
|
|
||||||
if loader == nil {
|
|
||||||
return nil, errors.New("no loader")
|
|
||||||
}
|
|
||||||
|
|
||||||
channel, err := loader.Channel("name", r.L.Channel)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ChannelResolver{C: channel}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Title resolves Log.title
|
|
||||||
func (r *LogResolver) Title() string {
|
|
||||||
return r.L.Title
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event resolves Log.event
|
|
||||||
func (r *LogResolver) Event() string {
|
|
||||||
return r.L.Event
|
|
||||||
}
|
|
||||||
|
|
||||||
// Description resolves Log.description
|
|
||||||
func (r *LogResolver) Description() string {
|
|
||||||
return r.L.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open resolves Log.open
|
|
||||||
func (r *LogResolver) Open() bool {
|
|
||||||
return r.L.Open
|
|
||||||
}
|
|
||||||
|
|
||||||
// Characters resolves Log.characters
|
|
||||||
func (r *LogResolver) Characters(ctx context.Context) ([]*CharacterResolver, error) {
|
|
||||||
loader := loader.FromContext(ctx)
|
|
||||||
if loader == nil {
|
|
||||||
return nil, errors.New("no loader")
|
|
||||||
}
|
|
||||||
|
|
||||||
chars, err := loader.Characters("id", r.L.CharacterIDs...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*CharacterResolver, 0, len(chars))
|
|
||||||
for i := range chars {
|
|
||||||
if chars[i].ID == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers = append(resolvers, &CharacterResolver{C: chars[i]})
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Posts resolves Log.posts
|
|
||||||
func (r *LogResolver) Posts(ctx context.Context, args *LogPostArgs) ([]*PostResolver, error) {
|
|
||||||
var kinds []string
|
|
||||||
if args.Kinds != nil {
|
|
||||||
kinds = *args.Kinds
|
|
||||||
}
|
|
||||||
|
|
||||||
posts, err := r.L.Posts(kinds...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*PostResolver, len(posts))
|
|
||||||
for i := range posts {
|
|
||||||
resolvers[i] = &PostResolver{posts[i]}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogPostArgs is an arg
|
|
||||||
type LogPostArgs struct {
|
|
||||||
Kinds *[]string
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/model/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PostResolver for the Post graphql type
|
|
||||||
type PostResolver struct{ P log.Post }
|
|
||||||
|
|
||||||
// ID resolves Post.id
|
|
||||||
func (r *PostResolver) ID() string {
|
|
||||||
return r.P.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogID resolves Post.logId
|
|
||||||
func (r *PostResolver) LogID() string {
|
|
||||||
return r.P.LogID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time resolves Post.time
|
|
||||||
func (r *PostResolver) Time() string {
|
|
||||||
return r.P.Time.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kind resolves Post.logId
|
|
||||||
func (r *PostResolver) Kind() string {
|
|
||||||
return r.P.Kind
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nick resolves Post.nick
|
|
||||||
func (r *PostResolver) Nick() string {
|
|
||||||
return r.P.Nick
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text resolves Post.text
|
|
||||||
func (r *PostResolver) Text() string {
|
|
||||||
return r.P.Text
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position resolves Post.text
|
|
||||||
func (r *PostResolver) Position() int32 {
|
|
||||||
return int32(r.P.Position)
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import "git.aiterp.net/rpdata/api/internal/session"
|
|
||||||
|
|
||||||
// SessionResolver resolves Session
|
|
||||||
type SessionResolver struct{ S *session.Session }
|
|
||||||
|
|
||||||
// User resolves Session.user
|
|
||||||
func (r *SessionResolver) User() *UserResolver {
|
|
||||||
user := r.S.User()
|
|
||||||
if user == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UserResolver{U: user}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StoryResolver for the Story graphql type
|
|
||||||
type StoryResolver struct{ S story.Story }
|
|
||||||
|
|
||||||
// ID resolves Story.id
|
|
||||||
func (r *StoryResolver) ID() string {
|
|
||||||
return r.S.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Author resolves Story.author
|
|
||||||
func (r *StoryResolver) Author() string {
|
|
||||||
return r.S.Author
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name resolves Story.name
|
|
||||||
func (r *StoryResolver) Name() string {
|
|
||||||
return r.S.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Category resolves Story.category
|
|
||||||
func (r *StoryResolver) Category() string {
|
|
||||||
return r.S.Category
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open resolves Story.open
|
|
||||||
func (r *StoryResolver) Open() bool {
|
|
||||||
return r.S.Open
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listed resolves Story.listed
|
|
||||||
func (r *StoryResolver) Listed() bool {
|
|
||||||
return r.S.Listed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tags resolves Story.tags
|
|
||||||
func (r *StoryResolver) Tags() []*TagResolver {
|
|
||||||
resolvers := make([]*TagResolver, len(r.S.Tags))
|
|
||||||
for i, tag := range r.S.Tags {
|
|
||||||
resolvers[i] = &TagResolver{T: tag}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chapters resolves Story.chapters
|
|
||||||
func (r *StoryResolver) Chapters() ([]*ChapterResolver, error) {
|
|
||||||
chapters, err := r.S.Chapters()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*ChapterResolver, len(chapters))
|
|
||||||
for i, chapter := range chapters {
|
|
||||||
resolvers[i] = &ChapterResolver{C: chapter}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvers, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreatedDate resolves Story.createdDate
|
|
||||||
func (r *StoryResolver) CreatedDate() string {
|
|
||||||
return r.S.CreatedDate.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FictionalDate resolves Story.fictionalDate
|
|
||||||
func (r *StoryResolver) FictionalDate() string {
|
|
||||||
return r.S.FictionalDate.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdatedDate resolves Story.updatedDate
|
|
||||||
func (r *StoryResolver) UpdatedDate() string {
|
|
||||||
return r.S.UpdatedDate.Format(time.RFC3339Nano)
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import "git.aiterp.net/rpdata/api/model/story"
|
|
||||||
|
|
||||||
// TagResolver for the Tag graphql type
|
|
||||||
type TagResolver struct{ T story.Tag }
|
|
||||||
|
|
||||||
// Kind resolves Tag.kind
|
|
||||||
func (r *TagResolver) Kind() string {
|
|
||||||
return r.T.Kind
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name resolves Tag.name
|
|
||||||
func (r *TagResolver) Name() string {
|
|
||||||
return r.T.Name
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user