Compare commits
131
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
162ccf6bfb | ||
|
|
7e3dc49635 | ||
|
|
aff0d99842 | ||
|
|
00150118d2 | ||
|
|
332a1eb32b | ||
|
|
db4d46c368 | ||
|
|
a8c8610ca2 | ||
|
|
d09c17d30d | ||
|
|
e3e3ea07db | ||
|
|
22592439da | ||
|
|
dfa9fb4025 | ||
|
|
0e2a68a2d4 | ||
|
|
1eefa65527 | ||
|
|
f9b6af58c9 | ||
|
|
56ecf48b57 | ||
|
|
06fbfc90c5 | ||
|
|
39a4fef506 | ||
|
|
f9fe0bb5f8 | ||
|
|
d22ab387dd | ||
|
|
53a86c0b9c | ||
|
|
e0b93c6b4b | ||
|
|
1ea04f1577 | ||
|
|
17fd3c60f8 | ||
|
|
c5b62a42db | ||
|
|
fa0926c311 | ||
|
|
d21efc1c7f | ||
|
|
852030b141 | ||
|
|
f7f0b76379 | ||
|
|
2711654816 | ||
|
|
b60897a597 | ||
|
|
80e6c048c9 | ||
|
|
6310cbbc1e | ||
|
|
89a1c2366c | ||
|
|
ac2b79e88a | ||
|
|
31239330df | ||
|
|
a58535fcb9 | ||
|
|
2a91b6f9bc | ||
|
|
caa7727c02 | ||
|
|
047c9784ae | ||
|
|
d038c1cfea | ||
|
|
7e812bd615 | ||
|
|
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 |
+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
@@ -4,4 +4,10 @@ config.json
|
|||||||
api
|
api
|
||||||
debug
|
debug
|
||||||
build
|
build
|
||||||
.vscode
|
rpdata-graphiql
|
||||||
|
rpdata-*
|
||||||
|
!rpdata-*/
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
generated.gql
|
||||||
|
generated.go
|
||||||
+16
-34
@@ -1,50 +1,32 @@
|
|||||||
## 1. Server
|
## 1. Build Server
|
||||||
# Use Go 1.10
|
# Use Go 1.12
|
||||||
FROM golang:1.10 AS build-server
|
FROM golang:1.12 AS build-server
|
||||||
|
|
||||||
# Load repository into docker
|
# Load repository into docker
|
||||||
WORKDIR /go/src/git.aiterp.net/rpdata/api/
|
WORKDIR /project/
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Load build tools and dependencies
|
# Install build tools and dependencies
|
||||||
RUN go get -u github.com/golang/dep/cmd/dep
|
|
||||||
RUN go get -u github.com/jteeuwen/go-bindata/...
|
|
||||||
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 -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 -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 -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 -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 -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 -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
|
||||||
|
|
||||||
# Install certificates to enable HTTPS GET requests
|
# Install certificates to enable HTTPS GET requests, and tzdata for log imports.
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates tzdata
|
||||||
|
|
||||||
# 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
-178
@@ -1,178 +0,0 @@
|
|||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "git.aiterp.net/aiterp/wikiauth"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "33860de804ddcec4fc17998745233b4ec477e7c2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/dustin/go-humanize"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "bb3d318650d48840a39aa21a027c6630e198e626"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/globalsign/mgo"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"bson",
|
|
||||||
"internal/json",
|
|
||||||
"internal/sasl",
|
|
||||||
"internal/scram"
|
|
||||||
]
|
|
||||||
revision = "f76e4f9da92ecd56e3be26f5ba92580af1ef97b4"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/go-ini/ini"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "ace140f73450505f33e8b8418216792275ae82a7"
|
|
||||||
version = "v1.35.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/go-sql-driver/mysql"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
|
||||||
version = "v1.4.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/graph-gophers/dataloader"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "78139374585c29dcb97b8f33089ed11959e4be59"
|
|
||||||
version = "v5"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/graph-gophers/graphql-go"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"errors",
|
|
||||||
"internal/common",
|
|
||||||
"internal/exec",
|
|
||||||
"internal/exec/packer",
|
|
||||||
"internal/exec/resolvable",
|
|
||||||
"internal/exec/selected",
|
|
||||||
"internal/query",
|
|
||||||
"internal/schema",
|
|
||||||
"internal/validation",
|
|
||||||
"introspection",
|
|
||||||
"log",
|
|
||||||
"relay",
|
|
||||||
"trace"
|
|
||||||
]
|
|
||||||
revision = "9ebf33af539ab8cb832c7107bc0a978ca8dbc0de"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/jmoiron/sqlx"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"reflectx"
|
|
||||||
]
|
|
||||||
revision = "0dae4fefe7c0e190f7b5a78dac28a1c82cc8d849"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/minio/minio-go"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"pkg/credentials",
|
|
||||||
"pkg/encrypt",
|
|
||||||
"pkg/s3signer",
|
|
||||||
"pkg/s3utils",
|
|
||||||
"pkg/set"
|
|
||||||
]
|
|
||||||
revision = "3d2d02921f0510e9d1f66ef77a265b8dddd36992"
|
|
||||||
version = "6.0.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/mitchellh/go-homedir"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "b8bc1bf767474819792c23f32d8286a45736f1c6"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/opentracing/opentracing-go"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"ext",
|
|
||||||
"log"
|
|
||||||
]
|
|
||||||
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
|
|
||||||
version = "v1.0.2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/sadbox/mediawiki"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "39fea8a1336076a961a300d1d95765dcd17e8a3c"
|
|
||||||
version = "v0.1"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/sirupsen/logrus"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
|
||||||
version = "v1.0.5"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/crypto"
|
|
||||||
packages = [
|
|
||||||
"argon2",
|
|
||||||
"blake2b",
|
|
||||||
"ssh/terminal"
|
|
||||||
]
|
|
||||||
revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
packages = [
|
|
||||||
"context",
|
|
||||||
"idna",
|
|
||||||
"lex/httplex"
|
|
||||||
]
|
|
||||||
revision = "a35a21de978d84ffc92f010a153705b170b2f9d1"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
packages = [
|
|
||||||
"unix",
|
|
||||||
"windows"
|
|
||||||
]
|
|
||||||
revision = "2f57af4873d00d535c5c9028850aa2152e6a5566"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "golang.org/x/text"
|
|
||||||
packages = [
|
|
||||||
"collate",
|
|
||||||
"collate/build",
|
|
||||||
"internal/colltab",
|
|
||||||
"internal/gen",
|
|
||||||
"internal/tag",
|
|
||||||
"internal/triegen",
|
|
||||||
"internal/ucd",
|
|
||||||
"language",
|
|
||||||
"secure/bidirule",
|
|
||||||
"transform",
|
|
||||||
"unicode/bidi",
|
|
||||||
"unicode/cldr",
|
|
||||||
"unicode/norm",
|
|
||||||
"unicode/rangetable"
|
|
||||||
]
|
|
||||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
|
||||||
version = "v0.3.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "google.golang.org/appengine"
|
|
||||||
packages = ["cloudsql"]
|
|
||||||
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
|
|
||||||
version = "v1.1.0"
|
|
||||||
|
|
||||||
[solve-meta]
|
|
||||||
analyzer-name = "dep"
|
|
||||||
analyzer-version = 1
|
|
||||||
inputs-digest = "16fd84401bc5796ffeaa895f31d099e1a23b363b15b87386877de0829ac9575b"
|
|
||||||
solver-name = "gps-cdcl"
|
|
||||||
solver-version = 1
|
|
||||||
-41
@@ -1,41 +0,0 @@
|
|||||||
# Gopkg.toml example
|
|
||||||
#
|
|
||||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
|
||||||
# for detailed Gopkg.toml documentation.
|
|
||||||
#
|
|
||||||
# required = ["github.com/user/thing/cmd/thing"]
|
|
||||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project"
|
|
||||||
# version = "1.0.0"
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project2"
|
|
||||||
# branch = "dev"
|
|
||||||
# source = "github.com/myfork/project2"
|
|
||||||
#
|
|
||||||
# [[override]]
|
|
||||||
# name = "github.com/x/y"
|
|
||||||
# version = "2.4.0"
|
|
||||||
#
|
|
||||||
# [prune]
|
|
||||||
# non-go = false
|
|
||||||
# go-tests = true
|
|
||||||
# unused-packages = true
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/globalsign/mgo"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/minio/minio-go"
|
|
||||||
version = "6.0.0"
|
|
||||||
|
|
||||||
[prune]
|
|
||||||
go-tests = true
|
|
||||||
unused-packages = true
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/graph-gophers/graphql-go"
|
|
||||||
@@ -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, models.ChapterCommentModeDisabled)
|
||||||
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, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
"git.aiterp.net/rpdata/api/models/logs"
|
||||||
|
"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")
|
||||||
|
}()
|
||||||
|
|
||||||
|
go logListedChanges()
|
||||||
|
|
||||||
|
log.Fatal(http.ListenAndServe(":8081", nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func logListedChanges() {
|
||||||
|
sub := changes.Subscribe(context.Background(), nil, true)
|
||||||
|
|
||||||
|
for change := range sub {
|
||||||
|
log.Printf("Change: Author=%#+v Model=%#+v Op=%#+v", change.Author, change.Model, change.Op)
|
||||||
|
for _, object := range change.Objects() {
|
||||||
|
switch object := object.(type) {
|
||||||
|
case models.Log:
|
||||||
|
log.Printf("\tLog: %s (%s)", object.ID, object.ShortID)
|
||||||
|
case models.Character:
|
||||||
|
log.Printf("\tCharacter: %s", object.ID)
|
||||||
|
case models.Channel:
|
||||||
|
log.Printf("\tChannel: %s", object.Name)
|
||||||
|
case models.Post:
|
||||||
|
log.Printf("\tPost: %s", object.ID)
|
||||||
|
case models.Story:
|
||||||
|
log.Printf("\tStory: %s", object.ID)
|
||||||
|
case models.Tag:
|
||||||
|
log.Printf("\tTag: (%s,%s)", object.Kind, object.Name)
|
||||||
|
case models.Chapter:
|
||||||
|
log.Printf("\tChapter: %s", object.ID)
|
||||||
|
case models.Comment:
|
||||||
|
log.Printf("\tComment: %s", object.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Change subscription closed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryHandler() http.HandlerFunc {
|
||||||
|
handler := handler.GraphQL(
|
||||||
|
graph2.New(),
|
||||||
|
handler.RecoverFunc(func(ctx context.Context, err interface{}) error {
|
||||||
|
log.Println(err)
|
||||||
|
log.Println(string(debug.Stack()))
|
||||||
|
|
||||||
|
return fmt.Errorf("The server failed to serve your request due to an internal error, it has been logged")
|
||||||
|
}),
|
||||||
|
handler.ComplexityLimit(300),
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
module git.aiterp.net/rpdata/api
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/99designs/gqlgen v0.8.0
|
||||||
|
github.com/agnivade/levenshtein v1.0.1
|
||||||
|
github.com/davecgh/go-spew v1.1.1
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4
|
||||||
|
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e
|
||||||
|
github.com/go-ini/ini v1.35.0
|
||||||
|
github.com/go-sql-driver/mysql v1.4.0
|
||||||
|
github.com/gorilla/websocket v1.4.0
|
||||||
|
github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0
|
||||||
|
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0
|
||||||
|
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05
|
||||||
|
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747
|
||||||
|
github.com/opentracing/opentracing-go v1.0.2
|
||||||
|
github.com/pkg/errors v0.8.1
|
||||||
|
github.com/pmezard/go-difflib v1.0.0
|
||||||
|
github.com/sirupsen/logrus v1.0.5
|
||||||
|
github.com/stretchr/testify v1.3.0
|
||||||
|
github.com/urfave/cli v1.20.0
|
||||||
|
github.com/vektah/gqlparser v1.1.0
|
||||||
|
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06
|
||||||
|
golang.org/x/net v0.0.0-20180416171110-a35a21de978d
|
||||||
|
golang.org/x/sys v0.0.0-20180416112224-2f57af4873d0
|
||||||
|
golang.org/x/text v0.3.0
|
||||||
|
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6
|
||||||
|
google.golang.org/appengine v1.1.0
|
||||||
|
gopkg.in/yaml.v2 v2.2.2
|
||||||
|
)
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
github.com/99designs/gqlgen v0.5.1 h1:cRsbpZgX83PrXb0/hj5EkNdmaVN4l/Eii81Z8LCexgY=
|
||||||
|
github.com/99designs/gqlgen v0.5.1/go.mod h1:KSQDfLlTTGmzlRgLGm6HeKKKo598l5E2svEM6Nz2Jnw=
|
||||||
|
github.com/99designs/gqlgen v0.8.0 h1:ZBteuSgeeFwn+mztjDqQZQdVa9pqslmPnDeCovcnc0Y=
|
||||||
|
github.com/99designs/gqlgen v0.8.0/go.mod h1:st7qHA6ssU3uRZkmv+wzrzgX4srvIqEIdE5iuRW8GhE=
|
||||||
|
github.com/99designs/gqlgen v0.8.3 h1:I6bMglXNKkn4KlvkSMzqZw53e1N2FF9Gud4NmsOxqiA=
|
||||||
|
github.com/99designs/gqlgen v0.8.3/go.mod h1:aLyJw9xUgdJxZ8EqNQxo2pGFhXXJ/hq8t7J4yn8TgI4=
|
||||||
|
github.com/agnivade/levenshtein v1.0.0 h1:q+77q31bLT5jhN3BHKA1276nUEdbz7XjDa0o5dRKcZ0=
|
||||||
|
github.com/agnivade/levenshtein v1.0.0/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||||
|
github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=
|
||||||
|
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||||
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
|
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e h1:hmrbHva/wKD6X4M7pgHVbg/KfVV1wwgr1NEkQaVD3rU=
|
||||||
|
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||||
|
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||||
|
github.com/go-ini/ini v1.35.0 h1:D/my3+xOfqZMkJpciRcyqU7XMBUgiZa9qXjZIa8uv2k=
|
||||||
|
github.com/go-ini/ini v1.35.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
|
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
|
||||||
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
|
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c h1:94S+uoVVMpQAEOrqGjCDyUdML4dJDkh6aC4MYmXECg4=
|
||||||
|
github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+uGHxWtRt4C0Wjc6kJKo5XYx8xE=
|
||||||
|
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05 h1:YEyFCqmHcmbcTLqZ7yEAg7VIUat6PuDzGbIctZy888k=
|
||||||
|
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8=
|
||||||
|
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 h1:eQox4Rh4ewJF+mqYPxCkmBAirRnPaHEB26UkNuPyjlk=
|
||||||
|
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||||
|
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
|
||||||
|
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
|
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||||
|
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||||
|
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||||
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
||||||
|
github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1 h1:FYOXUtr3sYR9shto7Q/aQ1B0Onyk77aws9wGOORiz+I=
|
||||||
|
github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1/go.mod h1:K4QdSSpS2XiHHwzb18kWh3iBljB8rLC8okGXsnQy3Nc=
|
||||||
|
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
|
||||||
|
github.com/vektah/gqlparser v1.1.0/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
|
github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68=
|
||||||
|
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
|
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06 h1:EOqG0JqGlLr+punVB69jvWCv/ErZKGlC7PMdyHfv+Bc=
|
||||||
|
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180416171110-a35a21de978d h1:O2P57H5Cc+d+DJos+iweraI9rmzMYwV+45vkZdDY0Oo=
|
||||||
|
golang.org/x/net v0.0.0-20180416171110-a35a21de978d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/sys v0.0.0-20180416112224-2f57af4873d0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1 h1:dzEuQYa6+a3gROnSlgly5ERUm4SZKJt+dh+4iSbO+bI=
|
||||||
|
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 h1:iZgcI2DDp6zW5v9Z/5+f0NuqoxNdmzg4hivjk2WLXpY=
|
||||||
|
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||||
|
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||||
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,182 @@
|
|||||||
|
package graph2
|
||||||
|
|
||||||
|
import (
|
||||||
|
input "git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
changes "git.aiterp.net/rpdata/api/models/changes"
|
||||||
|
channels "git.aiterp.net/rpdata/api/models/channels"
|
||||||
|
characters "git.aiterp.net/rpdata/api/models/characters"
|
||||||
|
files "git.aiterp.net/rpdata/api/models/files"
|
||||||
|
logs "git.aiterp.net/rpdata/api/models/logs"
|
||||||
|
posts "git.aiterp.net/rpdata/api/models/posts"
|
||||||
|
stories "git.aiterp.net/rpdata/api/models/stories"
|
||||||
|
)
|
||||||
|
|
||||||
|
func complexity() (cr ComplexityRoot) {
|
||||||
|
subListComplexity := 25
|
||||||
|
bigSublistComplexity := 75
|
||||||
|
hugeSublistComplexity := 100
|
||||||
|
findComplexity := 100
|
||||||
|
listComplexity := 200
|
||||||
|
mutationComplexity := 100
|
||||||
|
|
||||||
|
cr.Query.Character = func(childComplexity int, id *string, nick *string) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Characters = func(childComplexity int, filter *characters.Filter) int {
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Channel = func(childComplexity int, name string) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Channels = func(childComplexity int, filter *channels.Filter) int {
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Post = func(childComplexity int, id string) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Posts = func(childComplexity int, filter *posts.Filter) int {
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.UnknownNicks = func(childComplexity int, filter *input.UnknownNicksFilter) int {
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Log = func(childComplexity int, id string) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Logs = func(childComplexity int, filter *logs.Filter) int {
|
||||||
|
if filter != nil && filter.Open != nil && *filter.Open == true {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Chapter = func(childComplexity int, id string) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Comment = func(childComplexity int, id string) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Tags = func(childComplexity int) int {
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Story = func(childComplexity int, id string) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Stories = func(childComplexity int, filter *stories.Filter) int {
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.File = func(childComplexity int, id string) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Files = func(childComplexity int, filter *files.Filter) int {
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Changes = func(childComplexity int, filter *changes.Filter) int {
|
||||||
|
return childComplexity + listComplexity
|
||||||
|
}
|
||||||
|
cr.Query.Token = func(childComplexity int) int {
|
||||||
|
return childComplexity + findComplexity
|
||||||
|
}
|
||||||
|
|
||||||
|
cr.Mutation.AddStory = func(childComplexity int, input input.StoryAddInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.AddStoryTag = func(childComplexity int, input input.StoryTagAddInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.RemoveStoryTag = func(childComplexity int, input input.StoryTagRemoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.EditStory = func(childComplexity int, input input.StoryEditInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.RemoveStory = func(childComplexity int, input input.StoryRemoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.AddChapter = func(childComplexity int, input input.ChapterAddInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.EditChapter = func(childComplexity int, input input.ChapterEditInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.MoveChapter = func(childComplexity int, input input.ChapterMoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.RemoveChapter = func(childComplexity int, input input.ChapterRemoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.AddComment = func(childComplexity int, input input.CommentAddInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.EditComment = func(childComplexity int, input input.CommentEditInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.RemoveComment = func(childComplexity int, input input.CommentRemoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.AddLog = func(childComplexity int, input input.LogAddInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.ImportLog = func(childComplexity int, input input.LogImportInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.EditLog = func(childComplexity int, input input.LogEditInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.RemoveLog = func(childComplexity int, input input.LogRemoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.AddPost = func(childComplexity int, input input.PostAddInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.EditPost = func(childComplexity int, input input.PostEditInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.MovePost = func(childComplexity int, input input.PostMoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.RemovePost = func(childComplexity int, input input.PostRemoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.AddCharacter = func(childComplexity int, input input.CharacterAddInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.AddCharacterNick = func(childComplexity int, input input.CharacterNickInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.RemoveCharacterNick = func(childComplexity int, input input.CharacterNickInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.EditCharacter = func(childComplexity int, input input.CharacterEditInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.RemoveCharacter = func(childComplexity int, input input.CharacterRemoveInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.AddChannel = func(childComplexity int, input input.ChannelAddInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
cr.Mutation.EditChannel = func(childComplexity int, input input.ChannelEditInput) int {
|
||||||
|
return childComplexity + mutationComplexity
|
||||||
|
}
|
||||||
|
|
||||||
|
cr.Log.Characters = func(childComplexity int) int {
|
||||||
|
return childComplexity + subListComplexity
|
||||||
|
}
|
||||||
|
cr.Log.Posts = func(childComplexity int, kinds []string) int {
|
||||||
|
return childComplexity + hugeSublistComplexity
|
||||||
|
}
|
||||||
|
|
||||||
|
cr.Story.Chapters = func(childComplexity int) int {
|
||||||
|
return childComplexity + bigSublistComplexity
|
||||||
|
}
|
||||||
|
cr.Story.Tags = func(childComplexity int) int {
|
||||||
|
return childComplexity + subListComplexity
|
||||||
|
}
|
||||||
|
|
||||||
|
cr.Chapter.Comments = func(childComplexity int, limit *int) int {
|
||||||
|
return childComplexity + subListComplexity
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
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
|
||||||
|
UnknownNick:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.UnknownNick
|
||||||
|
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
|
||||||
|
LogImporter:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.LogImporter
|
||||||
|
Comment:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.Comment
|
||||||
|
fields:
|
||||||
|
fictionalDate:
|
||||||
|
resolver: true
|
||||||
|
ChapterCommentMode:
|
||||||
|
model: git.aiterp.net/rpdata/api/models.ChapterCommentMode
|
||||||
|
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,56 @@
|
|||||||
|
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 go run github.com/99designs/gqlgen -v
|
||||||
|
|
||||||
|
// New creates a new GraphQL schema.
|
||||||
|
func New() graphql.ExecutableSchema {
|
||||||
|
return NewExecutableSchema(Config{
|
||||||
|
Resolvers: &rootResolver{},
|
||||||
|
Complexity: complexity(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type rootResolver struct{}
|
||||||
|
|
||||||
|
func (r *rootResolver) Query() QueryResolver {
|
||||||
|
return &queries.Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Mutation() MutationResolver {
|
||||||
|
return queries.MutationResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Subscription() SubscriptionResolver {
|
||||||
|
return queries.SubscriptionResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Log() LogResolver {
|
||||||
|
return &types.LogResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Comment() CommentResolver {
|
||||||
|
return &types.CommentResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Chapter() ChapterResolver {
|
||||||
|
return &types.ChapterResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Story() StoryResolver {
|
||||||
|
return &types.StoryResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Change() ChangeResolver {
|
||||||
|
return &types.ChangeResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rootResolver) Token() TokenResolver {
|
||||||
|
return &types.TokenResolver
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subscriptions
|
||||||
|
|
||||||
|
func (r *subscriptionResolver) Changes(ctx context.Context, keys []models.ChangeKey) (<-chan *models.Change, error) {
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return nil, errors.New("At least one key is required for a subscription")
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes.Subscribe(ctx, keys, false), nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
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) {
|
||||||
|
channel, err := channels.FindName(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &channel, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 nil, 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 nil, 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 nil, errors.New("You are not permitted to edit channels")
|
||||||
|
}
|
||||||
|
|
||||||
|
channel, err := channels.FindName(input.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Channel not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
channel, err = channels.Edit(channel, input.Logged, input.Hub, input.EventName, input.LocationName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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,177 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"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/chapters"
|
||||||
|
"git.aiterp.net/rpdata/api/models/comments"
|
||||||
|
"git.aiterp.net/rpdata/api/models/stories"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Queries
|
||||||
|
|
||||||
|
func (r *resolver) Chapter(ctx context.Context, id string) (*models.Chapter, error) {
|
||||||
|
chapter, err := chapters.FindID(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &chapter, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutations
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAddInput) (*models.Chapter, error) {
|
||||||
|
story, err := stories.FindID(input.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Permitted("member", "story.add") {
|
||||||
|
return nil, errors.New("Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
author := token.UserID
|
||||||
|
if input.Author != nil && *input.Author != author {
|
||||||
|
if !token.Permitted("story.add") {
|
||||||
|
return nil, errors.New("False pretender")
|
||||||
|
}
|
||||||
|
|
||||||
|
author = *input.Author
|
||||||
|
}
|
||||||
|
|
||||||
|
if !story.Open && story.Author != author {
|
||||||
|
return nil, errors.New("Story is not open")
|
||||||
|
}
|
||||||
|
|
||||||
|
commentMode := models.ChapterCommentModeDisabled
|
||||||
|
if input.CommentMode != nil {
|
||||||
|
commentMode = *input.CommentMode
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err := chapters.Add(story, input.Title, author, input.Source, time.Now(), input.FictionalDate, commentMode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 nil, errors.New("Chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.move") {
|
||||||
|
return nil, errors.New("You are not allowed to move this chapter")
|
||||||
|
}
|
||||||
|
|
||||||
|
target, err := stories.FindID(input.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Target story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !target.Open && !token.PermittedUser(target.Author, "member", "chapter.move") {
|
||||||
|
return nil, 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 nil, 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 nil, errors.New("Chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.edit") {
|
||||||
|
return nil, 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, input.CommentMode, input.CommentsLocked)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 nil, errors.New("Chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.remove") {
|
||||||
|
return nil, errors.New("Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err = chapters.Remove(chapter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Failed to remove chapter: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = comments.RemoveChapter(chapter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Chapter was removed, but comment removal failed: " + 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,184 @@
|
|||||||
|
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 {
|
||||||
|
character, err := characters.FindID(*id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &character, nil
|
||||||
|
} else if nick != nil {
|
||||||
|
character, err := characters.FindNick(*nick)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &character, nil
|
||||||
|
} else {
|
||||||
|
return nil, 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 nil, errors.New("You are not permitted to add characters")
|
||||||
|
}
|
||||||
|
if len(input.Name) < 2 || len(input.Nick) < 2 {
|
||||||
|
return nil, 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 nil, 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 nil, 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 nil, errors.New("Character not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(input.Nick) < 2 {
|
||||||
|
return nil, 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 nil, errors.New("You are not permitted to edit this character")
|
||||||
|
}
|
||||||
|
|
||||||
|
logs.ScheduleFullUpdate()
|
||||||
|
|
||||||
|
character, err = characters.AddNick(character, input.Nick)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 nil, errors.New("Character not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.PermittedUser(character.Author, "member", "character.edit") {
|
||||||
|
return nil, errors.New("You are not permitted to edit this character")
|
||||||
|
}
|
||||||
|
|
||||||
|
character, err = characters.RemoveNick(character, input.Nick)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 nil, errors.New("Character not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.Name != nil && len(*input.Name) < 2 {
|
||||||
|
return nil, errors.New("You need to provide a valid name (min length: 2)")
|
||||||
|
}
|
||||||
|
if input.ShortName != nil && len(*input.ShortName) < 2 {
|
||||||
|
return nil, 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 nil, 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 nil, 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 nil, errors.New("Character not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.PermittedUser(character.Author, "member", "character.remove") {
|
||||||
|
return nil, errors.New("You are not permitted to remove this character")
|
||||||
|
}
|
||||||
|
|
||||||
|
character, err = characters.Remove(character)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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,180 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/stories"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models/characters"
|
||||||
|
|
||||||
|
"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/chapters"
|
||||||
|
"git.aiterp.net/rpdata/api/models/comments"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Queries
|
||||||
|
|
||||||
|
func (r *resolver) Comment(ctx context.Context, id string) (*models.Comment, error) {
|
||||||
|
comment, err := comments.Find(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &comment, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutations
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddComment(ctx context.Context, input input.CommentAddInput) (*models.Comment, error) {
|
||||||
|
chapter, err := chapters.FindID(input.ChapterID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Permitted("member", "story.edit") {
|
||||||
|
return nil, errors.New("Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !chapter.CanComment() {
|
||||||
|
return nil, errors.New("Comments are disabled or locked")
|
||||||
|
}
|
||||||
|
|
||||||
|
var characterPtr *models.Character
|
||||||
|
if input.CharacterID != nil {
|
||||||
|
character, err := characters.FindID(*input.CharacterID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Character not found")
|
||||||
|
} else if character.Author != token.UserID {
|
||||||
|
return nil, errors.New("That is not your character")
|
||||||
|
}
|
||||||
|
|
||||||
|
characterPtr = &character
|
||||||
|
}
|
||||||
|
|
||||||
|
fictionalDate := time.Time{}
|
||||||
|
if input.FictionalDate != nil {
|
||||||
|
fictionalDate = *input.FictionalDate
|
||||||
|
}
|
||||||
|
|
||||||
|
subject := ""
|
||||||
|
if input.Subject != nil {
|
||||||
|
subject = *input.Subject
|
||||||
|
}
|
||||||
|
|
||||||
|
comment, err := comments.Add(chapter, subject, token.UserID, input.Source, input.CharacterName, characterPtr, time.Now(), fictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Failed to add comment: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
story, err := stories.FindID(chapter.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("WARNING: Couldn't log comment change:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Comment", "add", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return &comment, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) EditComment(ctx context.Context, input input.CommentEditInput) (*models.Comment, error) {
|
||||||
|
comment, err := comments.Find(input.CommentID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Comment not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.PermittedUser(comment.Author, "member", "story.edit") {
|
||||||
|
return nil, errors.New("You cannot edit this comment")
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err := chapters.FindID(comment.ChapterID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Comment's chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !chapter.CanComment() {
|
||||||
|
return nil, errors.New("Comments are disabled or locked")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.ClearFictionalDate != nil && *input.ClearFictionalDate == true {
|
||||||
|
input.FictionalDate = &time.Time{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.CharacterID != nil && *input.CharacterID != "" {
|
||||||
|
character, err := characters.FindID(*input.CharacterID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Character not found")
|
||||||
|
} else if character.Author != token.UserID {
|
||||||
|
return nil, errors.New("That is not your character")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
comment, err = comments.Edit(comment, input.Source, input.CharacterName, input.CharacterID, input.Subject, input.FictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Could not post comment: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
story, err := stories.FindID(chapter.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("WARNING: Couldn't log comment change:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Comment", "edit", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return &comment, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) RemoveComment(ctx context.Context, input input.CommentRemoveInput) (*models.Comment, error) {
|
||||||
|
comment, err := comments.Find(input.CommentID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Comment not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.PermittedUser(comment.Author, "member", "story.edit") {
|
||||||
|
return nil, errors.New("You cannot remove this comment")
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err := chapters.FindID(comment.ChapterID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Comment's chapter not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !chapter.CanComment() {
|
||||||
|
return nil, errors.New("Comments are disabled or locked")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = comments.Remove(comment)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Failed to remove comment: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
story, err := stories.FindID(chapter.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("WARNING: Couldn't log comment change:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.Submit("Comment", "remove", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return &comment, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
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) {
|
||||||
|
file, err := files.FindID(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &file, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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,189 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"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) {
|
||||||
|
log, err := logs.FindID(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &log, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 nil, 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 nil, 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) ImportLog(ctx context.Context, input input.LogImportInput) ([]models.Log, error) {
|
||||||
|
token := auth.TokenFromContext(ctx)
|
||||||
|
if !token.Authenticated() || !token.Permitted("log.add") {
|
||||||
|
return nil, errors.New("You are not permitted to add logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
date := time.Time{}
|
||||||
|
if input.Date != nil {
|
||||||
|
date = *input.Date
|
||||||
|
}
|
||||||
|
|
||||||
|
tz := time.UTC
|
||||||
|
if input.Timezone != nil {
|
||||||
|
parsedTZ, err := time.LoadLocation(*input.Timezone)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Unknown timezone: " + *input.Timezone)
|
||||||
|
}
|
||||||
|
|
||||||
|
tz = parsedTZ
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := logs.Import(input.Importer, date, tz, input.ChannelName, input.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newLogs := make([]models.Log, 0, len(results))
|
||||||
|
for _, result := range results {
|
||||||
|
go func(result logs.ImportedLog) {
|
||||||
|
changes.Submit("Log", "add", token.UserID, true, changekeys.Many(result.Log), result.Log)
|
||||||
|
changes.Submit("Post", "add", token.UserID, true, changekeys.Many(result.Log, result.Posts), result.Posts)
|
||||||
|
}(result)
|
||||||
|
|
||||||
|
log, err := logs.UpdateCharacters(result.Log, nil)
|
||||||
|
if err != nil {
|
||||||
|
log = result.Log
|
||||||
|
}
|
||||||
|
|
||||||
|
newLogs = append(newLogs, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newLogs, 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 nil, errors.New("You are not permitted to edit logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err := logs.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Log not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err = logs.Edit(log, input.Title, input.Event, input.Description, input.Open)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 nil, errors.New("You are not permitted to remove logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err := logs.FindID(input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Log not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err = logs.Remove(log)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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,167 @@
|
|||||||
|
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) {
|
||||||
|
post, err := posts.FindID(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &post, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 nil, errors.New("You are not permitted to edit logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
log, err := logs.FindID(input.LogID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err := posts.Add(log, input.Time, input.Kind, input.Nick, input.Text)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go logs.UpdateCharacters(log, nil)
|
||||||
|
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 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")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.Nick != nil {
|
||||||
|
go func() {
|
||||||
|
log, err := logs.FindID(post.LogID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logs.UpdateCharacters(log, nil)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err = posts.Edit(post, input.Time, input.Kind, input.Nick, input.Text)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 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 (before removing, of course)")
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err = posts.Remove(post)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Could not remove post: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
log, err := logs.FindID(post.LogID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logs.UpdateCharacters(log, nil)
|
||||||
|
changes.Submit("Post", "remove", token.UserID, true, changekeys.Many(log, post), post)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return &post, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
type resolver struct{}
|
||||||
|
type mutationResolver struct{}
|
||||||
|
type subscriptionResolver struct{}
|
||||||
|
|
||||||
|
// Resolver has all the queries
|
||||||
|
var Resolver resolver
|
||||||
|
|
||||||
|
// MutationResolver brings the mutagens.
|
||||||
|
var MutationResolver *mutationResolver
|
||||||
|
|
||||||
|
// SubscriptionResolver has the real-time magic.
|
||||||
|
var SubscriptionResolver *subscriptionResolver
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
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) {
|
||||||
|
story, err := stories.FindID(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &story, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 nil, errors.New("Permission denied")
|
||||||
|
}
|
||||||
|
|
||||||
|
author := token.UserID
|
||||||
|
if input.Author != nil && *input.Author != author {
|
||||||
|
if !token.Permitted("story.add") {
|
||||||
|
return nil, 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 nil, 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 nil, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if story.Open {
|
||||||
|
if !token.Permitted("member") {
|
||||||
|
return nil, errors.New("You are not permitted to edit this story")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !token.PermittedUser(story.Author, "member", "story.edit") {
|
||||||
|
return nil, errors.New("You are not permitted to edit this story")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err = stories.AddTag(story, input.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 nil, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if story.Open {
|
||||||
|
if !token.Permitted("member") {
|
||||||
|
return nil, errors.New("You are not permitted to edit this story")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !token.PermittedUser(story.Author, "member", "story.edit") {
|
||||||
|
return nil, errors.New("You are not permitted to edit this story")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err = stories.RemoveTag(story, input.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 nil, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !token.PermittedUser(story.Author, "member", "story.edit") {
|
||||||
|
return nil, 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 nil, 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 nil, errors.New("Story not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !token.PermittedUser(story.Author, "member", "story.remove") {
|
||||||
|
return nil, errors.New("You are not permitted to remove this story")
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err = stories.Remove(story)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = chapters.RemoveStory(story)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 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 nil, errors.New("No (valid) token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/unknownnicks"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/input"
|
||||||
|
)
|
||||||
|
|
||||||
|
/// Queries
|
||||||
|
|
||||||
|
func (r *resolver) UnknownNicks(ctx context.Context, filter *input.UnknownNicksFilter) ([]models.UnknownNick, error) {
|
||||||
|
limit := 100
|
||||||
|
if filter != nil {
|
||||||
|
if filter.Limit > 0 {
|
||||||
|
limit = filter.Limit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unknownnicks.List(limit)
|
||||||
|
}
|
||||||
@@ -1,118 +1,77 @@
|
|||||||
# The Query type represents the read entry points into the API.
|
schema {
|
||||||
|
query: Query
|
||||||
|
mutation: Mutation
|
||||||
|
subscription: Subscription
|
||||||
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
# Find character by either an ID or a nick.
|
# Find character by either an ID or a nick.
|
||||||
character(id: String, nick: String): Character
|
character(id: String, nick: String): Character!
|
||||||
|
|
||||||
# Find characters
|
# Find characters
|
||||||
characters(filter: CharactersFilter): [Character!]!
|
characters(filter: CharactersFilter): [Character!]!
|
||||||
|
|
||||||
|
|
||||||
# Find channel by name
|
# Find channel by name
|
||||||
channel(name: String!): Channel
|
channel(name: String!): Channel!
|
||||||
|
|
||||||
# Find channels
|
# Find channels
|
||||||
channels(filter: ChannelsFilter): [Channel!]!
|
channels(filter: ChannelsFilter): [Channel!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find post by ID.
|
||||||
|
post(id: String!): Post!
|
||||||
|
|
||||||
|
# Find posts
|
||||||
|
posts(filter: PostsFilter): [Post!]!
|
||||||
|
|
||||||
|
|
||||||
|
"List unknown nicks"
|
||||||
|
unknownNicks(filter: UnknownNicksFilter): [UnknownNick!]!
|
||||||
|
|
||||||
|
|
||||||
# Find log by ID
|
# Find log by ID
|
||||||
log(id: String!): Log
|
log(id: String!): Log!
|
||||||
|
|
||||||
# Find logs
|
# Find logs
|
||||||
logs(filter: LogsFilter): [LogHeader!]!
|
logs(filter: LogsFilter): [Log!]!
|
||||||
|
|
||||||
|
|
||||||
# Find post by ID.
|
|
||||||
post(id: String!): Post
|
|
||||||
|
|
||||||
# Find posts by IDs. It's meant to allow other parts of the UI to link to a cluster of posts, e.g. for a room description for the
|
|
||||||
# Mapp should it ever become a thing. This does not have a filter, since it's meant to be queried in the logs' response's selection set.
|
|
||||||
posts(ids: [String!]!): [Post!]!
|
|
||||||
|
|
||||||
|
|
||||||
# Find file by ID
|
|
||||||
file(id: String!): File
|
|
||||||
|
|
||||||
# Find files
|
|
||||||
files(filter: FilesFilter): [File!]!
|
|
||||||
|
|
||||||
|
|
||||||
# Find story by ID
|
|
||||||
story(id: String!): Story
|
|
||||||
|
|
||||||
# Find stories
|
|
||||||
stories(filter: StoriesFilter): [Story!]!
|
|
||||||
|
|
||||||
|
|
||||||
# Find story chapter by ID
|
# Find story chapter by ID
|
||||||
chapter(id: String!): Chapter
|
chapter(id: String!): Chapter!
|
||||||
|
|
||||||
|
|
||||||
|
# Find comment by ID
|
||||||
|
comment(id: String!): Comment!
|
||||||
|
|
||||||
|
|
||||||
# Find all distinct tags used in stories
|
# Find all distinct tags used in stories
|
||||||
tags: [Tag!]!
|
tags: [Tag!]!
|
||||||
|
|
||||||
|
|
||||||
# Find current session
|
# Find story by ID
|
||||||
session: Session!
|
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!
|
||||||
}
|
}
|
||||||
|
|
||||||
# The Mutation type represents write entry points into the API.
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
# 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(id: String!): Character!
|
|
||||||
|
|
||||||
|
|
||||||
# Add a channel
|
|
||||||
addChannel(input: ChannelAddInput!): Channel!
|
|
||||||
|
|
||||||
# Edit a channel
|
|
||||||
editChannel(input: ChannelEditInput!): Channel!
|
|
||||||
|
|
||||||
# Remove a channel
|
|
||||||
removeChannel(name: String!): Channel!
|
|
||||||
|
|
||||||
|
|
||||||
# Add a new log
|
|
||||||
addLog(input: LogAddInput!): Log!
|
|
||||||
|
|
||||||
# Edit a log
|
|
||||||
editLog(input: LogEditInput!): Log!
|
|
||||||
|
|
||||||
# Remove a log
|
|
||||||
removeLog(id: String!): Log!
|
|
||||||
|
|
||||||
|
|
||||||
# Add a post
|
|
||||||
addPost(input: AddPostInput!): Post!
|
|
||||||
|
|
||||||
# Edit a post
|
|
||||||
editPost(input: EditPostInput!): Post!
|
|
||||||
|
|
||||||
# Move a post
|
|
||||||
movePost(input: MovePostInput!): Post!
|
|
||||||
|
|
||||||
# Remove a post
|
|
||||||
removePost(id: String!): Post!
|
|
||||||
|
|
||||||
|
|
||||||
# Edit a file
|
|
||||||
editFile(input: EditFileInput!): File!
|
|
||||||
|
|
||||||
# Remove a file
|
|
||||||
removeFile(id: String!): File!
|
|
||||||
|
|
||||||
|
|
||||||
# Add a story
|
# Add a story
|
||||||
addStory(input: StoryAddInput!): Story!
|
addStory(input: StoryAddInput!): Story!
|
||||||
|
|
||||||
@@ -126,7 +85,7 @@ type Mutation {
|
|||||||
editStory(input: StoryEditInput!): Story!
|
editStory(input: StoryEditInput!): Story!
|
||||||
|
|
||||||
# Remove a story
|
# Remove a story
|
||||||
removeStory(id: String!): Story!
|
removeStory(input: StoryRemoveInput!): Story!
|
||||||
|
|
||||||
|
|
||||||
# Add a chapter to a story
|
# Add a chapter to a story
|
||||||
@@ -135,18 +94,79 @@ type Mutation {
|
|||||||
# Edit a chapter
|
# Edit a chapter
|
||||||
editChapter(input: ChapterEditInput!): Chapter!
|
editChapter(input: ChapterEditInput!): Chapter!
|
||||||
|
|
||||||
|
# Move a chapter
|
||||||
|
moveChapter(input: ChapterMoveInput!): Chapter!
|
||||||
|
|
||||||
# Remove a chapter
|
# Remove a chapter
|
||||||
removeChapter(id: String!): Chapter!
|
removeChapter(input: ChapterRemoveInput!): Chapter!
|
||||||
|
|
||||||
|
|
||||||
# Log in
|
"Add a comment to a chapter."
|
||||||
login(username: String!, password: String!): Session!
|
addComment(input: CommentAddInput!): Comment!
|
||||||
|
|
||||||
|
"Edit a comment in a chapter."
|
||||||
|
editComment(input: CommentEditInput!): Comment!
|
||||||
|
|
||||||
|
"Remove a comemnt in a chapter."
|
||||||
|
removeComment(input: CommentRemoveInput!): Comment!
|
||||||
|
|
||||||
|
|
||||||
|
# Add a new log
|
||||||
|
addLog(input: LogAddInput!): Log!
|
||||||
|
|
||||||
|
# Import a log
|
||||||
|
importLog(input: LogImportInput!): [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!
|
||||||
|
|
||||||
# Log out
|
# Remove nick from character
|
||||||
logout(): Session!
|
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!
|
||||||
}
|
}
|
||||||
|
|
||||||
schema {
|
type Subscription {
|
||||||
query: Query
|
"""
|
||||||
mutation: Mutation
|
Changes subscribes to the changes matching the following keys.
|
||||||
}
|
"""
|
||||||
|
changes(keys: [ChangeKeyInput!]!): Change!
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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 | Comment
|
||||||
|
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
# A Chapter is the main content body of a story.
|
||||||
|
type Chapter {
|
||||||
|
# The chapter's ID
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
# The chapter's title
|
||||||
|
title: String!
|
||||||
|
|
||||||
|
# The chapter's author
|
||||||
|
author: String!
|
||||||
|
|
||||||
|
# The chapter's source
|
||||||
|
source: String!
|
||||||
|
|
||||||
|
# When the chapter was posted initialy
|
||||||
|
createdDate: Date!
|
||||||
|
|
||||||
|
# The in-universe date and time of the chapter
|
||||||
|
fictionalDate: Date
|
||||||
|
|
||||||
|
# The date of edit.
|
||||||
|
editedDate: Date!
|
||||||
|
|
||||||
|
"The comment mode."
|
||||||
|
commentMode: ChapterCommentMode!
|
||||||
|
|
||||||
|
"Whether the author has locket comments."
|
||||||
|
commentsLocked: Boolean!
|
||||||
|
|
||||||
|
"A shorthand for checking whether a logged-in user can comment on this chapter."
|
||||||
|
canComment: Boolean!
|
||||||
|
|
||||||
|
"Get all chapter comments."
|
||||||
|
comments(limit: Int): [Comment!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
The possibles modes of comments for a chapter.
|
||||||
|
"""
|
||||||
|
enum ChapterCommentMode {
|
||||||
|
"Comments are disabled and hidden."
|
||||||
|
Disabled
|
||||||
|
|
||||||
|
"Comments should be shown as typical news article comments."
|
||||||
|
Article
|
||||||
|
|
||||||
|
"Comments should be shown in a compact form suitable for many small messages."
|
||||||
|
Chat
|
||||||
|
|
||||||
|
"Comments are going to be shown as omni-tool messages."
|
||||||
|
Message
|
||||||
|
}
|
||||||
|
|
||||||
|
# Input for addChapter mutation
|
||||||
|
input ChapterAddInput {
|
||||||
|
# The story to add a chapter to
|
||||||
|
storyId: String!
|
||||||
|
|
||||||
|
# The title to give the chapter. It can not be left empty
|
||||||
|
title: String!
|
||||||
|
|
||||||
|
# The author to set for the chapter. It will use the logged in user ID, and only
|
||||||
|
# users with appropriate permissions can post as another author. Even then, it's only
|
||||||
|
# for importing/moving content. This author name will not be used when logging the
|
||||||
|
# submission
|
||||||
|
author: String
|
||||||
|
|
||||||
|
# The markdown source for the content
|
||||||
|
source: String!
|
||||||
|
|
||||||
|
# Optionally, assign a fictional date for the chapter
|
||||||
|
fictionalDate: Date
|
||||||
|
|
||||||
|
"The comment mode for the chapter."
|
||||||
|
commentMode: ChapterCommentMode
|
||||||
|
}
|
||||||
|
|
||||||
|
# Input for editChapter mutation
|
||||||
|
input ChapterEditInput {
|
||||||
|
# The chapter to edit
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
# Change the chapter's title
|
||||||
|
title: String
|
||||||
|
|
||||||
|
# Change the source
|
||||||
|
source: String
|
||||||
|
|
||||||
|
# Set the fictional date for a chapter
|
||||||
|
fictionalDate: Date
|
||||||
|
|
||||||
|
# Remove the fictional date for a chapter
|
||||||
|
clearFictionalDate: Boolean
|
||||||
|
|
||||||
|
"Set the comment mode for the chapter"
|
||||||
|
commentMode: ChapterCommentMode
|
||||||
|
|
||||||
|
"Set whether the chapter comments are locked"
|
||||||
|
commentsLocked: 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!
|
||||||
|
}
|
||||||
@@ -68,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!
|
||||||
@@ -80,4 +81,11 @@ 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!
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
"""
|
||||||
|
A Comment represents a comment to a story chapter.
|
||||||
|
"""
|
||||||
|
type Comment {
|
||||||
|
"A unique ID of the change."
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
"subject"
|
||||||
|
subject: String!
|
||||||
|
|
||||||
|
"The chapter ID the comment belongs to."
|
||||||
|
chapterId: String!
|
||||||
|
|
||||||
|
"The comment's author."
|
||||||
|
author: String!
|
||||||
|
|
||||||
|
"The displayed name of the character. This may be the same as character.name, but it does not need to be."
|
||||||
|
characterName: String!
|
||||||
|
|
||||||
|
"The character associated with the comment."
|
||||||
|
character: Character
|
||||||
|
|
||||||
|
"The fictional (IC) date of the comment."
|
||||||
|
fictionalDate: Date
|
||||||
|
|
||||||
|
"The date of creation."
|
||||||
|
createdDate: Date!
|
||||||
|
|
||||||
|
"The date of the last edit."
|
||||||
|
editedDate: Date!
|
||||||
|
|
||||||
|
"The markdown source of the comment."
|
||||||
|
source: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Input for the addComment mutation
|
||||||
|
"""
|
||||||
|
input CommentAddInput {
|
||||||
|
"What chapter to comment on."
|
||||||
|
chapterId: String!
|
||||||
|
|
||||||
|
"The markdown source of the comment."
|
||||||
|
source: String!
|
||||||
|
|
||||||
|
"The name of the character associated with this comment."
|
||||||
|
characterName: String!
|
||||||
|
|
||||||
|
"Optioanlly, a character ID."
|
||||||
|
characterId: String
|
||||||
|
|
||||||
|
"Optional in-universe date of the comment."
|
||||||
|
fictionalDate: Date
|
||||||
|
|
||||||
|
"Optional subject to add to the comment, only shown in some modes."
|
||||||
|
subject: String
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Input for the editComment mutation
|
||||||
|
"""
|
||||||
|
input CommentEditInput {
|
||||||
|
"What comment to edit."
|
||||||
|
commentId: String!
|
||||||
|
|
||||||
|
"Change the markdown source."
|
||||||
|
source: String
|
||||||
|
|
||||||
|
"Change the name of the character associated with this comment."
|
||||||
|
characterName: String
|
||||||
|
|
||||||
|
"Change the character assocaited with this comment."
|
||||||
|
characterId: String
|
||||||
|
|
||||||
|
"Change the optional in-universe date of the comment."
|
||||||
|
fictionalDate: Date
|
||||||
|
|
||||||
|
"Set to clear the fictional date."
|
||||||
|
clearFictionalDate: Boolean
|
||||||
|
|
||||||
|
"Change the optional subject for the comment, only shown in some modes."
|
||||||
|
subject: String
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Input for the removeComment mutation
|
||||||
|
"""
|
||||||
|
input CommentRemoveInput {
|
||||||
|
"What comment to edit."
|
||||||
|
commentId: 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.
|
||||||
@@ -35,7 +35,7 @@ input FilesFilter {
|
|||||||
public: Boolean
|
public: Boolean
|
||||||
|
|
||||||
# Limit the MIME types of the files.
|
# Limit the MIME types of the files.
|
||||||
mimeTypes: [String!]
|
mimeType: [String!]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Input for editFile mutation
|
# Input for editFile mutation
|
||||||
@@ -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,40 @@ 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.
|
Input for importLog mutation.
|
||||||
shortId: String!
|
"""
|
||||||
|
input LogImportInput {
|
||||||
# The date for a log.
|
"The channel of the log, alwyas required."
|
||||||
date: String!
|
|
||||||
|
|
||||||
# The channel name of a log.
|
|
||||||
channelName: String!
|
channelName: String!
|
||||||
|
|
||||||
# Information about the channel this log is in.
|
"Which importer to use."
|
||||||
channel: Channel!
|
importer: LogImporter!
|
||||||
|
|
||||||
# The session's title.
|
|
||||||
title: String!
|
|
||||||
|
|
||||||
# The log's event, which is the same as the tags in the previous logbot site.
|
"The timezone of the import, all log and post dates will be treated as it. It will be UTC if none is specified."
|
||||||
# Empty string means that it's no event.
|
timezone: String
|
||||||
event: String!
|
|
||||||
|
|
||||||
# The description of a session, which is empty if unset.
|
"The date of the log, if not provided in the log body."
|
||||||
description: String!
|
date: Date
|
||||||
|
|
||||||
# Whether the log session is open.
|
"The log body itself."
|
||||||
open: Boolean!
|
data: String!
|
||||||
|
|
||||||
# The characters involved in the log file.
|
|
||||||
characters: [Character!]!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum LogImporter {
|
||||||
|
"""
|
||||||
|
mIRC-like: This importer parses logs that copied from mIRC posts without spaces.
|
||||||
|
"""
|
||||||
|
MircLike
|
||||||
|
|
||||||
|
"""
|
||||||
|
Forum log: This importer parses the format on the forum. The displayed log, not the post source.
|
||||||
|
"""
|
||||||
|
ForumLog
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
@@ -33,4 +33,5 @@ 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,20 @@
|
|||||||
|
"""
|
||||||
|
An unknown nick is a nick found by the logbot that's not associated with
|
||||||
|
any characters. Many are going to be false positives, but most should be
|
||||||
|
useful in pointing out which characters are missing.
|
||||||
|
"""
|
||||||
|
type UnknownNick {
|
||||||
|
"The IRC nick that's unknown."
|
||||||
|
nick: String!
|
||||||
|
|
||||||
|
"The amount of logs that contains the unknown nick."
|
||||||
|
score: Int!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Input for the unknownNicks query.
|
||||||
|
"""
|
||||||
|
input UnknownNicksFilter {
|
||||||
|
"The highest amount of unknown nicks to return."
|
||||||
|
limit: Int!
|
||||||
|
}
|
||||||
@@ -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,26 @@
|
|||||||
|
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, 0, len(objects))
|
||||||
|
for _, object := range objects {
|
||||||
|
if changeObject, ok := object.(input.ChangeObject); ok {
|
||||||
|
results = append(results, changeObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeResolver is a resolver
|
||||||
|
var ChangeResolver changeResolver
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
"git.aiterp.net/rpdata/api/models/comments"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *chapterResolver) Comments(ctx context.Context, chapter *models.Chapter, limit *int) ([]models.Comment, error) {
|
||||||
|
limitValue := 0
|
||||||
|
if limit != nil {
|
||||||
|
if *limit < 0 {
|
||||||
|
return nil, errors.New("Limit cannot be negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
limitValue = *limit
|
||||||
|
}
|
||||||
|
|
||||||
|
if !chapter.CommentMode.IsEnabled() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return comments.ListChapterID(chapter.ID, limitValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChapterResolver is a resolver
|
||||||
|
var ChapterResolver chapterResolver
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/internal/loader"
|
||||||
|
"git.aiterp.net/rpdata/api/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type commentResolver struct{}
|
||||||
|
|
||||||
|
func (r *commentResolver) Character(ctx context.Context, obj *models.Comment) (*models.Character, error) {
|
||||||
|
if obj.CharacterID == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
loader := loader.FromContext(ctx)
|
||||||
|
if loader == nil {
|
||||||
|
return nil, errors.New("no loader")
|
||||||
|
}
|
||||||
|
|
||||||
|
character, err := loader.Character("id", obj.CharacterID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &character, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *commentResolver) FictionalDate(ctx context.Context, obj *models.Comment) (*time.Time, error) {
|
||||||
|
if obj.FictionalDate.IsZero() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &obj.FictionalDate, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommentResolver is a resolver
|
||||||
|
var CommentResolver commentResolver
|
||||||
@@ -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 nil, 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,22 @@
|
|||||||
|
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) {
|
||||||
|
user, err := users.Find(token.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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,43 +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 {
|
|
||||||
Filter *struct {
|
|
||||||
Logged *bool
|
|
||||||
EventName *string
|
|
||||||
LocationName *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Channels resolves the channels query
|
|
||||||
func (r *QueryResolver) Channels(ctx context.Context, args *ChannelsArgs) ([]*types.ChannelResolver, error) {
|
|
||||||
var channels []channel.Channel
|
|
||||||
var err error
|
|
||||||
|
|
||||||
filter := args.Filter
|
|
||||||
if filter != nil {
|
|
||||||
channels, err = channel.List(filter.Logged, filter.EventName, filter.LocationName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channels, err = channel.List(nil, nil, nil)
|
|
||||||
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,59 +0,0 @@
|
|||||||
package queries
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.aiterp.net/rpdata/api/graphql/resolver/types"
|
|
||||||
"git.aiterp.net/rpdata/api/model/character"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CharactersArgs is args for characters query
|
|
||||||
type CharactersArgs struct {
|
|
||||||
Filter *struct {
|
|
||||||
IDs *[]string
|
|
||||||
Nicks *[]string
|
|
||||||
Names *[]string
|
|
||||||
Author *string
|
|
||||||
Search *string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Characters resolves the characters query
|
|
||||||
func (r *QueryResolver) Characters(ctx context.Context, args *CharactersArgs) ([]*types.CharacterResolver, error) {
|
|
||||||
var characters []character.Character
|
|
||||||
var err error
|
|
||||||
|
|
||||||
filter := args.Filter
|
|
||||||
if filter != nil {
|
|
||||||
var ids []string
|
|
||||||
var nicks []string
|
|
||||||
var names []string
|
|
||||||
|
|
||||||
if filter.IDs != nil {
|
|
||||||
ids = *filter.IDs
|
|
||||||
}
|
|
||||||
if filter.Nicks != nil {
|
|
||||||
nicks = *filter.Nicks
|
|
||||||
}
|
|
||||||
if filter.Names != nil {
|
|
||||||
names = *filter.Names
|
|
||||||
}
|
|
||||||
|
|
||||||
characters, err = character.ListFilter(ids, nicks, names, filter.Author, filter.Search)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
characters, err = character.List()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvers := make([]*types.CharacterResolver, 0, len(characters))
|
|
||||||
for _, character := range characters {
|
|
||||||
resolvers = append(resolvers, &types.CharacterResolver{C: character})
|
|
||||||
}
|
|
||||||
|
|
||||||
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,45 +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 {
|
|
||||||
Filter *struct {
|
|
||||||
Public *bool
|
|
||||||
MimeTypes *[]string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Files resolves the file query
|
|
||||||
func (r *QueryResolver) Files(ctx context.Context, args *FilesArgs) ([]*types.FileResolver, error) {
|
|
||||||
filter := args.Filter
|
|
||||||
user := session.FromContext(ctx).User()
|
|
||||||
|
|
||||||
author := ""
|
|
||||||
if user != nil {
|
|
||||||
author = user.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
mimeTypes := []string(nil)
|
|
||||||
if filter.MimeTypes != nil {
|
|
||||||
mimeTypes = *filter.MimeTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
files, err := file.List(author, filter.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,23 +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) {
|
|
||||||
log, err := log.FindID(args.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.LogResolver{L: log}, 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)
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user