Merge branch 'gcf' into main

Signed-off-by: Katalina Okano <git@kat.cafe>
This commit is contained in:
41666 2020-12-05 03:11:12 -05:00
commit 156bd8f06e
364 changed files with 5234 additions and 22248 deletions

4
.babelrc Normal file
View file

@ -0,0 +1,4 @@
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}

View file

@ -1,89 +0,0 @@
build --workspace_status_command=hack/workspace_status.sh
test --workspace_status_command=hack/workspace_status.sh
run --workspace_status_command=hack/workspace_status.sh
# Common Bazel settings for JavaScript/NodeJS workspaces
# This rc file is automatically discovered when Bazel is run in this workspace,
# see https://docs.bazel.build/versions/master/guide.html#bazelrc
#
# The full list of Bazel options: https://docs.bazel.build/versions/master/command-line-reference.html
# Cache action outputs on disk so they persist across output_base and bazel shutdown (eg. changing branches)
build --disk_cache=~/.cache/bazel-disk-cache
# Bazel will create symlinks from the workspace directory to output artifacts.
# Build results will be placed in a directory called "dist/bin"
# Other directories will be created like "dist/testlogs"
# Be aware that this will still create a bazel-out symlink in
# your project directory, which you must exclude from version control and your
# editor's search path.
build --symlink_prefix=dist/
# To disable the symlinks altogether (including bazel-out) you can use
# build --symlink_prefix=/
# however this makes it harder to find outputs.
# Specifies desired output mode for running tests.
# Valid values are
# 'summary' to output only test status summary
# 'errors' to also print test logs for failed tests
# 'all' to print logs for all tests
# 'streamed' to output logs for all tests in real time
# (this will force tests to be executed locally one at a time regardless of --test_strategy value).
test --test_output=errors
# Support for debugging NodeJS tests
# Add the Bazel option `--config=debug` to enable this
# --test_output=streamed
# Stream stdout/stderr output from each test in real-time.
# See https://docs.bazel.build/versions/master/user-manual.html#flag--test_output for more details.
# --test_strategy=exclusive
# Run one test at a time.
# --test_timeout=9999
# Prevent long running tests from timing out
# See https://docs.bazel.build/versions/master/user-manual.html#flag--test_timeout for more details.
# --nocache_test_results
# Always run tests
# --node_options=--inspect-brk
# Pass the --inspect-brk option to all tests which enables the node inspector agent.
# See https://nodejs.org/de/docs/guides/debugging-getting-started/#command-line-options for more details.
# --define=VERBOSE_LOGS=1
# Rules will output verbose logs if the VERBOSE_LOGS environment variable is set. `VERBOSE_LOGS` will be passed to
# `nodejs_binary` and `nodejs_test` via the default value of the `default_env_vars` attribute of those rules.
# --compilation_mode=dbg
# Rules may change their build outputs if the compilation mode is set to dbg. For example,
# mininfiers such as terser may make their output more human readable when this is set. Rules will pass `COMPILATION_MODE`
# to `nodejs_binary` executables via the actions.run env attribute.
# See https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode for more details.
test:debug --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results --define=VERBOSE_LOGS=1
# Use bazel run with `--config=debug` to turn on the NodeJS inspector agent.
# The node process will break before user code starts and wait for the debugger to connect.
run:debug --define=VERBOSE_LOGS=1 -- --node_options=--inspect-brk
# The following option will change the build output of certain rules such as terser and may not be desirable in all cases
build:debug --compilation_mode=dbg
# Turn off legacy external runfiles
# This prevents accidentally depending on this feature, which Bazel will remove.
build --nolegacy_external_runfiles
# Turn on --incompatible_strict_action_env which was on by default
# in Bazel 0.21.0 but turned off again in 0.22.0. Follow
# https://github.com/bazelbuild/bazel/issues/7026 for more details.
# This flag is needed to so that the bazel cache is not invalidated
# when running bazel via `yarn bazel`.
# See https://github.com/angular/angular/issues/27514.
build --incompatible_strict_action_env
run --incompatible_strict_action_env
# When running `bazel coverage` --instrument_test_targets needs to be set in order to
# collect coverage information from test targets
coverage --instrument_test_targets
# Load any settings specific to the current user.
# .bazelrc.user should appear in .gitignore so that settings are not shared with team members
# This needs to be last statement in this
# config, as the user configuration should be able to overwrite flags from this file.
# See https://docs.bazel.build/versions/master/best-practices.html#bazelrc
# (Note that we use .bazelrc.user so the file appears next to .bazelrc in directory listing,
# rather than user.bazelrc as suggested in the Bazel docs)
try-import %workspace%/.bazelrc.user

View file

@ -1,20 +0,0 @@
{
"name": "Roleypoly (Bazel, Go, Node)",
// Docker Hub because easier to go fast
"image": "roleypoly/dev-container:main",
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"extensions": [
"bazelbuild.vscode-bazel",
"dbaeumer.vscode-eslint",
"golang.go",
"hashicorp.terraform",
"firsttris.vscode-jest-runner",
"esbenp.prettier-vscode",
"zxh404.vscode-proto3",
"jpoissonnier.vscode-styled-components",
"eg2.vscode-npm-script",
"christian-kohler.npm-intellisense"
]
}

1
.dockerignore Normal file
View file

@ -0,0 +1 @@
node_modules

30
.env.example Normal file
View file

@ -0,0 +1,30 @@
# Make an application at https://discord.com/developers/applications
BOT_CLIENT_ID=000000000000000000
BOT_CLIENT_SECRET=RnX8pXXXXXXXXXXXXXXXXXXXXXXXXXu-
BOT_TOKEN=Mzk2MjI3MTM0MjI3NXXXXXXXXXXXXXXXXXXXXXPUlYoARXXXXXXXXXXXXXX
# Comma separated; put your user ID here. Gives elevated permissions to everything.
ROOT_USERS=62601275618889728
# Comma separated; list any bot IDs that are allowed to operate upon this bot.
ALLOWED_BOTS=
# If 6600 or 6601 is taken, change this, and all other 6600/6601 references.
PORT=6600
UI_PORT=6601
# This is probably right, unless you set a different port.
OAUTH_REDIRECT_URI=http://localhost:6600/login-handler
# Again, probably right. Do not put a trailing /
UI_PUBLIC_URI=http://localhost:6601
API_PUBLIC_URI=http://localhost:6600
# Google Cloud Project ID -- This only needs to be set for production/public cloud
GCP_PROJECT_ID=roleypoly-0000000
# Unset this if you're planning to use public cloud Firestore as opposed to local
# Or set this differently if you changed your local endpoint port.
FIRESTORE_EMULATOR_HOST=localhost:6691
REDIS_ENDPOINT=localhost:6692

View file

@ -34,7 +34,6 @@ module.exports = {
},
},
],
'@typescript-eslint/naming-convention': 'error',
'@typescript-eslint/no-empty-function': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-new': 'error',

View file

@ -10,11 +10,6 @@ updates:
schedule:
interval: 'daily'
- package-ecosystem: 'docker'
directory: '/.devcontainer'
schedule:
interval: 'daily'
- package-ecosystem: 'gomod'
directory: '/'
schedule:

View file

@ -3,61 +3,86 @@ name: Bazel Build
on: push
jobs:
bazel_build:
name: Bazel Build
go_test:
runs-on: ubuntu-latest
name: Go CI
steps:
- uses: actions/checkout@master
- uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- uses: actions/setup-go@v2
with:
go-version: '^1.15.5'
- run: go vet ./...
- run: go test ./...
node_test:
runs-on: ubuntu-latest
name: Node CI
steps:
- uses: actions/checkout@master
- name: Mount bazel cache
uses: actions/cache@v2.1.2
- uses: actions/setup-node@v2-beta
with:
path: |
/home/runner/.cache/bazel
/home/runner/.cache/bazel-disk-cache
key: bazel
node-version: '14'
- name: Install bazelisk
run: |
curl -LO "https://github.com/bazelbuild/bazelisk/releases/download/v1.1.0/bazelisk-linux-amd64"
mkdir -p "${GITHUB_WORKSPACE}/bin/"
mv bazelisk-linux-amd64 "${GITHUB_WORKSPACE}/bin/bazel"
chmod +x "${GITHUB_WORKSPACE}/bin/bazel"
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Test
run: |
"${GITHUB_WORKSPACE}/bin/bazel" test \
-k -c opt \
--stamp \
--workspace_status_command hack/workspace_status.sh --\
//src/... //hack/... -//hack/dev-container/...
- name: Docker Login
run: |
echo ${{github.token}} | docker login -u ${{github.actor}} --password-stdin docker.pkg.github.com
- name: Publish Artifacts
run: |
"${GITHUB_WORKSPACE}/bin/bazel" query //src/... |\
grep +publish |\
xargs -l1 "${GITHUB_WORKSPACE}/bin/bazel" run \
-c opt \
--stamp \
--workspace_status_command hack/workspace_status.sh
- name: Write Artifact Manifest
run: |
artifacts=$(${GITHUB_WORKSPACE}/bin/bazel query //src/... | grep +publish)
publishedServices=${artifacts//$'//src/'/}
publishedServices=${publishedServices//$':+publish'/}
manifestJSON='{"services": {}}'
for svc in $publishedServices; do
manifestJSON=$(echo $manifestJSON | jq ".services+={\"$svc\":\"$(cat bazel-bin/src/$svc/+publish.digest)\"}")
done
echo $manifestJSON > manifest.json
- name: Upload Artifact Manifest
uses: actions/upload-artifact@v2
- uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
name: manifest.json
path: manifest.json
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- run: yarn install --frozen-lockfile
- run: yarn lint
- run: yarn test
- name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
with:
images: docker.pkg.github.com/roleypoly/roleypoly/ui
tag-sha: true
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
install: true
- name: Login to GitHub Packages Docker Registry
uses: docker/login-action@v1
with:
registry: docker.pkg.github.com
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: .hack/dockerfiles/ui.Dockerfile
push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
tags: ${{ steps.docker_meta.outputs.tags }}

View file

@ -1,48 +0,0 @@
name: Build Dev Container
on:
push:
paths:
- .devcontainer/*
- hack/dev-container
- WORKSPACE
- .github/workflows/dev-container.yml
schedule:
- cron: '0 12 * * 2' # 12 noon every tuesday
jobs:
dev_container_build:
name: Bazel Build (Dev Container)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Mount bazel cache
uses: actions/cache@v2.1.2
with:
path: |
/home/runner/.cache/bazel
/home/runner/.cache/bazel-disk-cache
key: bazel
- name: Install bazelisk
run: |
curl -LO "https://github.com/bazelbuild/bazelisk/releases/download/v1.1.0/bazelisk-linux-amd64"
mkdir -p "${GITHUB_WORKSPACE}/bin/"
mv bazelisk-linux-amd64 "${GITHUB_WORKSPACE}/bin/bazel"
chmod +x "${GITHUB_WORKSPACE}/bin/bazel"
- name: Build & Publish Dev Container
run: |
echo ${{github.token}} | docker login -u ${{github.actor}} --password-stdin docker.pkg.github.com
"${GITHUB_WORKSPACE}/bin/bazel" run \
-c opt \
--stamp \
--workspace_status_command hack/workspace_status.sh \
//hack/dev-container:publish-dev-container
echo ${{secrets.DOCKER_PASSWORD}} | docker login -u ${{secrets.DOCKER_USERNAME}} --password-stdin
"${GITHUB_WORKSPACE}/bin/bazel" run \
-c opt \
--stamp \
--workspace_status_command hack/workspace_status.sh \
//hack/dev-container:publish-dev-container-dockerhub

View file

@ -1,22 +0,0 @@
name: Release Workflow
on: workflow_dispatch
jobs:
commit_release_tag:
name: Commit Roleypoly Release Tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
with:
ssh-key: ${{ secrets.DEPLOY_KEY }}
- name: Push changes
id: push
run: |
TAG=$(date +v%Y%m%d-%H%M%S)
git config --local user.email "gh-automation@roleypoly.com"
git config --local user.name "Roleypoly Release Automation"
git tag $TAG
git push origin $TAG
echo "::set-output release_tag=${TAG}"

10
.gitignore vendored
View file

@ -1,11 +1,7 @@
bazel-bin
bazel-out
bazel-roleypoly
bazel-testlogs
node_modules
.env
docker-compose.yaml
/target
*.log
storybook-static
dist
.next
worker
wrangler.toml

View file

@ -1,3 +1,6 @@
bazel-*
dist
storybook-static
storybook-static
.next
worker
**/dist

View file

@ -13,4 +13,9 @@ module.exports = {
return config;
},
typescript: {
checkOptions: {
tsconfig: path.resolve(__dirname, '../tsconfig.stories.json'),
},
},
};

View file

@ -6,5 +6,10 @@
"editor.formatOnSave": true,
"editor.insertSpaces": true,
"editor.tabSize": 2,
"go.inferGopath": false
"go.inferGopath": false,
"search.exclude": {
"**/.yarn": true,
"**/.pnp.*": true
},
"typescript.enablePromptUseWorkspaceTsdk": true
}

View file

@ -1,15 +0,0 @@
load("@bazel_gazelle//:def.bzl", "gazelle")
# gazelle:prefix github.com/roleypoly/roleypoly
# gazelle:exclude hack/**
gazelle(name = "gazelle")
exports_files(
[
"tsconfig.json",
"jest.config.js",
"jest-reporter.js",
"hack/jestSetup.ts",
],
visibility = ["//visibility:public"],
)

121
WORKSPACE
View file

@ -1,121 +0,0 @@
workspace(
name = "roleypoly",
managed_directories = {"@npm": ["node_modules"]},
)
### BAZEL
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
http_archive(
name = "io_bazel_rules_go",
sha256 = "08c3cd71857d58af3cda759112437d9e63339ac9c6e0042add43f4d94caf632d",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.24.2/rules_go-v0.24.2.tar.gz",
"https://github.com/bazelbuild/rules_go/releases/download/v0.24.2/rules_go-v0.24.2.tar.gz",
],
)
http_archive(
name = "bazel_gazelle",
sha256 = "d4113967ab451dd4d2d767c3ca5f927fec4b30f3b2c6f8135a2033b9c05a5687",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.22.0/bazel-gazelle-v0.22.0.tar.gz",
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.22.0/bazel-gazelle-v0.22.0.tar.gz",
],
)
http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "f2194102720e662dbf193546585d705e645314319554c6ce7e47d8b59f459e9c",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/2.2.2/rules_nodejs-2.2.2.tar.gz"],
)
git_repository(
name = "io_bazel_rules_docker",
commit = "2083be6214ac15afbabe397726f685b61bec746b",
remote = "https://github.com/bazelbuild/rules_docker.git",
shallow_since = "1601573082 -0400",
)
http_archive(
name = "rules_proto",
sha256 = "602e7161d9195e50246177e7c55b2f39950a9cf7366f74ed5f22fd45750cd208",
strip_prefix = "rules_proto-97d8af4dc474595af3900dd85cb3a29ad28cc313",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz",
"https://github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz",
],
)
### NODE
load("@build_bazel_rules_nodejs//:index.bzl", "yarn_install")
yarn_install(
name = "npm",
package_json = "//:package.json",
yarn_lock = "//:yarn.lock",
)
### PROTO
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
rules_proto_dependencies()
rules_proto_toolchains()
### GO
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
load("//:go_dependencies.bzl", "go_repositories")
# gazelle:repository_macro go_dependencies.bzl%go_repositories
go_repositories()
go_rules_dependencies()
go_register_toolchains()
gazelle_dependencies()
### DOCKER/CONTAINER
# Must be last
load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
)
container_repositories()
load(
"@io_bazel_rules_docker//go:image.bzl",
_go_image_repos = "repositories",
)
_go_image_repos()
load(
"@io_bazel_rules_docker//nodejs:image.bzl",
_nodejs_image_repos = "repositories",
)
_nodejs_image_repos()
load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")
container_deps()
load("@io_bazel_rules_docker//repositories:pip_repositories.bzl", "pip_deps")
pip_deps()
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
container_pull(
name = "devcontainergo",
digest = "sha256:040d6ace87ea63292045155b4b2c1df27ddf41f9d4d7a6afce753c8054838cab",
registry = "mcr.microsoft.com",
repository = "vscode/devcontainers/go",
tag = "1.15",
)

16
docker-compose.yaml Normal file
View file

@ -0,0 +1,16 @@
# This is the Docker Compose for setting up a local dev environment.
# Production uses PaaS equivalents in Google Cloud
version: '3.8'
services:
firestore:
image: mtlynch/firestore-emulator
environment:
FIRESTORE_PROJECT_ID: roleypoly-00000000
ports:
- 6691:8080
redis:
image: redis:5-alpine
ports:
- 6692:6379

125
docs/user-stories.md Normal file
View file

@ -0,0 +1,125 @@
# User Stories
Loose doc defining end-to-end functionality for Roleypoly. Each slice has a cloud function or bot handler attached.
Legend
- (Hot) - Denotes cachable data stored for a short time, 2 minutes.
- Typical use cases: User roles; anything volatile.
- (Warm) - Denotes cachable data stored for a medium time, 10 minutes.
- Typical use cases: Guild roles; anything unlikely to change, but not painful to query.
- (Cold) - Denotes cachable data stored for a long time, 1 hour.
- Typical use cases: Guild lists for a session; anything very unlikely to change, and commonly used.
- (Sec) - Security-minded data. Should never reach end-users.
- Typical use cases: Access tokens
## Primary
### Logged-in Index
As a user, I'd like to see all the servers I am in that can be used with the app.
- Type: Function
- Auth Level: User
- Flow Type: JSON API
- Data:
- User Current Guilds (Cold)
### Server Role Picker View
As a user, I'd like to see all of the roles I can select in a previously set up server.
- Type: Function
- Auth Level: User
- Flow Type: JSON API
- Data:
- User Current Guilds (Cold)
- Guild Roles (Warm)
- User Roles (Hot)
- Guild Customization (Cold)
### Server Role Picker Action
As a user, I'd like to select roles that have been selected in the role picker view for a server.
- Type: Function
- Auth Level: User
- Flow Type: JSON API
- Data:
- User Current Guilds (Cold)
- Guild Roles (Warm)
- User Roles (Hot)
### Server Editor View
As an admin, I'd like to see all of the settings and options for a server.
- Type: Function
- Auth Level: Admin
- Flow Type: JSON API
- Data:
- User Current Guilds (Cold)
- Guild Roles (Warm)
- Guild Customization (Cold)
### Server Editor Action
As an admin, I'd like to save settings and options that I have set within the editor view.
- Type: Function
- Auth Level: Admin
- Flow Type: JSON API
- Data:
- User Current Guilds (Cold)
- Guild Roles (Warm)
- Guild Customization (Cold)
### Session Pre-warming
As a user, I'd like to warm the cache with my current guild list after I log in.
- Type: Function
- Auth Level: User
- Flow Type: Bounces
- Data:
- User Current Guilds (Cold)
### Login
As a guest, I'd like to login with Discord so I can be authenticated as a user.
- Type: Function
- Auth Level: Guest
- Flow Type: OAuth, Bounces
- Data:
- Access Tokens (Sec)
### Logout
As a user, I'd like to revoke my authentication details.
- Type: Function
- Auth Level: User
- Flow Type: OAuth
- Data:
- Access Tokens (Sec)
### Bot Mention
As a discord user, I'd like to mention Roleypoly's bot account to get a link to my editor view.
- Type: Bot Responder
- Auth Level: N/A
- Flow Type: Command
- Data:
- None
### Bot Join
As a discord server admin, I'd like to follow the flow for adding Roleypoly to my server.
- Type: Function
- Auth Level: Guest
- Flow Type: OAuth
- Data:
- None

7
go.mod
View file

@ -5,13 +5,8 @@ go 1.15
require (
github.com/bwmarrin/discordgo v0.22.0
github.com/dghubble/trie v0.0.0-20201011220304-ed6d6b8add55
github.com/facebook/ent v0.4.3
github.com/google/go-github/v32 v32.1.0
github.com/joho/godotenv v1.3.0
github.com/julienschmidt/httprouter v1.3.0
github.com/lampjaw/discordclient v0.0.0-20200923011548-6558fc9e89df
github.com/segmentio/ksuid v1.0.3
go.uber.org/fx v1.13.1
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
github.com/onsi/gomega v1.10.3
k8s.io/klog v1.0.0
)

534
go.sum
View file

@ -1,545 +1,75 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIxDdFM=
github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dghubble/trie v0.0.0-20201011220304-ed6d6b8add55 h1:3yKntgWb7KwnHd4nCVgCIUNQs4qRdua+jitRqGMxKys=
github.com/dghubble/trie v0.0.0-20201011220304-ed6d6b8add55/go.mod h1:xNBeoT4V92/aNvuC3IJ2g59uxuKP4/kzvkpoHrb7v4A=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/facebook/ent v0.4.3 h1:ds9HENceKzpGBgCRlkZNq6TqBIegwKcF3e5reuV9Z0M=
github.com/facebook/ent v0.4.3/go.mod h1:4e/LKv3FFjj/867jPJYCxycZg0aGeEIgkiQ8jv2j6iQ=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-bindata/go-bindata v1.0.1-0.20190711162640-ee3c2418e368/go.mod h1:7xCgX1lzlrXPHkfvn3EhumqHkmSlzt8at9q7v0ax19c=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
github.com/go-sql-driver/mysql v1.5.1-0.20200311113236-681ffa848bae/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lampjaw/discordclient v0.0.0-20200923011548-6558fc9e89df h1:Y2o9fEOoAYjCw8IDyxUVaBq44AUbOLyPnYSPpM6Ef3M=
github.com/lampjaw/discordclient v0.0.0-20200923011548-6558fc9e89df/go.mod h1:lOfqvGl1HcXws86Sczusw1DyV5d0KHPtTTtdjneekto=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/segmentio/ksuid v1.0.3 h1:FoResxvleQwYiPAVKe1tMUlEirodZqlqglIuFsdDntY=
github.com/segmentio/ksuid v1.0.3/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
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/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/dig v1.10.0 h1:yLmDDj9/zuDjv3gz8GQGviXMs9TfysIUMUilCpgzUJY=
go.uber.org/dig v1.10.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw=
go.uber.org/fx v1.13.1 h1:CFNTr1oin5OJ0VCZ8EycL3wzF29Jz2g0xe55RFsf2a4=
go.uber.org/fx v1.13.1/go.mod h1:bREWhavnedxpJeTq9pQT53BbvwhUv7TcpsOqcH4a+3w=
go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4=
go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858 h1:xLt+iB5ksWcZVxqc+g9K41ZHy+6MKWfXCDsjSThnsPA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
package(default_visibility = ["//visibility:public"])

View file

@ -1 +0,0 @@
package(default_visibility = ["//visibility:public"])

View file

@ -1,17 +0,0 @@
load("@io_bazel_rules_docker//container:container.bzl", "container_push")
def publish(
service,
name = "+publish",
image = ":image",
prefix = "roleypoly/roleypoly/",
registry = "docker.pkg.github.com",
):
container_push(
name = name,
format = "Docker",
image = image,
registry = registry,
repository = prefix + service,
tag = "{STABLE_URL_SAFE_TAG}",
)

View file

@ -1 +0,0 @@
package(default_visibility = ["//visibility:public"])

View file

@ -1,61 +0,0 @@
# Copied from https://github.com/bazelbuild/rules_nodejs/blob/stable/examples/jest/jest.bzl
# Licensed under Apache-2.0, modifications made:
# - improved dependency resolution
load("@npm//jest-cli:index.bzl", "jest", _jest_test = "jest_test")
load("//hack/bazel:utils.bzl", "render_deps")
DEFAULT_DEPS = [
"@npm//ts-jest",
"@npm//enzyme",
"@npm//enzyme-adapter-react-16",
"@npm//@types/enzyme",
"@npm//jest-environment-enzyme",
"@npm//jsdom",
"@npm//jest",
"@npm//@types/jest",
"@npm//jest-enzyme",
"@npm//jest-styled-components",
"@npm//enzyme-to-json",
"@npm//react-dom",
"@npm//@types/react-dom",
"@npm//jest-react-hooks-shallow",
"//:tsconfig.json",
"//:hack/jestSetup.ts",
]
def _impl_jest_test(name, srcs, deps, jest_config, **kwargs):
"A macro around the autogenerated jest_test rule"
templated_args = [
"--no-cache",
"--no-watchman",
"--ci",
"--no-colors",
]
templated_args.extend(["--config", "$(rootpath %s)" % jest_config])
for src in srcs:
templated_args.extend(["--runTestsByPath", "$(rootpath %s)" % src])
data = [jest_config] + srcs + deps + ["//:jest-reporter.js"]
_jest_test(
name = name,
data = data,
templated_args = templated_args,
**kwargs
)
# This rule is used specifically to update snapshots via `bazel run`
jest(
name = "%s.update" % name,
data = data,
templated_args = templated_args + ["-u"],
**kwargs
)
def jest_test(src, deps = []):
_impl_jest_test(
name = src[1:] + "_test",
srcs = native.glob(["*.spec.ts", "*.spec.tsx"]),
deps = [src] + render_deps(deps) + DEFAULT_DEPS,
jest_config = "//:jest.config.js",
)

View file

@ -1,36 +0,0 @@
load("//src/ts-protoc-gen/rules:index.bzl", "typescript_proto_library")
load("@npm//@bazel/typescript:index.bzl", "ts_library")
def _generalize_pb_imports(name, srcs = [], grpc = False):
suffix_match = "pb"
if grpc:
suffix_match = ""
native.genrule(
name = name,
srcs = srcs,
outs = ["index.ts"],
cmd = """
echo $(SRCS) | tr ' ' '\n' | grep '""" + suffix_match + """\\.js$$' | xargs -l1 -I '{}' basename {} .js | xargs -l1 -I'{}' echo 'export * from "./{}"' > $(location index.ts)
""",
output_to_bindir = True,
)
def ts_proto(proto, name = "ts", grpc = False):
typescript_proto_library(
name = name + "_proto",
proto = proto,
visibility = ["//visibility:public"],
)
_generalize_pb_imports(
grpc = grpc,
name = name + "_proto_generalized",
srcs = [":" + name + "_proto"],
)
ts_library(
name = name,
srcs = [":" + name + "_proto_generalized"],
deps = [":" + name + "_proto"],
visibility = ["//visibility:public"],
)

View file

@ -1,27 +0,0 @@
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("//hack/bazel:utils.bzl", "render_deps")
DEFAULT_DEPS = [
"react",
"styled-components",
"@types/react",
"@types/styled-components",
]
def react_library(name, deps = [], **kwargs):
ts_library(
name = name,
srcs = native.glob(
[
"*.ts",
"*.tsx",
],
exclude = native.glob([
"*.spec.ts*",
"*.story.tsx",
"*.stories.tsx",
]),
),
deps = render_deps(deps + DEFAULT_DEPS),
**kwargs
)

View file

@ -1,30 +0,0 @@
def _append_once(targetList, item):
if item not in targetList:
targetList.append(item)
def _extend_once(targetList, items):
for item in items:
_append_once(targetList, item)
def render_deps(deps = []):
output_deps = []
has_added_grpc_deps = False
for dep in deps:
if dep.startswith("//src/rpc"):
_append_once(output_deps, dep + ":ts")
_append_once(output_deps, dep + ":ts_proto")
if has_added_grpc_deps == False:
_extend_once(output_deps, [
"@npm//google-protobuf",
"@npm//@types/google-protobuf",
"@npm//@improbable-eng/grpc-web",
])
has_added_grpc_deps = True
elif dep.startswith("//") or dep.startswith("@npm//"):
_append_once(output_deps, dep)
else:
_append_once(output_deps, "@npm//" + dep)
return output_deps

View file

@ -1,44 +0,0 @@
load("//hack/bazel/docker:publish.bzl", "publish")
load("@io_bazel_rules_docker//docker/util:run.bzl", "container_run_and_commit_layer")
load("@io_bazel_rules_docker//container:container.bzl", "container_image")
container_run_and_commit_layer(
name = "bazel-layer",
commands = [
"go get -u github.com/bazelbuild/bazelisk",
"ln /go/bin/bazelisk /usr/bin/bazel",
"go get -u github.com/bazelbuild/buildtools/...",
],
image = "@devcontainergo//image",
)
container_run_and_commit_layer(
name = "node-layer",
commands = [
"su vscode -c 'source /usr/local/share/nvm/nvm.sh && nvm install lts/* 2>&1'",
],
image = "@devcontainergo//image",
)
container_image(
name = "dev-container",
base = "@devcontainergo//image",
layers = [
":bazel-layer",
":node-layer",
],
)
publish(
name = "publish-dev-container",
image = ":dev-container",
service = "dev-container",
)
publish(
name = "publish-dev-container-dockerhub",
image = ":dev-container",
prefix = "roleypoly/",
registry = "index.docker.io",
service = "dev-container",
)

View file

@ -1,24 +0,0 @@
# Dev Container
This package houses the dev-container image.
It includes:
- go (1.15.2)
- bazel (latest via bazelisk)
- node (latest lts via nvm)
As well as any other tooling within VSCode Dev Containers.
## Building
To build and use locally,
```sh
bazel run //srv/dev-container && docker run -it --rm bazel/src/dev-container:dev-container
```
To just use, this is published to two registries. There is no effective difference, except that GitHub's registry requires login, and Docker Hub does not.
- `docker pull roleypoly/dev-container:main`
- `docker pull docker.pkg.github.com/roleypoly/roleypoly/dev-container:main`

View file

@ -0,0 +1,25 @@
FROM node:14-alpine AS base
WORKDIR /src
#
# Builder
#
FROM base AS builder
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN yarn ui:build
RUN yarn install --frozen-lockfile --prod
#
# Output layer
#
FROM base AS output
COPY --from=builder /src/.next /src/node_modules ./
EXPOSE 3000
CMD yarn ui:prod

View file

@ -1,14 +0,0 @@
#!/bin/sh
cd $(dirname $(realpath $0))
cd ..
bazel run //:gazelle
bazel run //:gazelle -- update-repos -from_file=./go.mod --to_macro=go_dependencies.bzl%go_repositories -prune=true
bazel run //:gazelle
sleep 0.5
echo "Fixing go_dependencies.bzl..."
head -n2 ../go_dependencies.bzl >../go_dependencies.bzl~
tail -n+3 ../go_dependencies.bzl | sed '/^$/d' >>../go_dependencies.bzl~
mv ../go_dependencies.bzl~ ../go_dependencies.bzl

View file

@ -1,7 +0,0 @@
package hacknotused
//go:generate sh gazelle.sh
func noop() {
}

View file

@ -1,5 +0,0 @@
#!/bin/bash
echo "STABLE_GIT_COMMIT $(git rev-parse --short HEAD)"
echo "STABLE_GIT_BRANCH $(git rev-parse --abbrev-ref HEAD)"
echo "STABLE_URL_SAFE_TAG $(git rev-parse --abbrev-ref HEAD | tr '/' '-')"
echo "BUILD_DATE $(date -Iseconds)"

View file

@ -1,13 +0,0 @@
class BazelReporter {
onRunComplete(_, results) {
if (results.numFailedTests && results.snapshot.failure) {
console.log(`================================================================================
Snapshot failed, you can update the snapshot by running
bazel run ${process.env['TEST_TARGET'].replace(/_bin$/, '')}.update
`);
}
}
}
module.exports = BazelReporter;

View file

@ -2,12 +2,17 @@ const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig.json');
module.exports = {
preset: 'ts-jest',
preset: 'ts-jest/presets/js-with-babel',
testEnvironment: 'enzyme',
reporters: ['default', './jest-reporter'],
reporters: ['default'],
setupFilesAfterEnv: ['jest-enzyme', 'jest-styled-components', './hack/jestSetup.ts'],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
prefix: '<rootDir>/',
}),
snapshotSerializers: ['enzyme-to-json/serializer'],
globals: {
'ts-jest': {
tsconfig: './tsconfig.test.json',
},
},
};

2
next-env.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
/// <reference types="next" />
/// <reference types="next/types/global" />

View file

@ -18,77 +18,82 @@
"lint:prettier": "cross-env prettier -c '**/*.{ts,tsx,css,yml,yaml,md,json,js,jsx,sh,gitignore,mdx}'",
"lint:stylelint": "cross-env stylelint '**/*.{ts,tsx}'",
"now-build": "run-s storybook:build",
"storybook": "start-storybook -p 6006 --no-dll",
"storybook:build": "build-storybook --no-dll",
"test": "jest"
"storybook": "start-storybook -p 6006",
"storybook:build": "build-storybook",
"test": "jest",
"ui": "next dev -p 6601",
"ui:build": "next build",
"ui:prod": "next start"
},
"dependencies": {
"@improbable-eng/grpc-web": "^0.13.0",
"browser-headers": "^0.4.1",
"chroma-js": "^2.1.0",
"fuse.js": "^6.4.2",
"google-protobuf": "^3.13.0",
"next": "^9.5.5",
"isomorphic-unfetch": "^3.1.0",
"ksuid": "^2.0.0",
"next": "^10.0.3",
"nookies": "^2.5.0",
"react": "^17.0.1",
"react-custom-scrollbars": "^4.2.1",
"react-dom": "^17.0.1",
"react-icons": "^3.11.0",
"react-tooltip": "^4.2.10",
"styled-components": "^5.2.0"
"react-icons": "^4.1.0",
"react-is": "^17.0.1",
"react-tooltip": "^4.2.11",
"styled-components": "^5.2.1"
},
"devDependencies": {
"@babel/core": "^7.12.3",
"@bazel/typescript": "^2.2.2",
"@storybook/addon-actions": "^6.0.27",
"@storybook/addon-essentials": "^6.0.27",
"@storybook/addon-links": "^6.0.27",
"@storybook/addons": "^6.0.27",
"@storybook/react": "^6.0.27",
"@storybook/theming": "^6.0.27",
"@types/chroma-js": "^2.1.0",
"@types/enzyme": "^3.10.7",
"@babel/core": "^7.12.9",
"@cloudflare/workers-types": "^2.1.0",
"@storybook/addon-actions": "^6.1.9",
"@storybook/addon-essentials": "^6.1.9",
"@storybook/addon-links": "^6.1.9",
"@storybook/addons": "^6.1.9",
"@storybook/react": "^6.1.9",
"@storybook/theming": "^6.1.9",
"@types/chroma-js": "^2.1.2",
"@types/enzyme": "^3.10.8",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/google-protobuf": "^3.7.3",
"@types/jest": "^26.0.15",
"@types/minimist": "^1.2.0",
"@types/node": "^14.14.2",
"@types/react": "^16.9.53",
"@types/jest": "^26.0.16",
"@types/minimist": "^1.2.1",
"@types/node": "^14.14.10",
"@types/react": "^17.0.0",
"@types/react-custom-scrollbars": "^4.0.7",
"@types/react-dom": "^16.9.8",
"@types/react-dom": "^17.0.0",
"@types/styled-components": "^5.1.4",
"@typescript-eslint/eslint-plugin": "^4.5.0",
"@typescript-eslint/eslint-plugin-tslint": "^4.5.0",
"@typescript-eslint/parser": "^4.5.0",
"babel-jest": "^26.6.1",
"babel-loader": "^8.1.0",
"@types/uuid": "^8.3.0",
"@typescript-eslint/eslint-plugin": "^4.9.0",
"@typescript-eslint/eslint-plugin-tslint": "^4.9.0",
"@typescript-eslint/parser": "^4.9.0",
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"babel-plugin-styled-components": "^1.12.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"enzyme-to-json": "^3.6.1",
"eslint": "^7.12.0",
"eslint-config-prettier": "^6.14.0",
"eslint": "^7.14.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsdoc": "^30.7.3",
"eslint-plugin-jsdoc": "^30.7.8",
"eslint-plugin-react": "^7.21.5",
"jest": "^26.6.1",
"jest-cli": "^26.6.1",
"jest": "^26.6.3",
"jest-cli": "^26.6.3",
"jest-environment-enzyme": "^7.1.2",
"jest-enzyme": "^7.1.2",
"jest-react-hooks-shallow": "^1.4.1",
"jest-react-hooks-shallow": "^1.4.2",
"jest-styled-components": "^7.0.3",
"minimist": "^1.2.5",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.2",
"prettier-plugin-packagejson": "^2.2.7",
"prettier": "^2.2.1",
"prettier-plugin-packagejson": "^2.2.8",
"prettier-plugin-sh": "^0.6.0",
"react-is": "^17.0.1",
"stylelint": "^13.7.2",
"stylelint": "^13.8.0",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^20.0.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-prettier": "^1.1.2",
"stylelint-processor-styled-components": "^1.10.0",
"ts-jest": "^26.4.2",
"ts-jest": "^26.4.4",
"ts-loader": "^8.0.11",
"tsconfig-paths-webpack-plugin": "^3.3.0",
"typescript": "^4.0.3"
"typescript": "^4.1.2",
"webpack": "^5.9.0"
}
}
}

1
src/backend-worker/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
dist

13
src/backend-worker/bindings.d.ts vendored Normal file
View file

@ -0,0 +1,13 @@
export {};
declare global {
const BOT_CLIENT_ID: string;
const BOT_CLIENT_SECRET: string;
const UI_PUBLIC_URI: string;
const API_PUBLIC_URI: string;
const ROOT_USERS: string;
const KV_SESSIONS: KVNamespace;
const KV_GUILDS: KVNamespace;
const KV_GUILD_DATA: KVNamespace;
}

View file

@ -0,0 +1,35 @@
import { Bounce } from '../utils/bounce';
const validGuildID = /^[0-9]+$/;
type URLParams = {
clientID: string;
permissions: number;
guildID?: string;
};
const buildURL = (params: URLParams) => {
let url = `https://discord.com/api/oauth2/authorize?client_id=${params.clientID}&scope=bot&permissions=${params.permissions}`;
if (params.guildID) {
url += `&guild_id=${params.guildID}&disable_guild_select=true`;
}
return url;
};
export const BotJoin = (request: Request): Response => {
let guildID = new URL(request.url).searchParams.get('guild') || '';
if (guildID && !validGuildID.test(guildID)) {
guildID = '';
}
return Bounce(
buildURL({
clientID: BOT_CLIENT_ID,
permissions: 268435456,
guildID,
})
);
};

View file

@ -0,0 +1,31 @@
import { SessionData } from 'roleypoly/common/types';
import { getSessionID, respond } from '../utils/api-tools';
import { Sessions } from '../utils/kv';
const NotAuthenticated = (extra?: string) =>
respond(
{
err: extra || 'not authenticated',
},
{ status: 403 }
);
export const GetSession = async (request: Request): Promise<Response> => {
const sessionID = getSessionID(request);
if (!sessionID) {
return NotAuthenticated('missing auth header');
}
console.log(sessionID);
const sessionData = await Sessions.get<SessionData>(sessionID.id);
if (!sessionData) {
return NotAuthenticated('session not found');
}
const { tokens, ...withoutTokens } = sessionData;
return respond({
...withoutTokens,
});
};

View file

@ -0,0 +1,24 @@
import KSUID from 'ksuid';
import { Bounce } from '../utils/bounce';
import { apiPublicURI, botClientID } from '../utils/config';
type URLParams = {
clientID: string;
redirectURI: string;
state: string;
};
const buildURL = (params: URLParams) =>
`https://discord.com/api/oauth2/authorize?client_id=${
params.clientID
}&response_type=code&scope=identify%20guilds&redirect_uri=${encodeURIComponent(
params.redirectURI
)}&state=${params.state}`;
export const LoginBounce = async (request: Request): Promise<Response> => {
const state = await KSUID.random();
const redirectURI = `${apiPublicURI}/login-callback`;
const clientID = botClientID;
return Bounce(buildURL({ state: state.string, redirectURI, clientID }));
};

View file

@ -0,0 +1,134 @@
import KSUID from 'ksuid';
import {
DiscordUser,
GuildSlug,
SessionData,
AuthTokenResponse,
} from '../../common/types';
import { formData, resolveFailures, parsePermissions } from '../utils/api-tools';
import { Bounce } from '../utils/bounce';
import { apiPublicURI, botClientID, botClientSecret, uiPublicURI } from '../utils/config';
import { Sessions } from '../utils/kv';
const AuthErrorResponse = (extra?: string) =>
Bounce(
uiPublicURI +
`/machinery/error?error_code=authFailure${extra ? `&extra=${extra}` : ''}`
);
export const LoginCallback = resolveFailures(
AuthErrorResponse(),
async (request: Request): Promise<Response> => {
const query = new URL(request.url).searchParams;
const stateValue = query.get('state');
if (stateValue === null) {
return AuthErrorResponse('state missing');
}
try {
const state = KSUID.parse(stateValue);
const stateExpiry = state.date.getTime() + 1000 * 60 * 5;
const currentTime = Date.now();
if (currentTime > stateExpiry) {
return AuthErrorResponse('state expired');
}
} catch (e) {
return AuthErrorResponse('state invalid');
}
const code = query.get('code');
if (!code) {
return AuthErrorResponse('code missing');
}
const tokenRequest = {
client_id: botClientID,
client_secret: botClientSecret,
grant_type: 'authorization_code',
redirect_uri: apiPublicURI + '/login-callback',
scope: 'identify guilds',
code,
};
const tokenFetch = await fetch('https://discord.com/api/v8/oauth2/token', {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
body: formData(tokenRequest),
});
const tokens = (await tokenFetch.json()) as AuthTokenResponse;
if (!tokens.access_token) {
console.info({ tokens });
return AuthErrorResponse('token response invalid');
}
const [sessionID, user, guilds] = await Promise.all([
KSUID.random(),
getUser(tokens.access_token),
getGuilds(tokens.access_token),
]);
const sessionData: SessionData = {
tokens,
sessionID: sessionID.string,
user,
guilds,
};
await Sessions.put(sessionID.string, sessionData, 60 * 60 * 6);
return Bounce(
uiPublicURI + '/machinery/new-session?session_id=' + sessionID.string
);
}
);
const discordFetch = async <T>(url: string, auth: string): Promise<T> => {
const response = await fetch('https://discord.com/api/v8' + url, {
headers: {
authorization: 'Bearer ' + auth,
},
});
return (await response.json()) as T;
};
const getUser = async (accessToken: string): Promise<DiscordUser> => {
const { id, username, discriminator, bot, avatar } = await discordFetch<DiscordUser>(
'/users/@me',
accessToken
);
return { id, username, discriminator, bot, avatar };
};
type UserGuildsPayload = {
id: string;
name: string;
icon: string;
owner: boolean;
permissions: number;
features: string[];
}[];
const getGuilds = async (accessToken: string) => {
const guilds = await discordFetch<UserGuildsPayload>(
'/users/@me/guilds',
accessToken
);
const guildSlugs = guilds.map<GuildSlug>((guild) => ({
id: guild.id,
name: guild.name,
icon: guild.icon,
permissionLevel: parsePermissions(guild.permissions, guild.owner),
}));
return guildSlugs;
};

View file

@ -0,0 +1,16 @@
import { BotJoin } from './handlers/bot-join';
import { GetSession } from './handlers/get-session';
import { LoginBounce } from './handlers/login-bounce';
import { LoginCallback } from './handlers/login-callback';
import { Router } from './router';
const router = new Router();
router.add('GET', 'bot-join', BotJoin);
router.add('GET', 'login-bounce', LoginBounce);
router.add('GET', 'login-callback', LoginCallback);
router.add('GET', 'get-session', GetSession);
addEventListener('fetch', (event: FetchEvent) => {
event.respondWith(router.handle(event.request));
});

View file

@ -0,0 +1,73 @@
export type Handler = (request: Request) => Promise<Response> | Response;
type RoutingTree = {
[method: string]: {
[path: string]: Handler;
};
};
type Fallbacks = {
root: Handler;
404: Handler;
500: Handler;
};
export class Router {
private routingTree: RoutingTree = {};
private fallbacks: Fallbacks = {
root: this.respondToRoot,
404: this.notFound,
500: this.serverError,
};
addFallback(which: keyof Fallbacks, handler: Handler) {
this.fallbacks[which] = handler;
}
add(method: string, rootPath: string, handler: Handler) {
const lowerMethod = method.toLowerCase();
if (!this.routingTree[lowerMethod]) {
this.routingTree[lowerMethod] = {};
}
this.routingTree[lowerMethod][rootPath] = handler;
}
handle(request: Request): Promise<Response> | Response {
if (request.url === '/') {
return this.fallbacks.root(request);
}
const lowerMethod = request.method.toLowerCase();
const url = new URL(request.url);
const rootPath = url.pathname.split('/')[1];
const handler = this.routingTree[lowerMethod]?.[rootPath];
if (handler) {
try {
return handler(request);
} catch (e) {
console.error(e);
return this.fallbacks[500](request);
}
}
return this.fallbacks[404](request);
}
private respondToRoot(): Response {
return new Response('Hi there!');
}
private notFound(): Response {
return new Response(JSON.stringify({ error: 'not_found' }), {
status: 404,
});
}
private serverError(): Response {
return new Response(JSON.stringify({ error: 'internal_server_error' }), {
status: 500,
});
}
}

View file

@ -0,0 +1,14 @@
{
"compilerOptions": {
"outDir": "./dist",
"lib": ["esnext", "webworker"],
"types": ["@cloudflare/workers-types"]
},
"include": [
"./*.ts",
"./**/*.ts",
"../../node_modules/@cloudflare/workers-types/index.d.ts"
],
"exclude": ["./**/*.spec.ts"],
"extends": "../../tsconfig.json"
}

View file

@ -0,0 +1,55 @@
import { UserGuildPermissions } from '../../common/types';
import {
evaluatePermission,
permissions as Permissions,
} from '../../common/utils/hasPermission';
export const formData = (obj: Record<string, any>): string => {
return Object.keys(obj)
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)
.join('&');
};
export const respond = (obj: Record<string, any>, init?: ResponseInit) =>
new Response(JSON.stringify(obj), init);
export const resolveFailures = (
handleWith: Response,
handler: (request: Request) => Promise<Response> | Response
) => async (request: Request): Promise<Response> | Response => {
try {
return handler(request);
} catch (e) {
console.error(e);
return handleWith;
}
};
export const parsePermissions = (
permissions: number,
owner: boolean = false
): UserGuildPermissions => {
if (owner || evaluatePermission(permissions, Permissions.ADMINISTRATOR)) {
return UserGuildPermissions.Admin;
}
if (evaluatePermission(permissions, Permissions.MANAGE_ROLES)) {
return UserGuildPermissions.Manager;
}
return UserGuildPermissions.User;
};
export const getSessionID = (request: Request): { type: string; id: string } | null => {
const sessionID = request.headers.get('authorization');
if (!sessionID) {
return null;
}
const [type, id] = sessionID.split(' ');
if (type !== 'Bearer') {
return null;
}
return { type, id };
};

View file

@ -0,0 +1,7 @@
export const Bounce = (url: string): Response =>
new Response(null, {
status: 303,
headers: {
location: url,
},
});

View file

@ -0,0 +1,11 @@
const self = (global as any) as Record<string, string>;
const safeURI = (x: string) => x.replace(/\/$/, '');
const list = (x: string) => x.split(',');
export const botClientID = self.BOT_CLIENT_ID;
export const botClientSecret = self.BOT_CLIENT_SECRET;
export const uiPublicURI = safeURI(self.UI_PUBLIC_URI);
export const apiPublicURI = safeURI(self.API_PUBLIC_URI);
export const rootUsers = list(self.ROOT_USERS);
export const kvPrefix = self.KV_PREFIX;

View file

@ -0,0 +1,26 @@
class WrappedKVNamespace {
constructor(private kvNamespace: KVNamespace) {}
async get<T>(key: string): Promise<T | null> {
const data = await this.kvNamespace.get(key, 'text');
if (!data) {
return null;
}
return JSON.parse(data) as T;
}
async put<T>(key: string, value: T, ttlSeconds?: number) {
await this.kvNamespace.put(key, JSON.stringify(value), {
expirationTtl: ttlSeconds,
});
}
list = this.kvNamespace.list;
getWithMetadata = this.kvNamespace.getWithMetadata;
delete = this.kvNamespace.delete;
}
export const Sessions = new WrappedKVNamespace(KV_SESSIONS);
export const GuildData = new WrappedKVNamespace(KV_GUILD_DATA);
export const Guilds = new WrappedKVNamespace(KV_GUILDS);

View file

@ -0,0 +1,29 @@
const path = require('path');
const mode = process.env.NODE_ENV || 'production';
module.exports = {
target: 'webworker',
entry: path.join(__dirname, 'index.ts'),
output: {
filename: `worker.${mode}.js`,
path: path.join(__dirname, 'dist'),
},
mode,
resolve: {
extensions: ['.ts', '.tsx', '.js'],
plugins: [],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
transpileOnly: true,
configFile: path.join(__dirname, 'tsconfig.json'),
},
},
],
},
};

View file

@ -1,21 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "common",
srcs = [
"await-exit.go",
"envconfig.go",
"finders.go",
],
importpath = "github.com/roleypoly/roleypoly/src/common",
visibility = ["//visibility:public"],
)
go_test(
name = "common_test",
srcs = [
"envconfig_test.go",
"finders_test.go",
],
embed = [":common"],
)

View file

@ -1,18 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "bot",
srcs = [
"commandmux.go",
"scaffolding.go",
],
importpath = "github.com/roleypoly/roleypoly/src/common/bot",
visibility = ["//visibility:public"],
deps = [
"//src/common",
"@com_github_bwmarrin_discordgo//:discordgo",
"@com_github_dghubble_trie//:trie",
"@com_github_lampjaw_discordclient//:discordclient",
"@io_k8s_klog//:klog",
],
)

View file

@ -9,6 +9,7 @@ import (
// GetenvValue is a holder type for Getenv to translate any Getenv strings to real types
type GetenvValue struct {
key string
value string
}
@ -25,6 +26,7 @@ func Getenv(key string, defaultValue ...string) GetenvValue {
return GetenvValue{
value: strings.TrimSpace(value),
key: key,
}
}
@ -41,6 +43,15 @@ func (g GetenvValue) StringSlice(optionalDelimiter ...string) []string {
return strings.Split(g.value, delimiter)
}
// SafeURL removes any trailing slash
func (g GetenvValue) SafeURL() string {
if g.value[len(g.value)-1] == '/' {
return g.value[:len(g.value)-1]
}
return g.value
}
func (g GetenvValue) Bool() bool {
lowercaseValue := strings.ToLower(g.value)
if g.value == "1" || lowercaseValue == "true" || lowercaseValue == "yes" {
@ -63,3 +74,11 @@ func (g GetenvValue) Number() int {
func (g GetenvValue) JSON(target interface{}) error {
return json.Unmarshal([]byte(g.value), target)
}
func (g GetenvValue) OrFatal() GetenvValue {
if g.value == "" {
panic("Getenv value was empty and shouldn't be. key: " + g.key)
}
return g
}

View file

@ -2,8 +2,10 @@ package common_test
import (
"os"
"strings"
"testing"
"github.com/onsi/gomega"
"github.com/roleypoly/roleypoly/src/common"
)
@ -13,6 +15,8 @@ var (
"slice": "hello,world",
"slice_no_delim": "hello world",
"slice_set_delim": "hello|world",
"url": "https://google.com",
"url_trailing": "https://google.com/",
"number": "10005",
"number_bad": "abc123",
"bool": "true",
@ -60,6 +64,19 @@ func TestEnvconfigStringSliceSetDelimeter(t *testing.T) {
}
}
func TestEnvconfigSafeURL(t *testing.T) {
testUrl := common.Getenv("test__url").SafeURL()
if strings.HasSuffix(testUrl, "/") {
t.FailNow()
}
}
func TestEnvconfigSafeURLWithTrailing(t *testing.T) {
testUrl := common.Getenv("test__url_trailing").SafeURL()
if strings.HasSuffix(testUrl, "/") {
t.FailNow()
}
}
func TestEnvconfigNumber(t *testing.T) {
testNum := common.Getenv("test__number").Number()
if testNum != 10005 {
@ -121,3 +138,17 @@ func TestEnvconfigJSON(t *testing.T) {
t.FailNow()
}
}
func TestEnvconfigFatal(t *testing.T) {
O := gomega.NewWithT(t)
O.Expect(func() {
_ = common.Getenv("test__thing_that_doesnt_exist").OrFatal().String()
}).Should(gomega.Panic(), "Getenv without a value should panic")
}
func TestEnvconfigNotFatal(t *testing.T) {
O := gomega.NewWithT(t)
O.Expect(func() {
_ = common.Getenv("test__string").OrFatal().String()
}).ShouldNot(gomega.Panic(), "Getenv with a value should not panic")
}

View file

@ -34,3 +34,16 @@ export type PresentableGuild = {
export type GuildEnumeration = {
guildsList: PresentableGuild[];
};
export enum UserGuildPermissions {
User,
Manager,
Admin,
}
export type GuildSlug = {
id: string;
name: string;
icon: string;
permissionLevel: UserGuildPermissions;
};

View file

@ -0,0 +1,18 @@
import { GuildSlug } from './Guild';
import { DiscordUser } from './User';
export type AuthTokenResponse = {
access_token: string;
token_type: 'Bearer';
expires_in: number;
refresh_token: string;
scope: string;
};
export type SessionData = {
/** sessionID is a KSUID */
sessionID: string;
tokens: AuthTokenResponse;
user: DiscordUser;
guilds: GuildSlug[];
};

20
src/common/types/User.go Normal file
View file

@ -0,0 +1,20 @@
package types
type DiscordUser struct {
ID string `json:"id,omitempty"`
Username string `json:"username,omitempty"`
Discriminator string `json:"discriminator,omitempty"`
Avatar string `json:"avatar,omitempty"`
Bot bool `json:"bot,omitempty"`
}
type Member struct {
GuildID string `json:"guildid,omitempty"`
Roles []string `json:"rolesList,omitempty"`
Nick string `json:"nick,omitempty"`
User DiscordUser `json:"user,omitempty"`
}
type RoleypolyUser struct {
DiscordUser DiscordUser `json:"discorduser,omitempty"`
}

View file

@ -2,3 +2,4 @@ export * from './Role';
export * from './Category';
export * from './Guild';
export * from './User';
export * from './Session';

View file

@ -0,0 +1,31 @@
package types
import "time"
// CreateSessionRequest is the payload to /create-session
type CreateSessionRequest struct {
AccessTokenResponse AccessTokenResponse
Fingerprint Fingerprint
}
type Fingerprint struct {
UserAgent string
ClientIP string
ForwardedFor string
}
type CreateSessionResponse struct {
SessionID string
}
type SessionData struct {
SessionID string
Fingerprint Fingerprint
AccessTokens AccessTokenResponse
UserData UserData
}
type UserData struct {
DataExpires time.Time
UserID string
}

View file

@ -0,0 +1,10 @@
package types
// AccessTokenResponse is the response for Discord's OAuth token grant flow
type AccessTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
Scope string `json:"scope"`
}

View file

@ -1,21 +0,0 @@
load("//hack/bazel/js:react.bzl", "react_library")
load("//hack/bazel/js:jest.bzl", "jest_test")
package(default_visibility = ["//visibility:public"])
react_library(
name = "utils",
deps = [
"chroma-js",
"//src/rpc/shared",
"@types/chroma-js",
],
)
jest_test(
src = ":utils",
deps = [
"//src/design-system/shared-types",
"//src/rpc/shared",
],
)

View file

@ -1,8 +1,8 @@
import { hasPermission, permissions, hasPermissionOrAdmin } from './hasPermission';
import { Role } from 'roleypoly/src/rpc/shared';
import { guildRoles } from 'roleypoly/src/design-system/shared-types/storyData';
import { Role } from 'roleypoly/common/types';
import { guildRoles } from 'roleypoly/common/types/storyData';
const roles: Role.AsObject[] = [
const roles: Role[] = [
{
...guildRoles.rolesList[0],
permissions: permissions.ADMINISTRATOR,

View file

@ -1,14 +1,16 @@
import { Role } from 'roleypoly/src/rpc/shared';
import { Role } from '../types';
export const hasPermission = (roles: Role.AsObject[], permission: number): boolean => {
const aggregateRoles = roles.reduce((acc, role) => acc | role.permissions, 0);
return (aggregateRoles & permission) === permission;
export const evaluatePermission = (haystack: number, needle: number): boolean => {
return (haystack & needle) === needle;
};
export const hasPermissionOrAdmin = (
roles: Role.AsObject[],
permission: number
): boolean => hasPermission(roles, permission | permissions.ADMINISTRATOR);
export const hasPermission = (roles: Role[], permission: number): boolean => {
const aggregateRoles = roles.reduce((acc, role) => acc | role.permissions, 0);
return evaluatePermission(aggregateRoles, permission);
};
export const hasPermissionOrAdmin = (roles: Role[], permission: number): boolean =>
hasPermission(roles, permission | permissions.ADMINISTRATOR);
export const permissions = {
CREATE_INSTANT_INVITE: 0x1,

View file

@ -0,0 +1 @@
export const isBrowser = () => typeof window !== 'undefined';

View file

@ -1,9 +0,0 @@
import { DiscordUser } from 'roleypoly/src/rpc/shared';
import { user } from 'roleypoly/src/design-system/shared-types/storyData';
import { AsObjectToProto } from './protoReflection';
it('converts a RoleypolyUser.AsObject back to protobuf', () => {
const proto = AsObjectToProto(DiscordUser, user);
expect(proto.toObject()).toMatchObject(user);
});

View file

@ -1,47 +0,0 @@
import * as pbjs from 'google-protobuf';
// Protobuf Message itself
type GenericObject<T extends pbjs.Message> = T;
// Message's "setter" call
type ProtoFunction<T extends pbjs.Message, U extends ReturnType<T['toObject']>> = (
value: U[keyof U]
) => void;
/**
* AsObjectToProto does the opposite of ProtoMessage.toObject().
* This function turns regular JS objects back into their source protobuf message type,
* with the help us copious amounts of reflection.
* @param protoClass A protobuf message class
* @param input A JS object that corresponds to the protobuf message class.
*/
export const AsObjectToProto = <T extends pbjs.Message>(
protoClass: { new (): T },
input: ReturnType<T['toObject']>
): GenericObject<T> => {
// First, we create the message itself
const proto = new protoClass();
// We want the keys from the message, this will give us the setter names we need.
const protoKeys = Object.getOwnPropertyNames((proto as any).__proto__);
// Loop over the input data keys
for (let inputKey in input) {
// As we loop, find the setter function for the key
const setCallName = protoKeys.find(
(key) => `set${inputKey.toLowerCase()}` === key.toLowerCase()
) as keyof typeof proto;
// If we encounter a key without a place to go, we silently ignore it.
if (!setCallName) {
continue;
}
// But, if it all succeeds, we call the setter with the JS object's value.
((proto[setCallName] as unknown) as ProtoFunction<T, typeof input>)(
input[inputKey]
);
}
return proto;
};

View file

@ -1,7 +0,0 @@
load("//hack/bazel/js:react.bzl", "react_library")
package(default_visibility = ["//visibility:public"])
react_library(
name = "withContext",
)

View file

@ -1,19 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "version",
srcs = ["version.go"],
importpath = "github.com/roleypoly/roleypoly/src/common/version",
visibility = ["//visibility:public"],
x_defs = {
"GitCommit": "{STABLE_GIT_COMMIT}",
"GitBranch": "{STABLE_GIT_BRANCH}",
"BuildDate": "{BUILD_DATE}",
},
)
go_test(
name = "version_test",
srcs = ["version_test.go"],
embed = [":version"],
)

1
src/db/.gitignore vendored
View file

@ -1 +0,0 @@
.env

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019 roleypoly maintainers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,17 +0,0 @@
# DB
Roleypoly's DB schemas, connectors, and other useful database admin tools.
## Tools
### ent
ent schema and the files it generates.
Edit nothing outside of the `schemas` folder, as all others are generated.
When done editing, do `go generate ./ent` to update generation.
_Failing to generate files will make CI fail._
All schemas must be backwards compatible with previous versions of this library, and be compatible with **CockroachDB**-based Postgres.

View file

@ -1,45 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "ent",
srcs = [
"challenge.go",
"challenge_create.go",
"challenge_delete.go",
"challenge_query.go",
"challenge_update.go",
"client.go",
"config.go",
"context.go",
"ent.go",
"generate.go",
"guild.go",
"guild_create.go",
"guild_delete.go",
"guild_query.go",
"guild_update.go",
"mutation.go",
"runtime.go",
"session.go",
"session_create.go",
"session_delete.go",
"session_query.go",
"session_update.go",
"tx.go",
],
importpath = "github.com/roleypoly/roleypoly/src/db/ent",
visibility = ["//visibility:public"],
deps = [
"//src/db/ent/challenge",
"//src/db/ent/guild",
"//src/db/ent/migrate",
"//src/db/ent/predicate",
"//src/db/ent/schema",
"//src/db/ent/session",
"@com_github_facebook_ent//:ent",
"@com_github_facebook_ent//dialect",
"@com_github_facebook_ent//dialect/sql",
"@com_github_facebook_ent//dialect/sql/sqlgraph",
"@com_github_facebook_ent//schema/field",
],
)

View file

@ -1,147 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"github.com/facebook/ent/dialect/sql"
"github.com/roleypoly/roleypoly/src/db/ent/challenge"
)
// Challenge is the model entity for the Challenge schema.
type Challenge struct {
config `json:"-"`
// ID of the ent.
ID int `json:"id,omitempty"`
// CreateTime holds the value of the "create_time" field.
CreateTime time.Time `json:"create_time,omitempty"`
// UpdateTime holds the value of the "update_time" field.
UpdateTime time.Time `json:"update_time,omitempty"`
// ChallengeID holds the value of the "challenge_id" field.
ChallengeID string `json:"challenge_id,omitempty"`
// UserID holds the value of the "user_id" field.
UserID string `json:"user_id,omitempty"`
// Human holds the value of the "human" field.
Human string `json:"human,omitempty"`
// Magic holds the value of the "magic" field.
Magic string `json:"magic,omitempty"`
// ExpiresAt holds the value of the "expires_at" field.
ExpiresAt time.Time `json:"expires_at,omitempty"`
}
// scanValues returns the types for scanning values from sql.Rows.
func (*Challenge) scanValues() []interface{} {
return []interface{}{
&sql.NullInt64{}, // id
&sql.NullTime{}, // create_time
&sql.NullTime{}, // update_time
&sql.NullString{}, // challenge_id
&sql.NullString{}, // user_id
&sql.NullString{}, // human
&sql.NullString{}, // magic
&sql.NullTime{}, // expires_at
}
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the Challenge fields.
func (c *Challenge) assignValues(values ...interface{}) error {
if m, n := len(values), len(challenge.Columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
value, ok := values[0].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
c.ID = int(value.Int64)
values = values[1:]
if value, ok := values[0].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field create_time", values[0])
} else if value.Valid {
c.CreateTime = value.Time
}
if value, ok := values[1].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field update_time", values[1])
} else if value.Valid {
c.UpdateTime = value.Time
}
if value, ok := values[2].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field challenge_id", values[2])
} else if value.Valid {
c.ChallengeID = value.String
}
if value, ok := values[3].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field user_id", values[3])
} else if value.Valid {
c.UserID = value.String
}
if value, ok := values[4].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field human", values[4])
} else if value.Valid {
c.Human = value.String
}
if value, ok := values[5].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field magic", values[5])
} else if value.Valid {
c.Magic = value.String
}
if value, ok := values[6].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field expires_at", values[6])
} else if value.Valid {
c.ExpiresAt = value.Time
}
return nil
}
// Update returns a builder for updating this Challenge.
// Note that, you need to call Challenge.Unwrap() before calling this method, if this Challenge
// was returned from a transaction, and the transaction was committed or rolled back.
func (c *Challenge) Update() *ChallengeUpdateOne {
return (&ChallengeClient{config: c.config}).UpdateOne(c)
}
// Unwrap unwraps the entity that was returned from a transaction after it was closed,
// so that all next queries will be executed through the driver which created the transaction.
func (c *Challenge) Unwrap() *Challenge {
tx, ok := c.config.driver.(*txDriver)
if !ok {
panic("ent: Challenge is not a transactional entity")
}
c.config.driver = tx.drv
return c
}
// String implements the fmt.Stringer.
func (c *Challenge) String() string {
var builder strings.Builder
builder.WriteString("Challenge(")
builder.WriteString(fmt.Sprintf("id=%v", c.ID))
builder.WriteString(", create_time=")
builder.WriteString(c.CreateTime.Format(time.ANSIC))
builder.WriteString(", update_time=")
builder.WriteString(c.UpdateTime.Format(time.ANSIC))
builder.WriteString(", challenge_id=")
builder.WriteString(c.ChallengeID)
builder.WriteString(", user_id=")
builder.WriteString(c.UserID)
builder.WriteString(", human=")
builder.WriteString(c.Human)
builder.WriteString(", magic=")
builder.WriteString(c.Magic)
builder.WriteString(", expires_at=")
builder.WriteString(c.ExpiresAt.Format(time.ANSIC))
builder.WriteByte(')')
return builder.String()
}
// Challenges is a parsable slice of Challenge.
type Challenges []*Challenge
func (c Challenges) config(cfg config) {
for _i := range c {
c[_i].config = cfg
}
}

View file

@ -1,15 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "challenge",
srcs = [
"challenge.go",
"where.go",
],
importpath = "github.com/roleypoly/roleypoly/src/db/ent/challenge",
visibility = ["//visibility:public"],
deps = [
"//src/db/ent/predicate",
"@com_github_facebook_ent//dialect/sql",
],
)

View file

@ -1,64 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package challenge
import (
"time"
)
const (
// Label holds the string label denoting the challenge type in the database.
Label = "challenge"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldCreateTime holds the string denoting the create_time field in the database.
FieldCreateTime = "create_time"
// FieldUpdateTime holds the string denoting the update_time field in the database.
FieldUpdateTime = "update_time"
// FieldChallengeID holds the string denoting the challenge_id field in the database.
FieldChallengeID = "challenge_id"
// FieldUserID holds the string denoting the user_id field in the database.
FieldUserID = "user_id"
// FieldHuman holds the string denoting the human field in the database.
FieldHuman = "human"
// FieldMagic holds the string denoting the magic field in the database.
FieldMagic = "magic"
// FieldExpiresAt holds the string denoting the expires_at field in the database.
FieldExpiresAt = "expires_at"
// Table holds the table name of the challenge in the database.
Table = "challenges"
)
// Columns holds all SQL columns for challenge fields.
var Columns = []string{
FieldID,
FieldCreateTime,
FieldUpdateTime,
FieldChallengeID,
FieldUserID,
FieldHuman,
FieldMagic,
FieldExpiresAt,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// DefaultCreateTime holds the default value on creation for the create_time field.
DefaultCreateTime func() time.Time
// DefaultUpdateTime holds the default value on creation for the update_time field.
DefaultUpdateTime func() time.Time
// UpdateDefaultUpdateTime holds the default value on update for the update_time field.
UpdateDefaultUpdateTime func() time.Time
// DefaultExpiresAt holds the default value on creation for the expires_at field.
DefaultExpiresAt func() time.Time
)

View file

@ -1,846 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package challenge
import (
"time"
"github.com/facebook/ent/dialect/sql"
"github.com/roleypoly/roleypoly/src/db/ent/predicate"
)
// ID filters vertices based on their identifier.
func ID(id int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldID), id))
})
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldID), id))
})
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldID), id))
})
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(ids) == 0 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
s.Where(sql.In(s.C(FieldID), v...))
})
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(ids) == 0 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
s.Where(sql.NotIn(s.C(FieldID), v...))
})
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldID), id))
})
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldID), id))
})
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldID), id))
})
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldID), id))
})
}
// CreateTime applies equality check predicate on the "create_time" field. It's identical to CreateTimeEQ.
func CreateTime(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldCreateTime), v))
})
}
// UpdateTime applies equality check predicate on the "update_time" field. It's identical to UpdateTimeEQ.
func UpdateTime(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUpdateTime), v))
})
}
// ChallengeID applies equality check predicate on the "challenge_id" field. It's identical to ChallengeIDEQ.
func ChallengeID(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldChallengeID), v))
})
}
// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
func UserID(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUserID), v))
})
}
// Human applies equality check predicate on the "human" field. It's identical to HumanEQ.
func Human(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldHuman), v))
})
}
// Magic applies equality check predicate on the "magic" field. It's identical to MagicEQ.
func Magic(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldMagic), v))
})
}
// ExpiresAt applies equality check predicate on the "expires_at" field. It's identical to ExpiresAtEQ.
func ExpiresAt(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldExpiresAt), v))
})
}
// CreateTimeEQ applies the EQ predicate on the "create_time" field.
func CreateTimeEQ(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldCreateTime), v))
})
}
// CreateTimeNEQ applies the NEQ predicate on the "create_time" field.
func CreateTimeNEQ(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldCreateTime), v))
})
}
// CreateTimeIn applies the In predicate on the "create_time" field.
func CreateTimeIn(vs ...time.Time) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldCreateTime), v...))
})
}
// CreateTimeNotIn applies the NotIn predicate on the "create_time" field.
func CreateTimeNotIn(vs ...time.Time) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldCreateTime), v...))
})
}
// CreateTimeGT applies the GT predicate on the "create_time" field.
func CreateTimeGT(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldCreateTime), v))
})
}
// CreateTimeGTE applies the GTE predicate on the "create_time" field.
func CreateTimeGTE(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldCreateTime), v))
})
}
// CreateTimeLT applies the LT predicate on the "create_time" field.
func CreateTimeLT(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldCreateTime), v))
})
}
// CreateTimeLTE applies the LTE predicate on the "create_time" field.
func CreateTimeLTE(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldCreateTime), v))
})
}
// UpdateTimeEQ applies the EQ predicate on the "update_time" field.
func UpdateTimeEQ(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeNEQ applies the NEQ predicate on the "update_time" field.
func UpdateTimeNEQ(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeIn applies the In predicate on the "update_time" field.
func UpdateTimeIn(vs ...time.Time) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldUpdateTime), v...))
})
}
// UpdateTimeNotIn applies the NotIn predicate on the "update_time" field.
func UpdateTimeNotIn(vs ...time.Time) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldUpdateTime), v...))
})
}
// UpdateTimeGT applies the GT predicate on the "update_time" field.
func UpdateTimeGT(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeGTE applies the GTE predicate on the "update_time" field.
func UpdateTimeGTE(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeLT applies the LT predicate on the "update_time" field.
func UpdateTimeLT(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeLTE applies the LTE predicate on the "update_time" field.
func UpdateTimeLTE(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldUpdateTime), v))
})
}
// ChallengeIDEQ applies the EQ predicate on the "challenge_id" field.
func ChallengeIDEQ(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldChallengeID), v))
})
}
// ChallengeIDNEQ applies the NEQ predicate on the "challenge_id" field.
func ChallengeIDNEQ(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldChallengeID), v))
})
}
// ChallengeIDIn applies the In predicate on the "challenge_id" field.
func ChallengeIDIn(vs ...string) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldChallengeID), v...))
})
}
// ChallengeIDNotIn applies the NotIn predicate on the "challenge_id" field.
func ChallengeIDNotIn(vs ...string) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldChallengeID), v...))
})
}
// ChallengeIDGT applies the GT predicate on the "challenge_id" field.
func ChallengeIDGT(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldChallengeID), v))
})
}
// ChallengeIDGTE applies the GTE predicate on the "challenge_id" field.
func ChallengeIDGTE(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldChallengeID), v))
})
}
// ChallengeIDLT applies the LT predicate on the "challenge_id" field.
func ChallengeIDLT(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldChallengeID), v))
})
}
// ChallengeIDLTE applies the LTE predicate on the "challenge_id" field.
func ChallengeIDLTE(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldChallengeID), v))
})
}
// ChallengeIDContains applies the Contains predicate on the "challenge_id" field.
func ChallengeIDContains(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldChallengeID), v))
})
}
// ChallengeIDHasPrefix applies the HasPrefix predicate on the "challenge_id" field.
func ChallengeIDHasPrefix(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldChallengeID), v))
})
}
// ChallengeIDHasSuffix applies the HasSuffix predicate on the "challenge_id" field.
func ChallengeIDHasSuffix(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldChallengeID), v))
})
}
// ChallengeIDEqualFold applies the EqualFold predicate on the "challenge_id" field.
func ChallengeIDEqualFold(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldChallengeID), v))
})
}
// ChallengeIDContainsFold applies the ContainsFold predicate on the "challenge_id" field.
func ChallengeIDContainsFold(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldChallengeID), v))
})
}
// UserIDEQ applies the EQ predicate on the "user_id" field.
func UserIDEQ(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUserID), v))
})
}
// UserIDNEQ applies the NEQ predicate on the "user_id" field.
func UserIDNEQ(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldUserID), v))
})
}
// UserIDIn applies the In predicate on the "user_id" field.
func UserIDIn(vs ...string) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldUserID), v...))
})
}
// UserIDNotIn applies the NotIn predicate on the "user_id" field.
func UserIDNotIn(vs ...string) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldUserID), v...))
})
}
// UserIDGT applies the GT predicate on the "user_id" field.
func UserIDGT(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldUserID), v))
})
}
// UserIDGTE applies the GTE predicate on the "user_id" field.
func UserIDGTE(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldUserID), v))
})
}
// UserIDLT applies the LT predicate on the "user_id" field.
func UserIDLT(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldUserID), v))
})
}
// UserIDLTE applies the LTE predicate on the "user_id" field.
func UserIDLTE(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldUserID), v))
})
}
// UserIDContains applies the Contains predicate on the "user_id" field.
func UserIDContains(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldUserID), v))
})
}
// UserIDHasPrefix applies the HasPrefix predicate on the "user_id" field.
func UserIDHasPrefix(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldUserID), v))
})
}
// UserIDHasSuffix applies the HasSuffix predicate on the "user_id" field.
func UserIDHasSuffix(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldUserID), v))
})
}
// UserIDEqualFold applies the EqualFold predicate on the "user_id" field.
func UserIDEqualFold(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldUserID), v))
})
}
// UserIDContainsFold applies the ContainsFold predicate on the "user_id" field.
func UserIDContainsFold(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldUserID), v))
})
}
// HumanEQ applies the EQ predicate on the "human" field.
func HumanEQ(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldHuman), v))
})
}
// HumanNEQ applies the NEQ predicate on the "human" field.
func HumanNEQ(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldHuman), v))
})
}
// HumanIn applies the In predicate on the "human" field.
func HumanIn(vs ...string) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldHuman), v...))
})
}
// HumanNotIn applies the NotIn predicate on the "human" field.
func HumanNotIn(vs ...string) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldHuman), v...))
})
}
// HumanGT applies the GT predicate on the "human" field.
func HumanGT(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldHuman), v))
})
}
// HumanGTE applies the GTE predicate on the "human" field.
func HumanGTE(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldHuman), v))
})
}
// HumanLT applies the LT predicate on the "human" field.
func HumanLT(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldHuman), v))
})
}
// HumanLTE applies the LTE predicate on the "human" field.
func HumanLTE(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldHuman), v))
})
}
// HumanContains applies the Contains predicate on the "human" field.
func HumanContains(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldHuman), v))
})
}
// HumanHasPrefix applies the HasPrefix predicate on the "human" field.
func HumanHasPrefix(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldHuman), v))
})
}
// HumanHasSuffix applies the HasSuffix predicate on the "human" field.
func HumanHasSuffix(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldHuman), v))
})
}
// HumanEqualFold applies the EqualFold predicate on the "human" field.
func HumanEqualFold(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldHuman), v))
})
}
// HumanContainsFold applies the ContainsFold predicate on the "human" field.
func HumanContainsFold(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldHuman), v))
})
}
// MagicEQ applies the EQ predicate on the "magic" field.
func MagicEQ(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldMagic), v))
})
}
// MagicNEQ applies the NEQ predicate on the "magic" field.
func MagicNEQ(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldMagic), v))
})
}
// MagicIn applies the In predicate on the "magic" field.
func MagicIn(vs ...string) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldMagic), v...))
})
}
// MagicNotIn applies the NotIn predicate on the "magic" field.
func MagicNotIn(vs ...string) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldMagic), v...))
})
}
// MagicGT applies the GT predicate on the "magic" field.
func MagicGT(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldMagic), v))
})
}
// MagicGTE applies the GTE predicate on the "magic" field.
func MagicGTE(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldMagic), v))
})
}
// MagicLT applies the LT predicate on the "magic" field.
func MagicLT(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldMagic), v))
})
}
// MagicLTE applies the LTE predicate on the "magic" field.
func MagicLTE(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldMagic), v))
})
}
// MagicContains applies the Contains predicate on the "magic" field.
func MagicContains(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldMagic), v))
})
}
// MagicHasPrefix applies the HasPrefix predicate on the "magic" field.
func MagicHasPrefix(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldMagic), v))
})
}
// MagicHasSuffix applies the HasSuffix predicate on the "magic" field.
func MagicHasSuffix(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldMagic), v))
})
}
// MagicEqualFold applies the EqualFold predicate on the "magic" field.
func MagicEqualFold(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldMagic), v))
})
}
// MagicContainsFold applies the ContainsFold predicate on the "magic" field.
func MagicContainsFold(v string) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldMagic), v))
})
}
// ExpiresAtEQ applies the EQ predicate on the "expires_at" field.
func ExpiresAtEQ(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldExpiresAt), v))
})
}
// ExpiresAtNEQ applies the NEQ predicate on the "expires_at" field.
func ExpiresAtNEQ(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldExpiresAt), v))
})
}
// ExpiresAtIn applies the In predicate on the "expires_at" field.
func ExpiresAtIn(vs ...time.Time) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldExpiresAt), v...))
})
}
// ExpiresAtNotIn applies the NotIn predicate on the "expires_at" field.
func ExpiresAtNotIn(vs ...time.Time) predicate.Challenge {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Challenge(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldExpiresAt), v...))
})
}
// ExpiresAtGT applies the GT predicate on the "expires_at" field.
func ExpiresAtGT(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldExpiresAt), v))
})
}
// ExpiresAtGTE applies the GTE predicate on the "expires_at" field.
func ExpiresAtGTE(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldExpiresAt), v))
})
}
// ExpiresAtLT applies the LT predicate on the "expires_at" field.
func ExpiresAtLT(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldExpiresAt), v))
})
}
// ExpiresAtLTE applies the LTE predicate on the "expires_at" field.
func ExpiresAtLTE(v time.Time) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldExpiresAt), v))
})
}
// And groups list of predicates with the AND operator between them.
func And(predicates ...predicate.Challenge) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s1 := s.Clone().SetP(nil)
for _, p := range predicates {
p(s1)
}
s.Where(s1.P())
})
}
// Or groups list of predicates with the OR operator between them.
func Or(predicates ...predicate.Challenge) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
s1 := s.Clone().SetP(nil)
for i, p := range predicates {
if i > 0 {
s1.Or()
}
p(s1)
}
s.Where(s1.P())
})
}
// Not applies the not operator on the given predicate.
func Not(p predicate.Challenge) predicate.Challenge {
return predicate.Challenge(func(s *sql.Selector) {
p(s.Not())
})
}

View file

@ -1,329 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"github.com/facebook/ent/dialect/sql/sqlgraph"
"github.com/facebook/ent/schema/field"
"github.com/roleypoly/roleypoly/src/db/ent/challenge"
)
// ChallengeCreate is the builder for creating a Challenge entity.
type ChallengeCreate struct {
config
mutation *ChallengeMutation
hooks []Hook
}
// SetCreateTime sets the create_time field.
func (cc *ChallengeCreate) SetCreateTime(t time.Time) *ChallengeCreate {
cc.mutation.SetCreateTime(t)
return cc
}
// SetNillableCreateTime sets the create_time field if the given value is not nil.
func (cc *ChallengeCreate) SetNillableCreateTime(t *time.Time) *ChallengeCreate {
if t != nil {
cc.SetCreateTime(*t)
}
return cc
}
// SetUpdateTime sets the update_time field.
func (cc *ChallengeCreate) SetUpdateTime(t time.Time) *ChallengeCreate {
cc.mutation.SetUpdateTime(t)
return cc
}
// SetNillableUpdateTime sets the update_time field if the given value is not nil.
func (cc *ChallengeCreate) SetNillableUpdateTime(t *time.Time) *ChallengeCreate {
if t != nil {
cc.SetUpdateTime(*t)
}
return cc
}
// SetChallengeID sets the challenge_id field.
func (cc *ChallengeCreate) SetChallengeID(s string) *ChallengeCreate {
cc.mutation.SetChallengeID(s)
return cc
}
// SetUserID sets the user_id field.
func (cc *ChallengeCreate) SetUserID(s string) *ChallengeCreate {
cc.mutation.SetUserID(s)
return cc
}
// SetHuman sets the human field.
func (cc *ChallengeCreate) SetHuman(s string) *ChallengeCreate {
cc.mutation.SetHuman(s)
return cc
}
// SetMagic sets the magic field.
func (cc *ChallengeCreate) SetMagic(s string) *ChallengeCreate {
cc.mutation.SetMagic(s)
return cc
}
// SetExpiresAt sets the expires_at field.
func (cc *ChallengeCreate) SetExpiresAt(t time.Time) *ChallengeCreate {
cc.mutation.SetExpiresAt(t)
return cc
}
// SetNillableExpiresAt sets the expires_at field if the given value is not nil.
func (cc *ChallengeCreate) SetNillableExpiresAt(t *time.Time) *ChallengeCreate {
if t != nil {
cc.SetExpiresAt(*t)
}
return cc
}
// Mutation returns the ChallengeMutation object of the builder.
func (cc *ChallengeCreate) Mutation() *ChallengeMutation {
return cc.mutation
}
// Save creates the Challenge in the database.
func (cc *ChallengeCreate) Save(ctx context.Context) (*Challenge, error) {
var (
err error
node *Challenge
)
cc.defaults()
if len(cc.hooks) == 0 {
if err = cc.check(); err != nil {
return nil, err
}
node, err = cc.sqlSave(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ChallengeMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err = cc.check(); err != nil {
return nil, err
}
cc.mutation = mutation
node, err = cc.sqlSave(ctx)
mutation.done = true
return node, err
})
for i := len(cc.hooks) - 1; i >= 0; i-- {
mut = cc.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, cc.mutation); err != nil {
return nil, err
}
}
return node, err
}
// SaveX calls Save and panics if Save returns an error.
func (cc *ChallengeCreate) SaveX(ctx context.Context) *Challenge {
v, err := cc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// defaults sets the default values of the builder before save.
func (cc *ChallengeCreate) defaults() {
if _, ok := cc.mutation.CreateTime(); !ok {
v := challenge.DefaultCreateTime()
cc.mutation.SetCreateTime(v)
}
if _, ok := cc.mutation.UpdateTime(); !ok {
v := challenge.DefaultUpdateTime()
cc.mutation.SetUpdateTime(v)
}
if _, ok := cc.mutation.ExpiresAt(); !ok {
v := challenge.DefaultExpiresAt()
cc.mutation.SetExpiresAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (cc *ChallengeCreate) check() error {
if _, ok := cc.mutation.CreateTime(); !ok {
return &ValidationError{Name: "create_time", err: errors.New("ent: missing required field \"create_time\"")}
}
if _, ok := cc.mutation.UpdateTime(); !ok {
return &ValidationError{Name: "update_time", err: errors.New("ent: missing required field \"update_time\"")}
}
if _, ok := cc.mutation.ChallengeID(); !ok {
return &ValidationError{Name: "challenge_id", err: errors.New("ent: missing required field \"challenge_id\"")}
}
if _, ok := cc.mutation.UserID(); !ok {
return &ValidationError{Name: "user_id", err: errors.New("ent: missing required field \"user_id\"")}
}
if _, ok := cc.mutation.Human(); !ok {
return &ValidationError{Name: "human", err: errors.New("ent: missing required field \"human\"")}
}
if _, ok := cc.mutation.Magic(); !ok {
return &ValidationError{Name: "magic", err: errors.New("ent: missing required field \"magic\"")}
}
if _, ok := cc.mutation.ExpiresAt(); !ok {
return &ValidationError{Name: "expires_at", err: errors.New("ent: missing required field \"expires_at\"")}
}
return nil
}
func (cc *ChallengeCreate) sqlSave(ctx context.Context) (*Challenge, error) {
_node, _spec := cc.createSpec()
if err := sqlgraph.CreateNode(ctx, cc.driver, _spec); err != nil {
if cerr, ok := isSQLConstraintError(err); ok {
err = cerr
}
return nil, err
}
id := _spec.ID.Value.(int64)
_node.ID = int(id)
return _node, nil
}
func (cc *ChallengeCreate) createSpec() (*Challenge, *sqlgraph.CreateSpec) {
var (
_node = &Challenge{config: cc.config}
_spec = &sqlgraph.CreateSpec{
Table: challenge.Table,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: challenge.FieldID,
},
}
)
if value, ok := cc.mutation.CreateTime(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: challenge.FieldCreateTime,
})
_node.CreateTime = value
}
if value, ok := cc.mutation.UpdateTime(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: challenge.FieldUpdateTime,
})
_node.UpdateTime = value
}
if value, ok := cc.mutation.ChallengeID(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: challenge.FieldChallengeID,
})
_node.ChallengeID = value
}
if value, ok := cc.mutation.UserID(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: challenge.FieldUserID,
})
_node.UserID = value
}
if value, ok := cc.mutation.Human(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: challenge.FieldHuman,
})
_node.Human = value
}
if value, ok := cc.mutation.Magic(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: challenge.FieldMagic,
})
_node.Magic = value
}
if value, ok := cc.mutation.ExpiresAt(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: challenge.FieldExpiresAt,
})
_node.ExpiresAt = value
}
return _node, _spec
}
// ChallengeCreateBulk is the builder for creating a bulk of Challenge entities.
type ChallengeCreateBulk struct {
config
builders []*ChallengeCreate
}
// Save creates the Challenge entities in the database.
func (ccb *ChallengeCreateBulk) Save(ctx context.Context) ([]*Challenge, error) {
specs := make([]*sqlgraph.CreateSpec, len(ccb.builders))
nodes := make([]*Challenge, len(ccb.builders))
mutators := make([]Mutator, len(ccb.builders))
for i := range ccb.builders {
func(i int, root context.Context) {
builder := ccb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ChallengeMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err := builder.check(); err != nil {
return nil, err
}
builder.mutation = mutation
nodes[i], specs[i] = builder.createSpec()
var err error
if i < len(mutators)-1 {
_, err = mutators[i+1].Mutate(root, ccb.builders[i+1].mutation)
} else {
// Invoke the actual operation on the latest mutation in the chain.
if err = sqlgraph.BatchCreate(ctx, ccb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil {
if cerr, ok := isSQLConstraintError(err); ok {
err = cerr
}
}
}
mutation.done = true
if err != nil {
return nil, err
}
id := specs[i].ID.Value.(int64)
nodes[i].ID = int(id)
return nodes[i], nil
})
for i := len(builder.hooks) - 1; i >= 0; i-- {
mut = builder.hooks[i](mut)
}
mutators[i] = mut
}(i, ctx)
}
if len(mutators) > 0 {
if _, err := mutators[0].Mutate(ctx, ccb.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX calls Save and panics if Save returns an error.
func (ccb *ChallengeCreateBulk) SaveX(ctx context.Context) []*Challenge {
v, err := ccb.Save(ctx)
if err != nil {
panic(err)
}
return v
}

View file

@ -1,109 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"github.com/facebook/ent/dialect/sql"
"github.com/facebook/ent/dialect/sql/sqlgraph"
"github.com/facebook/ent/schema/field"
"github.com/roleypoly/roleypoly/src/db/ent/challenge"
"github.com/roleypoly/roleypoly/src/db/ent/predicate"
)
// ChallengeDelete is the builder for deleting a Challenge entity.
type ChallengeDelete struct {
config
hooks []Hook
mutation *ChallengeMutation
predicates []predicate.Challenge
}
// Where adds a new predicate to the delete builder.
func (cd *ChallengeDelete) Where(ps ...predicate.Challenge) *ChallengeDelete {
cd.predicates = append(cd.predicates, ps...)
return cd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (cd *ChallengeDelete) Exec(ctx context.Context) (int, error) {
var (
err error
affected int
)
if len(cd.hooks) == 0 {
affected, err = cd.sqlExec(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ChallengeMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
cd.mutation = mutation
affected, err = cd.sqlExec(ctx)
mutation.done = true
return affected, err
})
for i := len(cd.hooks) - 1; i >= 0; i-- {
mut = cd.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, cd.mutation); err != nil {
return 0, err
}
}
return affected, err
}
// ExecX is like Exec, but panics if an error occurs.
func (cd *ChallengeDelete) ExecX(ctx context.Context) int {
n, err := cd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (cd *ChallengeDelete) sqlExec(ctx context.Context) (int, error) {
_spec := &sqlgraph.DeleteSpec{
Node: &sqlgraph.NodeSpec{
Table: challenge.Table,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: challenge.FieldID,
},
},
}
if ps := cd.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return sqlgraph.DeleteNodes(ctx, cd.driver, _spec)
}
// ChallengeDeleteOne is the builder for deleting a single Challenge entity.
type ChallengeDeleteOne struct {
cd *ChallengeDelete
}
// Exec executes the deletion query.
func (cdo *ChallengeDeleteOne) Exec(ctx context.Context) error {
n, err := cdo.cd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{challenge.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (cdo *ChallengeDeleteOne) ExecX(ctx context.Context) {
cdo.cd.ExecX(ctx)
}

View file

@ -1,880 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"math"
"github.com/facebook/ent/dialect/sql"
"github.com/facebook/ent/dialect/sql/sqlgraph"
"github.com/facebook/ent/schema/field"
"github.com/roleypoly/roleypoly/src/db/ent/challenge"
"github.com/roleypoly/roleypoly/src/db/ent/predicate"
)
// ChallengeQuery is the builder for querying Challenge entities.
type ChallengeQuery struct {
config
limit *int
offset *int
order []OrderFunc
unique []string
predicates []predicate.Challenge
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the builder.
func (cq *ChallengeQuery) Where(ps ...predicate.Challenge) *ChallengeQuery {
cq.predicates = append(cq.predicates, ps...)
return cq
}
// Limit adds a limit step to the query.
func (cq *ChallengeQuery) Limit(limit int) *ChallengeQuery {
cq.limit = &limit
return cq
}
// Offset adds an offset step to the query.
func (cq *ChallengeQuery) Offset(offset int) *ChallengeQuery {
cq.offset = &offset
return cq
}
// Order adds an order step to the query.
func (cq *ChallengeQuery) Order(o ...OrderFunc) *ChallengeQuery {
cq.order = append(cq.order, o...)
return cq
}
// First returns the first Challenge entity in the query. Returns *NotFoundError when no challenge was found.
func (cq *ChallengeQuery) First(ctx context.Context) (*Challenge, error) {
nodes, err := cq.Limit(1).All(ctx)
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{challenge.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (cq *ChallengeQuery) FirstX(ctx context.Context) *Challenge {
node, err := cq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first Challenge id in the query. Returns *NotFoundError when no id was found.
func (cq *ChallengeQuery) FirstID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = cq.Limit(1).IDs(ctx); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{challenge.Label}
return
}
return ids[0], nil
}
// FirstXID is like FirstID, but panics if an error occurs.
func (cq *ChallengeQuery) FirstXID(ctx context.Context) int {
id, err := cq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns the only Challenge entity in the query, returns an error if not exactly one entity was returned.
func (cq *ChallengeQuery) Only(ctx context.Context) (*Challenge, error) {
nodes, err := cq.Limit(2).All(ctx)
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{challenge.Label}
default:
return nil, &NotSingularError{challenge.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (cq *ChallengeQuery) OnlyX(ctx context.Context) *Challenge {
node, err := cq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID returns the only Challenge id in the query, returns an error if not exactly one id was returned.
func (cq *ChallengeQuery) OnlyID(ctx context.Context) (id int, err error) {
var ids []int
if ids, err = cq.Limit(2).IDs(ctx); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{challenge.Label}
default:
err = &NotSingularError{challenge.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (cq *ChallengeQuery) OnlyIDX(ctx context.Context) int {
id, err := cq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of Challenges.
func (cq *ChallengeQuery) All(ctx context.Context) ([]*Challenge, error) {
if err := cq.prepareQuery(ctx); err != nil {
return nil, err
}
return cq.sqlAll(ctx)
}
// AllX is like All, but panics if an error occurs.
func (cq *ChallengeQuery) AllX(ctx context.Context) []*Challenge {
nodes, err := cq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of Challenge ids.
func (cq *ChallengeQuery) IDs(ctx context.Context) ([]int, error) {
var ids []int
if err := cq.Select(challenge.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (cq *ChallengeQuery) IDsX(ctx context.Context) []int {
ids, err := cq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (cq *ChallengeQuery) Count(ctx context.Context) (int, error) {
if err := cq.prepareQuery(ctx); err != nil {
return 0, err
}
return cq.sqlCount(ctx)
}
// CountX is like Count, but panics if an error occurs.
func (cq *ChallengeQuery) CountX(ctx context.Context) int {
count, err := cq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (cq *ChallengeQuery) Exist(ctx context.Context) (bool, error) {
if err := cq.prepareQuery(ctx); err != nil {
return false, err
}
return cq.sqlExist(ctx)
}
// ExistX is like Exist, but panics if an error occurs.
func (cq *ChallengeQuery) ExistX(ctx context.Context) bool {
exist, err := cq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the query builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (cq *ChallengeQuery) Clone() *ChallengeQuery {
return &ChallengeQuery{
config: cq.config,
limit: cq.limit,
offset: cq.offset,
order: append([]OrderFunc{}, cq.order...),
unique: append([]string{}, cq.unique...),
predicates: append([]predicate.Challenge{}, cq.predicates...),
// clone intermediate query.
sql: cq.sql.Clone(),
path: cq.path,
}
}
// GroupBy used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// CreateTime time.Time `json:"create_time,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.Challenge.Query().
// GroupBy(challenge.FieldCreateTime).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
//
func (cq *ChallengeQuery) GroupBy(field string, fields ...string) *ChallengeGroupBy {
group := &ChallengeGroupBy{config: cq.config}
group.fields = append([]string{field}, fields...)
group.path = func(ctx context.Context) (prev *sql.Selector, err error) {
if err := cq.prepareQuery(ctx); err != nil {
return nil, err
}
return cq.sqlQuery(), nil
}
return group
}
// Select one or more fields from the given query.
//
// Example:
//
// var v []struct {
// CreateTime time.Time `json:"create_time,omitempty"`
// }
//
// client.Challenge.Query().
// Select(challenge.FieldCreateTime).
// Scan(ctx, &v)
//
func (cq *ChallengeQuery) Select(field string, fields ...string) *ChallengeSelect {
selector := &ChallengeSelect{config: cq.config}
selector.fields = append([]string{field}, fields...)
selector.path = func(ctx context.Context) (prev *sql.Selector, err error) {
if err := cq.prepareQuery(ctx); err != nil {
return nil, err
}
return cq.sqlQuery(), nil
}
return selector
}
func (cq *ChallengeQuery) prepareQuery(ctx context.Context) error {
if cq.path != nil {
prev, err := cq.path(ctx)
if err != nil {
return err
}
cq.sql = prev
}
return nil
}
func (cq *ChallengeQuery) sqlAll(ctx context.Context) ([]*Challenge, error) {
var (
nodes = []*Challenge{}
_spec = cq.querySpec()
)
_spec.ScanValues = func() []interface{} {
node := &Challenge{config: cq.config}
nodes = append(nodes, node)
values := node.scanValues()
return values
}
_spec.Assign = func(values ...interface{}) error {
if len(nodes) == 0 {
return fmt.Errorf("ent: Assign called without calling ScanValues")
}
node := nodes[len(nodes)-1]
return node.assignValues(values...)
}
if err := sqlgraph.QueryNodes(ctx, cq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
return nodes, nil
}
func (cq *ChallengeQuery) sqlCount(ctx context.Context) (int, error) {
_spec := cq.querySpec()
return sqlgraph.CountNodes(ctx, cq.driver, _spec)
}
func (cq *ChallengeQuery) sqlExist(ctx context.Context) (bool, error) {
n, err := cq.sqlCount(ctx)
if err != nil {
return false, fmt.Errorf("ent: check existence: %v", err)
}
return n > 0, nil
}
func (cq *ChallengeQuery) querySpec() *sqlgraph.QuerySpec {
_spec := &sqlgraph.QuerySpec{
Node: &sqlgraph.NodeSpec{
Table: challenge.Table,
Columns: challenge.Columns,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: challenge.FieldID,
},
},
From: cq.sql,
Unique: true,
}
if ps := cq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := cq.limit; limit != nil {
_spec.Limit = *limit
}
if offset := cq.offset; offset != nil {
_spec.Offset = *offset
}
if ps := cq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector, challenge.ValidColumn)
}
}
}
return _spec
}
func (cq *ChallengeQuery) sqlQuery() *sql.Selector {
builder := sql.Dialect(cq.driver.Dialect())
t1 := builder.Table(challenge.Table)
selector := builder.Select(t1.Columns(challenge.Columns...)...).From(t1)
if cq.sql != nil {
selector = cq.sql
selector.Select(selector.Columns(challenge.Columns...)...)
}
for _, p := range cq.predicates {
p(selector)
}
for _, p := range cq.order {
p(selector, challenge.ValidColumn)
}
if offset := cq.offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := cq.limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// ChallengeGroupBy is the builder for group-by Challenge entities.
type ChallengeGroupBy struct {
config
fields []string
fns []AggregateFunc
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Aggregate adds the given aggregation functions to the group-by query.
func (cgb *ChallengeGroupBy) Aggregate(fns ...AggregateFunc) *ChallengeGroupBy {
cgb.fns = append(cgb.fns, fns...)
return cgb
}
// Scan applies the group-by query and scan the result into the given value.
func (cgb *ChallengeGroupBy) Scan(ctx context.Context, v interface{}) error {
query, err := cgb.path(ctx)
if err != nil {
return err
}
cgb.sql = query
return cgb.sqlScan(ctx, v)
}
// ScanX is like Scan, but panics if an error occurs.
func (cgb *ChallengeGroupBy) ScanX(ctx context.Context, v interface{}) {
if err := cgb.Scan(ctx, v); err != nil {
panic(err)
}
}
// Strings returns list of strings from group-by. It is only allowed when querying group-by with one field.
func (cgb *ChallengeGroupBy) Strings(ctx context.Context) ([]string, error) {
if len(cgb.fields) > 1 {
return nil, errors.New("ent: ChallengeGroupBy.Strings is not achievable when grouping more than 1 field")
}
var v []string
if err := cgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// StringsX is like Strings, but panics if an error occurs.
func (cgb *ChallengeGroupBy) StringsX(ctx context.Context) []string {
v, err := cgb.Strings(ctx)
if err != nil {
panic(err)
}
return v
}
// String returns a single string from group-by. It is only allowed when querying group-by with one field.
func (cgb *ChallengeGroupBy) String(ctx context.Context) (_ string, err error) {
var v []string
if v, err = cgb.Strings(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{challenge.Label}
default:
err = fmt.Errorf("ent: ChallengeGroupBy.Strings returned %d results when one was expected", len(v))
}
return
}
// StringX is like String, but panics if an error occurs.
func (cgb *ChallengeGroupBy) StringX(ctx context.Context) string {
v, err := cgb.String(ctx)
if err != nil {
panic(err)
}
return v
}
// Ints returns list of ints from group-by. It is only allowed when querying group-by with one field.
func (cgb *ChallengeGroupBy) Ints(ctx context.Context) ([]int, error) {
if len(cgb.fields) > 1 {
return nil, errors.New("ent: ChallengeGroupBy.Ints is not achievable when grouping more than 1 field")
}
var v []int
if err := cgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// IntsX is like Ints, but panics if an error occurs.
func (cgb *ChallengeGroupBy) IntsX(ctx context.Context) []int {
v, err := cgb.Ints(ctx)
if err != nil {
panic(err)
}
return v
}
// Int returns a single int from group-by. It is only allowed when querying group-by with one field.
func (cgb *ChallengeGroupBy) Int(ctx context.Context) (_ int, err error) {
var v []int
if v, err = cgb.Ints(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{challenge.Label}
default:
err = fmt.Errorf("ent: ChallengeGroupBy.Ints returned %d results when one was expected", len(v))
}
return
}
// IntX is like Int, but panics if an error occurs.
func (cgb *ChallengeGroupBy) IntX(ctx context.Context) int {
v, err := cgb.Int(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64s returns list of float64s from group-by. It is only allowed when querying group-by with one field.
func (cgb *ChallengeGroupBy) Float64s(ctx context.Context) ([]float64, error) {
if len(cgb.fields) > 1 {
return nil, errors.New("ent: ChallengeGroupBy.Float64s is not achievable when grouping more than 1 field")
}
var v []float64
if err := cgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// Float64sX is like Float64s, but panics if an error occurs.
func (cgb *ChallengeGroupBy) Float64sX(ctx context.Context) []float64 {
v, err := cgb.Float64s(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64 returns a single float64 from group-by. It is only allowed when querying group-by with one field.
func (cgb *ChallengeGroupBy) Float64(ctx context.Context) (_ float64, err error) {
var v []float64
if v, err = cgb.Float64s(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{challenge.Label}
default:
err = fmt.Errorf("ent: ChallengeGroupBy.Float64s returned %d results when one was expected", len(v))
}
return
}
// Float64X is like Float64, but panics if an error occurs.
func (cgb *ChallengeGroupBy) Float64X(ctx context.Context) float64 {
v, err := cgb.Float64(ctx)
if err != nil {
panic(err)
}
return v
}
// Bools returns list of bools from group-by. It is only allowed when querying group-by with one field.
func (cgb *ChallengeGroupBy) Bools(ctx context.Context) ([]bool, error) {
if len(cgb.fields) > 1 {
return nil, errors.New("ent: ChallengeGroupBy.Bools is not achievable when grouping more than 1 field")
}
var v []bool
if err := cgb.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// BoolsX is like Bools, but panics if an error occurs.
func (cgb *ChallengeGroupBy) BoolsX(ctx context.Context) []bool {
v, err := cgb.Bools(ctx)
if err != nil {
panic(err)
}
return v
}
// Bool returns a single bool from group-by. It is only allowed when querying group-by with one field.
func (cgb *ChallengeGroupBy) Bool(ctx context.Context) (_ bool, err error) {
var v []bool
if v, err = cgb.Bools(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{challenge.Label}
default:
err = fmt.Errorf("ent: ChallengeGroupBy.Bools returned %d results when one was expected", len(v))
}
return
}
// BoolX is like Bool, but panics if an error occurs.
func (cgb *ChallengeGroupBy) BoolX(ctx context.Context) bool {
v, err := cgb.Bool(ctx)
if err != nil {
panic(err)
}
return v
}
func (cgb *ChallengeGroupBy) sqlScan(ctx context.Context, v interface{}) error {
for _, f := range cgb.fields {
if !challenge.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)}
}
}
selector := cgb.sqlQuery()
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := cgb.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
func (cgb *ChallengeGroupBy) sqlQuery() *sql.Selector {
selector := cgb.sql
columns := make([]string, 0, len(cgb.fields)+len(cgb.fns))
columns = append(columns, cgb.fields...)
for _, fn := range cgb.fns {
columns = append(columns, fn(selector, challenge.ValidColumn))
}
return selector.Select(columns...).GroupBy(cgb.fields...)
}
// ChallengeSelect is the builder for select fields of Challenge entities.
type ChallengeSelect struct {
config
fields []string
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Scan applies the selector query and scan the result into the given value.
func (cs *ChallengeSelect) Scan(ctx context.Context, v interface{}) error {
query, err := cs.path(ctx)
if err != nil {
return err
}
cs.sql = query
return cs.sqlScan(ctx, v)
}
// ScanX is like Scan, but panics if an error occurs.
func (cs *ChallengeSelect) ScanX(ctx context.Context, v interface{}) {
if err := cs.Scan(ctx, v); err != nil {
panic(err)
}
}
// Strings returns list of strings from selector. It is only allowed when selecting one field.
func (cs *ChallengeSelect) Strings(ctx context.Context) ([]string, error) {
if len(cs.fields) > 1 {
return nil, errors.New("ent: ChallengeSelect.Strings is not achievable when selecting more than 1 field")
}
var v []string
if err := cs.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// StringsX is like Strings, but panics if an error occurs.
func (cs *ChallengeSelect) StringsX(ctx context.Context) []string {
v, err := cs.Strings(ctx)
if err != nil {
panic(err)
}
return v
}
// String returns a single string from selector. It is only allowed when selecting one field.
func (cs *ChallengeSelect) String(ctx context.Context) (_ string, err error) {
var v []string
if v, err = cs.Strings(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{challenge.Label}
default:
err = fmt.Errorf("ent: ChallengeSelect.Strings returned %d results when one was expected", len(v))
}
return
}
// StringX is like String, but panics if an error occurs.
func (cs *ChallengeSelect) StringX(ctx context.Context) string {
v, err := cs.String(ctx)
if err != nil {
panic(err)
}
return v
}
// Ints returns list of ints from selector. It is only allowed when selecting one field.
func (cs *ChallengeSelect) Ints(ctx context.Context) ([]int, error) {
if len(cs.fields) > 1 {
return nil, errors.New("ent: ChallengeSelect.Ints is not achievable when selecting more than 1 field")
}
var v []int
if err := cs.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// IntsX is like Ints, but panics if an error occurs.
func (cs *ChallengeSelect) IntsX(ctx context.Context) []int {
v, err := cs.Ints(ctx)
if err != nil {
panic(err)
}
return v
}
// Int returns a single int from selector. It is only allowed when selecting one field.
func (cs *ChallengeSelect) Int(ctx context.Context) (_ int, err error) {
var v []int
if v, err = cs.Ints(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{challenge.Label}
default:
err = fmt.Errorf("ent: ChallengeSelect.Ints returned %d results when one was expected", len(v))
}
return
}
// IntX is like Int, but panics if an error occurs.
func (cs *ChallengeSelect) IntX(ctx context.Context) int {
v, err := cs.Int(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64s returns list of float64s from selector. It is only allowed when selecting one field.
func (cs *ChallengeSelect) Float64s(ctx context.Context) ([]float64, error) {
if len(cs.fields) > 1 {
return nil, errors.New("ent: ChallengeSelect.Float64s is not achievable when selecting more than 1 field")
}
var v []float64
if err := cs.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// Float64sX is like Float64s, but panics if an error occurs.
func (cs *ChallengeSelect) Float64sX(ctx context.Context) []float64 {
v, err := cs.Float64s(ctx)
if err != nil {
panic(err)
}
return v
}
// Float64 returns a single float64 from selector. It is only allowed when selecting one field.
func (cs *ChallengeSelect) Float64(ctx context.Context) (_ float64, err error) {
var v []float64
if v, err = cs.Float64s(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{challenge.Label}
default:
err = fmt.Errorf("ent: ChallengeSelect.Float64s returned %d results when one was expected", len(v))
}
return
}
// Float64X is like Float64, but panics if an error occurs.
func (cs *ChallengeSelect) Float64X(ctx context.Context) float64 {
v, err := cs.Float64(ctx)
if err != nil {
panic(err)
}
return v
}
// Bools returns list of bools from selector. It is only allowed when selecting one field.
func (cs *ChallengeSelect) Bools(ctx context.Context) ([]bool, error) {
if len(cs.fields) > 1 {
return nil, errors.New("ent: ChallengeSelect.Bools is not achievable when selecting more than 1 field")
}
var v []bool
if err := cs.Scan(ctx, &v); err != nil {
return nil, err
}
return v, nil
}
// BoolsX is like Bools, but panics if an error occurs.
func (cs *ChallengeSelect) BoolsX(ctx context.Context) []bool {
v, err := cs.Bools(ctx)
if err != nil {
panic(err)
}
return v
}
// Bool returns a single bool from selector. It is only allowed when selecting one field.
func (cs *ChallengeSelect) Bool(ctx context.Context) (_ bool, err error) {
var v []bool
if v, err = cs.Bools(ctx); err != nil {
return
}
switch len(v) {
case 1:
return v[0], nil
case 0:
err = &NotFoundError{challenge.Label}
default:
err = fmt.Errorf("ent: ChallengeSelect.Bools returned %d results when one was expected", len(v))
}
return
}
// BoolX is like Bool, but panics if an error occurs.
func (cs *ChallengeSelect) BoolX(ctx context.Context) bool {
v, err := cs.Bool(ctx)
if err != nil {
panic(err)
}
return v
}
func (cs *ChallengeSelect) sqlScan(ctx context.Context, v interface{}) error {
for _, f := range cs.fields {
if !challenge.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for selection", f)}
}
}
rows := &sql.Rows{}
query, args := cs.sqlQuery().Query()
if err := cs.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
func (cs *ChallengeSelect) sqlQuery() sql.Querier {
selector := cs.sql
selector.Select(selector.Columns(cs.fields...)...)
return selector
}

View file

@ -1,238 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"github.com/facebook/ent/dialect/sql"
"github.com/facebook/ent/dialect/sql/sqlgraph"
"github.com/facebook/ent/schema/field"
"github.com/roleypoly/roleypoly/src/db/ent/challenge"
"github.com/roleypoly/roleypoly/src/db/ent/predicate"
)
// ChallengeUpdate is the builder for updating Challenge entities.
type ChallengeUpdate struct {
config
hooks []Hook
mutation *ChallengeMutation
predicates []predicate.Challenge
}
// Where adds a new predicate for the builder.
func (cu *ChallengeUpdate) Where(ps ...predicate.Challenge) *ChallengeUpdate {
cu.predicates = append(cu.predicates, ps...)
return cu
}
// Mutation returns the ChallengeMutation object of the builder.
func (cu *ChallengeUpdate) Mutation() *ChallengeMutation {
return cu.mutation
}
// Save executes the query and returns the number of rows/vertices matched by this operation.
func (cu *ChallengeUpdate) Save(ctx context.Context) (int, error) {
var (
err error
affected int
)
cu.defaults()
if len(cu.hooks) == 0 {
affected, err = cu.sqlSave(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ChallengeMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
cu.mutation = mutation
affected, err = cu.sqlSave(ctx)
mutation.done = true
return affected, err
})
for i := len(cu.hooks) - 1; i >= 0; i-- {
mut = cu.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, cu.mutation); err != nil {
return 0, err
}
}
return affected, err
}
// SaveX is like Save, but panics if an error occurs.
func (cu *ChallengeUpdate) SaveX(ctx context.Context) int {
affected, err := cu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (cu *ChallengeUpdate) Exec(ctx context.Context) error {
_, err := cu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (cu *ChallengeUpdate) ExecX(ctx context.Context) {
if err := cu.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (cu *ChallengeUpdate) defaults() {
if _, ok := cu.mutation.UpdateTime(); !ok {
v := challenge.UpdateDefaultUpdateTime()
cu.mutation.SetUpdateTime(v)
}
}
func (cu *ChallengeUpdate) sqlSave(ctx context.Context) (n int, err error) {
_spec := &sqlgraph.UpdateSpec{
Node: &sqlgraph.NodeSpec{
Table: challenge.Table,
Columns: challenge.Columns,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: challenge.FieldID,
},
},
}
if ps := cu.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := cu.mutation.UpdateTime(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: challenge.FieldUpdateTime,
})
}
if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{challenge.Label}
} else if cerr, ok := isSQLConstraintError(err); ok {
err = cerr
}
return 0, err
}
return n, nil
}
// ChallengeUpdateOne is the builder for updating a single Challenge entity.
type ChallengeUpdateOne struct {
config
hooks []Hook
mutation *ChallengeMutation
}
// Mutation returns the ChallengeMutation object of the builder.
func (cuo *ChallengeUpdateOne) Mutation() *ChallengeMutation {
return cuo.mutation
}
// Save executes the query and returns the updated entity.
func (cuo *ChallengeUpdateOne) Save(ctx context.Context) (*Challenge, error) {
var (
err error
node *Challenge
)
cuo.defaults()
if len(cuo.hooks) == 0 {
node, err = cuo.sqlSave(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*ChallengeMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
cuo.mutation = mutation
node, err = cuo.sqlSave(ctx)
mutation.done = true
return node, err
})
for i := len(cuo.hooks) - 1; i >= 0; i-- {
mut = cuo.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, cuo.mutation); err != nil {
return nil, err
}
}
return node, err
}
// SaveX is like Save, but panics if an error occurs.
func (cuo *ChallengeUpdateOne) SaveX(ctx context.Context) *Challenge {
node, err := cuo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (cuo *ChallengeUpdateOne) Exec(ctx context.Context) error {
_, err := cuo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (cuo *ChallengeUpdateOne) ExecX(ctx context.Context) {
if err := cuo.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (cuo *ChallengeUpdateOne) defaults() {
if _, ok := cuo.mutation.UpdateTime(); !ok {
v := challenge.UpdateDefaultUpdateTime()
cuo.mutation.SetUpdateTime(v)
}
}
func (cuo *ChallengeUpdateOne) sqlSave(ctx context.Context) (_node *Challenge, err error) {
_spec := &sqlgraph.UpdateSpec{
Node: &sqlgraph.NodeSpec{
Table: challenge.Table,
Columns: challenge.Columns,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: challenge.FieldID,
},
},
}
id, ok := cuo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Challenge.ID for update")}
}
_spec.Node.ID.Value = id
if value, ok := cuo.mutation.UpdateTime(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: challenge.FieldUpdateTime,
})
}
_node = &Challenge{config: cuo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues()
if err = sqlgraph.UpdateNode(ctx, cuo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{challenge.Label}
} else if cerr, ok := isSQLConstraintError(err); ok {
err = cerr
}
return nil, err
}
return _node, nil
}

View file

@ -1,395 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"log"
"github.com/roleypoly/roleypoly/src/db/ent/migrate"
"github.com/roleypoly/roleypoly/src/db/ent/challenge"
"github.com/roleypoly/roleypoly/src/db/ent/guild"
"github.com/roleypoly/roleypoly/src/db/ent/session"
"github.com/facebook/ent/dialect"
"github.com/facebook/ent/dialect/sql"
)
// Client is the client that holds all ent builders.
type Client struct {
config
// Schema is the client for creating, migrating and dropping schema.
Schema *migrate.Schema
// Challenge is the client for interacting with the Challenge builders.
Challenge *ChallengeClient
// Guild is the client for interacting with the Guild builders.
Guild *GuildClient
// Session is the client for interacting with the Session builders.
Session *SessionClient
}
// NewClient creates a new client configured with the given options.
func NewClient(opts ...Option) *Client {
cfg := config{log: log.Println, hooks: &hooks{}}
cfg.options(opts...)
client := &Client{config: cfg}
client.init()
return client
}
func (c *Client) init() {
c.Schema = migrate.NewSchema(c.driver)
c.Challenge = NewChallengeClient(c.config)
c.Guild = NewGuildClient(c.config)
c.Session = NewSessionClient(c.config)
}
// Open opens a database/sql.DB specified by the driver name and
// the data source name, and returns a new client attached to it.
// Optional parameters can be added for configuring the client.
func Open(driverName, dataSourceName string, options ...Option) (*Client, error) {
switch driverName {
case dialect.MySQL, dialect.Postgres, dialect.SQLite:
drv, err := sql.Open(driverName, dataSourceName)
if err != nil {
return nil, err
}
return NewClient(append(options, Driver(drv))...), nil
default:
return nil, fmt.Errorf("unsupported driver: %q", driverName)
}
}
// Tx returns a new transactional client. The provided context
// is used until the transaction is committed or rolled back.
func (c *Client) Tx(ctx context.Context) (*Tx, error) {
if _, ok := c.driver.(*txDriver); ok {
return nil, fmt.Errorf("ent: cannot start a transaction within a transaction")
}
tx, err := newTx(ctx, c.driver)
if err != nil {
return nil, fmt.Errorf("ent: starting a transaction: %v", err)
}
cfg := config{driver: tx, log: c.log, debug: c.debug, hooks: c.hooks}
return &Tx{
ctx: ctx,
config: cfg,
Challenge: NewChallengeClient(cfg),
Guild: NewGuildClient(cfg),
Session: NewSessionClient(cfg),
}, nil
}
// BeginTx returns a transactional client with options.
func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
if _, ok := c.driver.(*txDriver); ok {
return nil, fmt.Errorf("ent: cannot start a transaction within a transaction")
}
tx, err := c.driver.(*sql.Driver).BeginTx(ctx, opts)
if err != nil {
return nil, fmt.Errorf("ent: starting a transaction: %v", err)
}
cfg := config{driver: &txDriver{tx: tx, drv: c.driver}, log: c.log, debug: c.debug, hooks: c.hooks}
return &Tx{
config: cfg,
Challenge: NewChallengeClient(cfg),
Guild: NewGuildClient(cfg),
Session: NewSessionClient(cfg),
}, nil
}
// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
//
// client.Debug().
// Challenge.
// Query().
// Count(ctx)
//
func (c *Client) Debug() *Client {
if c.debug {
return c
}
cfg := config{driver: dialect.Debug(c.driver, c.log), log: c.log, debug: true, hooks: c.hooks}
client := &Client{config: cfg}
client.init()
return client
}
// Close closes the database connection and prevents new queries from starting.
func (c *Client) Close() error {
return c.driver.Close()
}
// Use adds the mutation hooks to all the entity clients.
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
func (c *Client) Use(hooks ...Hook) {
c.Challenge.Use(hooks...)
c.Guild.Use(hooks...)
c.Session.Use(hooks...)
}
// ChallengeClient is a client for the Challenge schema.
type ChallengeClient struct {
config
}
// NewChallengeClient returns a client for the Challenge from the given config.
func NewChallengeClient(c config) *ChallengeClient {
return &ChallengeClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `challenge.Hooks(f(g(h())))`.
func (c *ChallengeClient) Use(hooks ...Hook) {
c.hooks.Challenge = append(c.hooks.Challenge, hooks...)
}
// Create returns a create builder for Challenge.
func (c *ChallengeClient) Create() *ChallengeCreate {
mutation := newChallengeMutation(c.config, OpCreate)
return &ChallengeCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// BulkCreate returns a builder for creating a bulk of Challenge entities.
func (c *ChallengeClient) CreateBulk(builders ...*ChallengeCreate) *ChallengeCreateBulk {
return &ChallengeCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for Challenge.
func (c *ChallengeClient) Update() *ChallengeUpdate {
mutation := newChallengeMutation(c.config, OpUpdate)
return &ChallengeUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *ChallengeClient) UpdateOne(ch *Challenge) *ChallengeUpdateOne {
mutation := newChallengeMutation(c.config, OpUpdateOne, withChallenge(ch))
return &ChallengeUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *ChallengeClient) UpdateOneID(id int) *ChallengeUpdateOne {
mutation := newChallengeMutation(c.config, OpUpdateOne, withChallengeID(id))
return &ChallengeUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for Challenge.
func (c *ChallengeClient) Delete() *ChallengeDelete {
mutation := newChallengeMutation(c.config, OpDelete)
return &ChallengeDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a delete builder for the given entity.
func (c *ChallengeClient) DeleteOne(ch *Challenge) *ChallengeDeleteOne {
return c.DeleteOneID(ch.ID)
}
// DeleteOneID returns a delete builder for the given id.
func (c *ChallengeClient) DeleteOneID(id int) *ChallengeDeleteOne {
builder := c.Delete().Where(challenge.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &ChallengeDeleteOne{builder}
}
// Query returns a query builder for Challenge.
func (c *ChallengeClient) Query() *ChallengeQuery {
return &ChallengeQuery{config: c.config}
}
// Get returns a Challenge entity by its id.
func (c *ChallengeClient) Get(ctx context.Context, id int) (*Challenge, error) {
return c.Query().Where(challenge.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *ChallengeClient) GetX(ctx context.Context, id int) *Challenge {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// Hooks returns the client hooks.
func (c *ChallengeClient) Hooks() []Hook {
return c.hooks.Challenge
}
// GuildClient is a client for the Guild schema.
type GuildClient struct {
config
}
// NewGuildClient returns a client for the Guild from the given config.
func NewGuildClient(c config) *GuildClient {
return &GuildClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `guild.Hooks(f(g(h())))`.
func (c *GuildClient) Use(hooks ...Hook) {
c.hooks.Guild = append(c.hooks.Guild, hooks...)
}
// Create returns a create builder for Guild.
func (c *GuildClient) Create() *GuildCreate {
mutation := newGuildMutation(c.config, OpCreate)
return &GuildCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// BulkCreate returns a builder for creating a bulk of Guild entities.
func (c *GuildClient) CreateBulk(builders ...*GuildCreate) *GuildCreateBulk {
return &GuildCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for Guild.
func (c *GuildClient) Update() *GuildUpdate {
mutation := newGuildMutation(c.config, OpUpdate)
return &GuildUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *GuildClient) UpdateOne(gu *Guild) *GuildUpdateOne {
mutation := newGuildMutation(c.config, OpUpdateOne, withGuild(gu))
return &GuildUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *GuildClient) UpdateOneID(id int) *GuildUpdateOne {
mutation := newGuildMutation(c.config, OpUpdateOne, withGuildID(id))
return &GuildUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for Guild.
func (c *GuildClient) Delete() *GuildDelete {
mutation := newGuildMutation(c.config, OpDelete)
return &GuildDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a delete builder for the given entity.
func (c *GuildClient) DeleteOne(gu *Guild) *GuildDeleteOne {
return c.DeleteOneID(gu.ID)
}
// DeleteOneID returns a delete builder for the given id.
func (c *GuildClient) DeleteOneID(id int) *GuildDeleteOne {
builder := c.Delete().Where(guild.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &GuildDeleteOne{builder}
}
// Query returns a query builder for Guild.
func (c *GuildClient) Query() *GuildQuery {
return &GuildQuery{config: c.config}
}
// Get returns a Guild entity by its id.
func (c *GuildClient) Get(ctx context.Context, id int) (*Guild, error) {
return c.Query().Where(guild.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *GuildClient) GetX(ctx context.Context, id int) *Guild {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// Hooks returns the client hooks.
func (c *GuildClient) Hooks() []Hook {
return c.hooks.Guild
}
// SessionClient is a client for the Session schema.
type SessionClient struct {
config
}
// NewSessionClient returns a client for the Session from the given config.
func NewSessionClient(c config) *SessionClient {
return &SessionClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `session.Hooks(f(g(h())))`.
func (c *SessionClient) Use(hooks ...Hook) {
c.hooks.Session = append(c.hooks.Session, hooks...)
}
// Create returns a create builder for Session.
func (c *SessionClient) Create() *SessionCreate {
mutation := newSessionMutation(c.config, OpCreate)
return &SessionCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// BulkCreate returns a builder for creating a bulk of Session entities.
func (c *SessionClient) CreateBulk(builders ...*SessionCreate) *SessionCreateBulk {
return &SessionCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for Session.
func (c *SessionClient) Update() *SessionUpdate {
mutation := newSessionMutation(c.config, OpUpdate)
return &SessionUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *SessionClient) UpdateOne(s *Session) *SessionUpdateOne {
mutation := newSessionMutation(c.config, OpUpdateOne, withSession(s))
return &SessionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *SessionClient) UpdateOneID(id int) *SessionUpdateOne {
mutation := newSessionMutation(c.config, OpUpdateOne, withSessionID(id))
return &SessionUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for Session.
func (c *SessionClient) Delete() *SessionDelete {
mutation := newSessionMutation(c.config, OpDelete)
return &SessionDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a delete builder for the given entity.
func (c *SessionClient) DeleteOne(s *Session) *SessionDeleteOne {
return c.DeleteOneID(s.ID)
}
// DeleteOneID returns a delete builder for the given id.
func (c *SessionClient) DeleteOneID(id int) *SessionDeleteOne {
builder := c.Delete().Where(session.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &SessionDeleteOne{builder}
}
// Query returns a query builder for Session.
func (c *SessionClient) Query() *SessionQuery {
return &SessionQuery{config: c.config}
}
// Get returns a Session entity by its id.
func (c *SessionClient) Get(ctx context.Context, id int) (*Session, error) {
return c.Query().Where(session.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *SessionClient) GetX(ctx context.Context, id int) *Session {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// Hooks returns the client hooks.
func (c *SessionClient) Hooks() []Hook {
return c.hooks.Session
}

View file

@ -1,61 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"github.com/facebook/ent"
"github.com/facebook/ent/dialect"
)
// Option function to configure the client.
type Option func(*config)
// Config is the configuration for the client and its builder.
type config struct {
// driver used for executing database requests.
driver dialect.Driver
// debug enable a debug logging.
debug bool
// log used for logging on debug mode.
log func(...interface{})
// hooks to execute on mutations.
hooks *hooks
}
// hooks per client, for fast access.
type hooks struct {
Challenge []ent.Hook
Guild []ent.Hook
Session []ent.Hook
}
// Options applies the options on the config object.
func (c *config) options(opts ...Option) {
for _, opt := range opts {
opt(c)
}
if c.debug {
c.driver = dialect.Debug(c.driver, c.log)
}
}
// Debug enables debug logging on the ent.Driver.
func Debug() Option {
return func(c *config) {
c.debug = true
}
}
// Log sets the logging function for debug mode.
func Log(fn func(...interface{})) Option {
return func(c *config) {
c.log = fn
}
}
// Driver configures the client driver.
func Driver(driver dialect.Driver) Option {
return func(c *config) {
c.driver = driver
}
}

View file

@ -1,33 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
)
type clientCtxKey struct{}
// FromContext returns the Client stored in a context, or nil if there isn't one.
func FromContext(ctx context.Context) *Client {
c, _ := ctx.Value(clientCtxKey{}).(*Client)
return c
}
// NewContext returns a new context with the given Client attached.
func NewContext(parent context.Context, c *Client) context.Context {
return context.WithValue(parent, clientCtxKey{}, c)
}
type txCtxKey struct{}
// TxFromContext returns the Tx stored in a context, or nil if there isn't one.
func TxFromContext(ctx context.Context) *Tx {
tx, _ := ctx.Value(txCtxKey{}).(*Tx)
return tx
}
// NewTxContext returns a new context with the given Client attached.
func NewTxContext(parent context.Context, tx *Tx) context.Context {
return context.WithValue(parent, txCtxKey{}, tx)
}

View file

@ -1,270 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"errors"
"fmt"
"strings"
"github.com/facebook/ent"
"github.com/facebook/ent/dialect"
"github.com/facebook/ent/dialect/sql"
"github.com/facebook/ent/dialect/sql/sqlgraph"
)
// ent aliases to avoid import conflict in user's code.
type (
Op = ent.Op
Hook = ent.Hook
Value = ent.Value
Query = ent.Query
Policy = ent.Policy
Mutator = ent.Mutator
Mutation = ent.Mutation
MutateFunc = ent.MutateFunc
)
// OrderFunc applies an ordering on the sql selector.
type OrderFunc func(*sql.Selector, func(string) bool)
// Asc applies the given fields in ASC order.
func Asc(fields ...string) OrderFunc {
return func(s *sql.Selector, check func(string) bool) {
for _, f := range fields {
if check(f) {
s.OrderBy(sql.Asc(f))
} else {
s.AddError(&ValidationError{Name: f, err: fmt.Errorf("invalid field %q for ordering", f)})
}
}
}
}
// Desc applies the given fields in DESC order.
func Desc(fields ...string) OrderFunc {
return func(s *sql.Selector, check func(string) bool) {
for _, f := range fields {
if check(f) {
s.OrderBy(sql.Desc(f))
} else {
s.AddError(&ValidationError{Name: f, err: fmt.Errorf("invalid field %q for ordering", f)})
}
}
}
}
// AggregateFunc applies an aggregation step on the group-by traversal/selector.
type AggregateFunc func(*sql.Selector, func(string) bool) string
// As is a pseudo aggregation function for renaming another other functions with custom names. For example:
//
// GroupBy(field1, field2).
// Aggregate(ent.As(ent.Sum(field1), "sum_field1"), (ent.As(ent.Sum(field2), "sum_field2")).
// Scan(ctx, &v)
//
func As(fn AggregateFunc, end string) AggregateFunc {
return func(s *sql.Selector, check func(string) bool) string {
return sql.As(fn(s, check), end)
}
}
// Count applies the "count" aggregation function on each group.
func Count() AggregateFunc {
return func(s *sql.Selector, _ func(string) bool) string {
return sql.Count("*")
}
}
// Max applies the "max" aggregation function on the given field of each group.
func Max(field string) AggregateFunc {
return func(s *sql.Selector, check func(string) bool) string {
if !check(field) {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("invalid field %q for grouping", field)})
return ""
}
return sql.Max(s.C(field))
}
}
// Mean applies the "mean" aggregation function on the given field of each group.
func Mean(field string) AggregateFunc {
return func(s *sql.Selector, check func(string) bool) string {
if !check(field) {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("invalid field %q for grouping", field)})
return ""
}
return sql.Avg(s.C(field))
}
}
// Min applies the "min" aggregation function on the given field of each group.
func Min(field string) AggregateFunc {
return func(s *sql.Selector, check func(string) bool) string {
if !check(field) {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("invalid field %q for grouping", field)})
return ""
}
return sql.Min(s.C(field))
}
}
// Sum applies the "sum" aggregation function on the given field of each group.
func Sum(field string) AggregateFunc {
return func(s *sql.Selector, check func(string) bool) string {
if !check(field) {
s.AddError(&ValidationError{Name: field, err: fmt.Errorf("invalid field %q for grouping", field)})
return ""
}
return sql.Sum(s.C(field))
}
}
// ValidationError returns when validating a field fails.
type ValidationError struct {
Name string // Field or edge name.
err error
}
// Error implements the error interface.
func (e *ValidationError) Error() string {
return e.err.Error()
}
// Unwrap implements the errors.Wrapper interface.
func (e *ValidationError) Unwrap() error {
return e.err
}
// IsValidationError returns a boolean indicating whether the error is a validaton error.
func IsValidationError(err error) bool {
if err == nil {
return false
}
var e *ValidationError
return errors.As(err, &e)
}
// NotFoundError returns when trying to fetch a specific entity and it was not found in the database.
type NotFoundError struct {
label string
}
// Error implements the error interface.
func (e *NotFoundError) Error() string {
return "ent: " + e.label + " not found"
}
// IsNotFound returns a boolean indicating whether the error is a not found error.
func IsNotFound(err error) bool {
if err == nil {
return false
}
var e *NotFoundError
return errors.As(err, &e)
}
// MaskNotFound masks nor found error.
func MaskNotFound(err error) error {
if IsNotFound(err) {
return nil
}
return err
}
// NotSingularError returns when trying to fetch a singular entity and more then one was found in the database.
type NotSingularError struct {
label string
}
// Error implements the error interface.
func (e *NotSingularError) Error() string {
return "ent: " + e.label + " not singular"
}
// IsNotSingular returns a boolean indicating whether the error is a not singular error.
func IsNotSingular(err error) bool {
if err == nil {
return false
}
var e *NotSingularError
return errors.As(err, &e)
}
// NotLoadedError returns when trying to get a node that was not loaded by the query.
type NotLoadedError struct {
edge string
}
// Error implements the error interface.
func (e *NotLoadedError) Error() string {
return "ent: " + e.edge + " edge was not loaded"
}
// IsNotLoaded returns a boolean indicating whether the error is a not loaded error.
func IsNotLoaded(err error) bool {
if err == nil {
return false
}
var e *NotLoadedError
return errors.As(err, &e)
}
// ConstraintError returns when trying to create/update one or more entities and
// one or more of their constraints failed. For example, violation of edge or
// field uniqueness.
type ConstraintError struct {
msg string
wrap error
}
// Error implements the error interface.
func (e ConstraintError) Error() string {
return "ent: constraint failed: " + e.msg
}
// Unwrap implements the errors.Wrapper interface.
func (e *ConstraintError) Unwrap() error {
return e.wrap
}
// IsConstraintError returns a boolean indicating whether the error is a constraint failure.
func IsConstraintError(err error) bool {
if err == nil {
return false
}
var e *ConstraintError
return errors.As(err, &e)
}
func isSQLConstraintError(err error) (*ConstraintError, bool) {
var (
msg = err.Error()
// error format per dialect.
errors = [...]string{
"Error 1062", // MySQL 1062 error (ER_DUP_ENTRY).
"UNIQUE constraint failed", // SQLite.
"duplicate key value violates unique constraint", // PostgreSQL.
}
)
if _, ok := err.(*sqlgraph.ConstraintError); ok {
return &ConstraintError{msg, err}, true
}
for i := range errors {
if strings.Contains(msg, errors[i]) {
return &ConstraintError{msg, err}, true
}
}
return nil, false
}
// rollback calls to tx.Rollback and wraps the given error with the rollback error if occurred.
func rollback(tx dialect.Tx, err error) error {
if rerr := tx.Rollback(); rerr != nil {
err = fmt.Errorf("%s: %v", err.Error(), rerr)
}
if err, ok := isSQLConstraintError(err); ok {
return err
}
return err
}

View file

@ -1,13 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "enttest",
srcs = ["enttest.go"],
importpath = "github.com/roleypoly/roleypoly/src/db/ent/enttest",
visibility = ["//visibility:public"],
deps = [
"//src/db/ent",
"//src/db/ent/runtime",
"@com_github_facebook_ent//dialect/sql/schema",
],
)

View file

@ -1,78 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package enttest
import (
"context"
"github.com/roleypoly/roleypoly/src/db/ent"
// required by schema hooks.
_ "github.com/roleypoly/roleypoly/src/db/ent/runtime"
"github.com/facebook/ent/dialect/sql/schema"
)
type (
// TestingT is the interface that is shared between
// testing.T and testing.B and used by enttest.
TestingT interface {
FailNow()
Error(...interface{})
}
// Option configures client creation.
Option func(*options)
options struct {
opts []ent.Option
migrateOpts []schema.MigrateOption
}
)
// WithOptions forwards options to client creation.
func WithOptions(opts ...ent.Option) Option {
return func(o *options) {
o.opts = append(o.opts, opts...)
}
}
// WithMigrateOptions forwards options to auto migration.
func WithMigrateOptions(opts ...schema.MigrateOption) Option {
return func(o *options) {
o.migrateOpts = append(o.migrateOpts, opts...)
}
}
func newOptions(opts []Option) *options {
o := &options{}
for _, opt := range opts {
opt(o)
}
return o
}
// Open calls ent.Open and auto-run migration.
func Open(t TestingT, driverName, dataSourceName string, opts ...Option) *ent.Client {
o := newOptions(opts)
c, err := ent.Open(driverName, dataSourceName, o.opts...)
if err != nil {
t.Error(err)
t.FailNow()
}
if err := c.Schema.Create(context.Background(), o.migrateOpts...); err != nil {
t.Error(err)
t.FailNow()
}
return c
}
// NewClient calls ent.NewClient and auto-run migration.
func NewClient(t TestingT, opts ...Option) *ent.Client {
o := newOptions(opts)
c := ent.NewClient(o.opts...)
if err := c.Schema.Create(context.Background(), o.migrateOpts...); err != nil {
t.Error(err)
t.FailNow()
}
return c
}

View file

@ -1,3 +0,0 @@
package ent
//go:generate go run github.com/facebook/ent/cmd/entc generate ./schema

View file

@ -1,145 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"encoding/json"
"fmt"
"strings"
"time"
"github.com/facebook/ent/dialect/sql"
"github.com/roleypoly/roleypoly/src/db/ent/guild"
"github.com/roleypoly/roleypoly/src/db/ent/schema"
)
// Guild is the model entity for the Guild schema.
type Guild struct {
config `json:"-"`
// ID of the ent.
ID int `json:"id,omitempty"`
// CreateTime holds the value of the "create_time" field.
CreateTime time.Time `json:"create_time,omitempty"`
// UpdateTime holds the value of the "update_time" field.
UpdateTime time.Time `json:"update_time,omitempty"`
// Snowflake holds the value of the "snowflake" field.
Snowflake string `json:"snowflake,omitempty"`
// Message holds the value of the "message" field.
Message string `json:"message,omitempty"`
// Categories holds the value of the "categories" field.
Categories []schema.Category `json:"categories,omitempty"`
// Entitlements holds the value of the "entitlements" field.
Entitlements []string `json:"entitlements,omitempty"`
}
// scanValues returns the types for scanning values from sql.Rows.
func (*Guild) scanValues() []interface{} {
return []interface{}{
&sql.NullInt64{}, // id
&sql.NullTime{}, // create_time
&sql.NullTime{}, // update_time
&sql.NullString{}, // snowflake
&sql.NullString{}, // message
&[]byte{}, // categories
&[]byte{}, // entitlements
}
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the Guild fields.
func (gu *Guild) assignValues(values ...interface{}) error {
if m, n := len(values), len(guild.Columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
value, ok := values[0].(*sql.NullInt64)
if !ok {
return fmt.Errorf("unexpected type %T for field id", value)
}
gu.ID = int(value.Int64)
values = values[1:]
if value, ok := values[0].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field create_time", values[0])
} else if value.Valid {
gu.CreateTime = value.Time
}
if value, ok := values[1].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field update_time", values[1])
} else if value.Valid {
gu.UpdateTime = value.Time
}
if value, ok := values[2].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field snowflake", values[2])
} else if value.Valid {
gu.Snowflake = value.String
}
if value, ok := values[3].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field message", values[3])
} else if value.Valid {
gu.Message = value.String
}
if value, ok := values[4].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field categories", values[4])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &gu.Categories); err != nil {
return fmt.Errorf("unmarshal field categories: %v", err)
}
}
if value, ok := values[5].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field entitlements", values[5])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &gu.Entitlements); err != nil {
return fmt.Errorf("unmarshal field entitlements: %v", err)
}
}
return nil
}
// Update returns a builder for updating this Guild.
// Note that, you need to call Guild.Unwrap() before calling this method, if this Guild
// was returned from a transaction, and the transaction was committed or rolled back.
func (gu *Guild) Update() *GuildUpdateOne {
return (&GuildClient{config: gu.config}).UpdateOne(gu)
}
// Unwrap unwraps the entity that was returned from a transaction after it was closed,
// so that all next queries will be executed through the driver which created the transaction.
func (gu *Guild) Unwrap() *Guild {
tx, ok := gu.config.driver.(*txDriver)
if !ok {
panic("ent: Guild is not a transactional entity")
}
gu.config.driver = tx.drv
return gu
}
// String implements the fmt.Stringer.
func (gu *Guild) String() string {
var builder strings.Builder
builder.WriteString("Guild(")
builder.WriteString(fmt.Sprintf("id=%v", gu.ID))
builder.WriteString(", create_time=")
builder.WriteString(gu.CreateTime.Format(time.ANSIC))
builder.WriteString(", update_time=")
builder.WriteString(gu.UpdateTime.Format(time.ANSIC))
builder.WriteString(", snowflake=")
builder.WriteString(gu.Snowflake)
builder.WriteString(", message=")
builder.WriteString(gu.Message)
builder.WriteString(", categories=")
builder.WriteString(fmt.Sprintf("%v", gu.Categories))
builder.WriteString(", entitlements=")
builder.WriteString(fmt.Sprintf("%v", gu.Entitlements))
builder.WriteByte(')')
return builder.String()
}
// Guilds is a parsable slice of Guild.
type Guilds []*Guild
func (gu Guilds) config(cfg config) {
for _i := range gu {
gu[_i].config = cfg
}
}

View file

@ -1,15 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "guild",
srcs = [
"guild.go",
"where.go",
],
importpath = "github.com/roleypoly/roleypoly/src/db/ent/guild",
visibility = ["//visibility:public"],
deps = [
"//src/db/ent/predicate",
"@com_github_facebook_ent//dialect/sql",
],
)

View file

@ -1,59 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package guild
import (
"time"
)
const (
// Label holds the string label denoting the guild type in the database.
Label = "guild"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldCreateTime holds the string denoting the create_time field in the database.
FieldCreateTime = "create_time"
// FieldUpdateTime holds the string denoting the update_time field in the database.
FieldUpdateTime = "update_time"
// FieldSnowflake holds the string denoting the snowflake field in the database.
FieldSnowflake = "snowflake"
// FieldMessage holds the string denoting the message field in the database.
FieldMessage = "message"
// FieldCategories holds the string denoting the categories field in the database.
FieldCategories = "categories"
// FieldEntitlements holds the string denoting the entitlements field in the database.
FieldEntitlements = "entitlements"
// Table holds the table name of the guild in the database.
Table = "guilds"
)
// Columns holds all SQL columns for guild fields.
var Columns = []string{
FieldID,
FieldCreateTime,
FieldUpdateTime,
FieldSnowflake,
FieldMessage,
FieldCategories,
FieldEntitlements,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// DefaultCreateTime holds the default value on creation for the create_time field.
DefaultCreateTime func() time.Time
// DefaultUpdateTime holds the default value on creation for the update_time field.
DefaultUpdateTime func() time.Time
// UpdateDefaultUpdateTime holds the default value on update for the update_time field.
UpdateDefaultUpdateTime func() time.Time
)

View file

@ -1,527 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package guild
import (
"time"
"github.com/facebook/ent/dialect/sql"
"github.com/roleypoly/roleypoly/src/db/ent/predicate"
)
// ID filters vertices based on their identifier.
func ID(id int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldID), id))
})
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldID), id))
})
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldID), id))
})
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(ids) == 0 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
s.Where(sql.In(s.C(FieldID), v...))
})
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(ids) == 0 {
s.Where(sql.False())
return
}
v := make([]interface{}, len(ids))
for i := range v {
v[i] = ids[i]
}
s.Where(sql.NotIn(s.C(FieldID), v...))
})
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldID), id))
})
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldID), id))
})
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldID), id))
})
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id int) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldID), id))
})
}
// CreateTime applies equality check predicate on the "create_time" field. It's identical to CreateTimeEQ.
func CreateTime(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldCreateTime), v))
})
}
// UpdateTime applies equality check predicate on the "update_time" field. It's identical to UpdateTimeEQ.
func UpdateTime(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUpdateTime), v))
})
}
// Snowflake applies equality check predicate on the "snowflake" field. It's identical to SnowflakeEQ.
func Snowflake(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldSnowflake), v))
})
}
// Message applies equality check predicate on the "message" field. It's identical to MessageEQ.
func Message(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldMessage), v))
})
}
// CreateTimeEQ applies the EQ predicate on the "create_time" field.
func CreateTimeEQ(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldCreateTime), v))
})
}
// CreateTimeNEQ applies the NEQ predicate on the "create_time" field.
func CreateTimeNEQ(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldCreateTime), v))
})
}
// CreateTimeIn applies the In predicate on the "create_time" field.
func CreateTimeIn(vs ...time.Time) predicate.Guild {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldCreateTime), v...))
})
}
// CreateTimeNotIn applies the NotIn predicate on the "create_time" field.
func CreateTimeNotIn(vs ...time.Time) predicate.Guild {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldCreateTime), v...))
})
}
// CreateTimeGT applies the GT predicate on the "create_time" field.
func CreateTimeGT(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldCreateTime), v))
})
}
// CreateTimeGTE applies the GTE predicate on the "create_time" field.
func CreateTimeGTE(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldCreateTime), v))
})
}
// CreateTimeLT applies the LT predicate on the "create_time" field.
func CreateTimeLT(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldCreateTime), v))
})
}
// CreateTimeLTE applies the LTE predicate on the "create_time" field.
func CreateTimeLTE(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldCreateTime), v))
})
}
// UpdateTimeEQ applies the EQ predicate on the "update_time" field.
func UpdateTimeEQ(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeNEQ applies the NEQ predicate on the "update_time" field.
func UpdateTimeNEQ(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeIn applies the In predicate on the "update_time" field.
func UpdateTimeIn(vs ...time.Time) predicate.Guild {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldUpdateTime), v...))
})
}
// UpdateTimeNotIn applies the NotIn predicate on the "update_time" field.
func UpdateTimeNotIn(vs ...time.Time) predicate.Guild {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldUpdateTime), v...))
})
}
// UpdateTimeGT applies the GT predicate on the "update_time" field.
func UpdateTimeGT(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeGTE applies the GTE predicate on the "update_time" field.
func UpdateTimeGTE(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeLT applies the LT predicate on the "update_time" field.
func UpdateTimeLT(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldUpdateTime), v))
})
}
// UpdateTimeLTE applies the LTE predicate on the "update_time" field.
func UpdateTimeLTE(v time.Time) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldUpdateTime), v))
})
}
// SnowflakeEQ applies the EQ predicate on the "snowflake" field.
func SnowflakeEQ(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldSnowflake), v))
})
}
// SnowflakeNEQ applies the NEQ predicate on the "snowflake" field.
func SnowflakeNEQ(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldSnowflake), v))
})
}
// SnowflakeIn applies the In predicate on the "snowflake" field.
func SnowflakeIn(vs ...string) predicate.Guild {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldSnowflake), v...))
})
}
// SnowflakeNotIn applies the NotIn predicate on the "snowflake" field.
func SnowflakeNotIn(vs ...string) predicate.Guild {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldSnowflake), v...))
})
}
// SnowflakeGT applies the GT predicate on the "snowflake" field.
func SnowflakeGT(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldSnowflake), v))
})
}
// SnowflakeGTE applies the GTE predicate on the "snowflake" field.
func SnowflakeGTE(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldSnowflake), v))
})
}
// SnowflakeLT applies the LT predicate on the "snowflake" field.
func SnowflakeLT(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldSnowflake), v))
})
}
// SnowflakeLTE applies the LTE predicate on the "snowflake" field.
func SnowflakeLTE(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldSnowflake), v))
})
}
// SnowflakeContains applies the Contains predicate on the "snowflake" field.
func SnowflakeContains(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldSnowflake), v))
})
}
// SnowflakeHasPrefix applies the HasPrefix predicate on the "snowflake" field.
func SnowflakeHasPrefix(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldSnowflake), v))
})
}
// SnowflakeHasSuffix applies the HasSuffix predicate on the "snowflake" field.
func SnowflakeHasSuffix(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldSnowflake), v))
})
}
// SnowflakeEqualFold applies the EqualFold predicate on the "snowflake" field.
func SnowflakeEqualFold(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldSnowflake), v))
})
}
// SnowflakeContainsFold applies the ContainsFold predicate on the "snowflake" field.
func SnowflakeContainsFold(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldSnowflake), v))
})
}
// MessageEQ applies the EQ predicate on the "message" field.
func MessageEQ(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldMessage), v))
})
}
// MessageNEQ applies the NEQ predicate on the "message" field.
func MessageNEQ(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldMessage), v))
})
}
// MessageIn applies the In predicate on the "message" field.
func MessageIn(vs ...string) predicate.Guild {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.In(s.C(FieldMessage), v...))
})
}
// MessageNotIn applies the NotIn predicate on the "message" field.
func MessageNotIn(vs ...string) predicate.Guild {
v := make([]interface{}, len(vs))
for i := range v {
v[i] = vs[i]
}
return predicate.Guild(func(s *sql.Selector) {
// if not arguments were provided, append the FALSE constants,
// since we can't apply "IN ()". This will make this predicate falsy.
if len(v) == 0 {
s.Where(sql.False())
return
}
s.Where(sql.NotIn(s.C(FieldMessage), v...))
})
}
// MessageGT applies the GT predicate on the "message" field.
func MessageGT(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GT(s.C(FieldMessage), v))
})
}
// MessageGTE applies the GTE predicate on the "message" field.
func MessageGTE(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.GTE(s.C(FieldMessage), v))
})
}
// MessageLT applies the LT predicate on the "message" field.
func MessageLT(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LT(s.C(FieldMessage), v))
})
}
// MessageLTE applies the LTE predicate on the "message" field.
func MessageLTE(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.LTE(s.C(FieldMessage), v))
})
}
// MessageContains applies the Contains predicate on the "message" field.
func MessageContains(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.Contains(s.C(FieldMessage), v))
})
}
// MessageHasPrefix applies the HasPrefix predicate on the "message" field.
func MessageHasPrefix(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.HasPrefix(s.C(FieldMessage), v))
})
}
// MessageHasSuffix applies the HasSuffix predicate on the "message" field.
func MessageHasSuffix(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.HasSuffix(s.C(FieldMessage), v))
})
}
// MessageEqualFold applies the EqualFold predicate on the "message" field.
func MessageEqualFold(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.EqualFold(s.C(FieldMessage), v))
})
}
// MessageContainsFold applies the ContainsFold predicate on the "message" field.
func MessageContainsFold(v string) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s.Where(sql.ContainsFold(s.C(FieldMessage), v))
})
}
// And groups list of predicates with the AND operator between them.
func And(predicates ...predicate.Guild) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s1 := s.Clone().SetP(nil)
for _, p := range predicates {
p(s1)
}
s.Where(s1.P())
})
}
// Or groups list of predicates with the OR operator between them.
func Or(predicates ...predicate.Guild) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
s1 := s.Clone().SetP(nil)
for i, p := range predicates {
if i > 0 {
s1.Or()
}
p(s1)
}
s.Where(s1.P())
})
}
// Not applies the not operator on the given predicate.
func Not(p predicate.Guild) predicate.Guild {
return predicate.Guild(func(s *sql.Selector) {
p(s.Not())
})
}

View file

@ -1,301 +0,0 @@
// Code generated by entc, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"github.com/facebook/ent/dialect/sql/sqlgraph"
"github.com/facebook/ent/schema/field"
"github.com/roleypoly/roleypoly/src/db/ent/guild"
"github.com/roleypoly/roleypoly/src/db/ent/schema"
)
// GuildCreate is the builder for creating a Guild entity.
type GuildCreate struct {
config
mutation *GuildMutation
hooks []Hook
}
// SetCreateTime sets the create_time field.
func (gc *GuildCreate) SetCreateTime(t time.Time) *GuildCreate {
gc.mutation.SetCreateTime(t)
return gc
}
// SetNillableCreateTime sets the create_time field if the given value is not nil.
func (gc *GuildCreate) SetNillableCreateTime(t *time.Time) *GuildCreate {
if t != nil {
gc.SetCreateTime(*t)
}
return gc
}
// SetUpdateTime sets the update_time field.
func (gc *GuildCreate) SetUpdateTime(t time.Time) *GuildCreate {
gc.mutation.SetUpdateTime(t)
return gc
}
// SetNillableUpdateTime sets the update_time field if the given value is not nil.
func (gc *GuildCreate) SetNillableUpdateTime(t *time.Time) *GuildCreate {
if t != nil {
gc.SetUpdateTime(*t)
}
return gc
}
// SetSnowflake sets the snowflake field.
func (gc *GuildCreate) SetSnowflake(s string) *GuildCreate {
gc.mutation.SetSnowflake(s)
return gc
}
// SetMessage sets the message field.
func (gc *GuildCreate) SetMessage(s string) *GuildCreate {
gc.mutation.SetMessage(s)
return gc
}
// SetCategories sets the categories field.
func (gc *GuildCreate) SetCategories(s []schema.Category) *GuildCreate {
gc.mutation.SetCategories(s)
return gc
}
// SetEntitlements sets the entitlements field.
func (gc *GuildCreate) SetEntitlements(s []string) *GuildCreate {
gc.mutation.SetEntitlements(s)
return gc
}
// Mutation returns the GuildMutation object of the builder.
func (gc *GuildCreate) Mutation() *GuildMutation {
return gc.mutation
}
// Save creates the Guild in the database.
func (gc *GuildCreate) Save(ctx context.Context) (*Guild, error) {
var (
err error
node *Guild
)
gc.defaults()
if len(gc.hooks) == 0 {
if err = gc.check(); err != nil {
return nil, err
}
node, err = gc.sqlSave(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*GuildMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err = gc.check(); err != nil {
return nil, err
}
gc.mutation = mutation
node, err = gc.sqlSave(ctx)
mutation.done = true
return node, err
})
for i := len(gc.hooks) - 1; i >= 0; i-- {
mut = gc.hooks[i](mut)
}
if _, err := mut.Mutate(ctx, gc.mutation); err != nil {
return nil, err
}
}
return node, err
}
// SaveX calls Save and panics if Save returns an error.
func (gc *GuildCreate) SaveX(ctx context.Context) *Guild {
v, err := gc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// defaults sets the default values of the builder before save.
func (gc *GuildCreate) defaults() {
if _, ok := gc.mutation.CreateTime(); !ok {
v := guild.DefaultCreateTime()
gc.mutation.SetCreateTime(v)
}
if _, ok := gc.mutation.UpdateTime(); !ok {
v := guild.DefaultUpdateTime()
gc.mutation.SetUpdateTime(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (gc *GuildCreate) check() error {
if _, ok := gc.mutation.CreateTime(); !ok {
return &ValidationError{Name: "create_time", err: errors.New("ent: missing required field \"create_time\"")}
}
if _, ok := gc.mutation.UpdateTime(); !ok {
return &ValidationError{Name: "update_time", err: errors.New("ent: missing required field \"update_time\"")}
}
if _, ok := gc.mutation.Snowflake(); !ok {
return &ValidationError{Name: "snowflake", err: errors.New("ent: missing required field \"snowflake\"")}
}
if _, ok := gc.mutation.Message(); !ok {
return &ValidationError{Name: "message", err: errors.New("ent: missing required field \"message\"")}
}
if _, ok := gc.mutation.Categories(); !ok {
return &ValidationError{Name: "categories", err: errors.New("ent: missing required field \"categories\"")}
}
if _, ok := gc.mutation.Entitlements(); !ok {
return &ValidationError{Name: "entitlements", err: errors.New("ent: missing required field \"entitlements\"")}
}
return nil
}
func (gc *GuildCreate) sqlSave(ctx context.Context) (*Guild, error) {
_node, _spec := gc.createSpec()
if err := sqlgraph.CreateNode(ctx, gc.driver, _spec); err != nil {
if cerr, ok := isSQLConstraintError(err); ok {
err = cerr
}
return nil, err
}
id := _spec.ID.Value.(int64)
_node.ID = int(id)
return _node, nil
}
func (gc *GuildCreate) createSpec() (*Guild, *sqlgraph.CreateSpec) {
var (
_node = &Guild{config: gc.config}
_spec = &sqlgraph.CreateSpec{
Table: guild.Table,
ID: &sqlgraph.FieldSpec{
Type: field.TypeInt,
Column: guild.FieldID,
},
}
)
if value, ok := gc.mutation.CreateTime(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: guild.FieldCreateTime,
})
_node.CreateTime = value
}
if value, ok := gc.mutation.UpdateTime(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeTime,
Value: value,
Column: guild.FieldUpdateTime,
})
_node.UpdateTime = value
}
if value, ok := gc.mutation.Snowflake(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: guild.FieldSnowflake,
})
_node.Snowflake = value
}
if value, ok := gc.mutation.Message(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeString,
Value: value,
Column: guild.FieldMessage,
})
_node.Message = value
}
if value, ok := gc.mutation.Categories(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeJSON,
Value: value,
Column: guild.FieldCategories,
})
_node.Categories = value
}
if value, ok := gc.mutation.Entitlements(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeJSON,
Value: value,
Column: guild.FieldEntitlements,
})
_node.Entitlements = value
}
return _node, _spec
}
// GuildCreateBulk is the builder for creating a bulk of Guild entities.
type GuildCreateBulk struct {
config
builders []*GuildCreate
}
// Save creates the Guild entities in the database.
func (gcb *GuildCreateBulk) Save(ctx context.Context) ([]*Guild, error) {
specs := make([]*sqlgraph.CreateSpec, len(gcb.builders))
nodes := make([]*Guild, len(gcb.builders))
mutators := make([]Mutator, len(gcb.builders))
for i := range gcb.builders {
func(i int, root context.Context) {
builder := gcb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*GuildMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err := builder.check(); err != nil {
return nil, err
}
builder.mutation = mutation
nodes[i], specs[i] = builder.createSpec()
var err error
if i < len(mutators)-1 {
_, err = mutators[i+1].Mutate(root, gcb.builders[i+1].mutation)
} else {
// Invoke the actual operation on the latest mutation in the chain.
if err = sqlgraph.BatchCreate(ctx, gcb.driver, &sqlgraph.BatchCreateSpec{Nodes: specs}); err != nil {
if cerr, ok := isSQLConstraintError(err); ok {
err = cerr
}
}
}
mutation.done = true
if err != nil {
return nil, err
}
id := specs[i].ID.Value.(int64)
nodes[i].ID = int(id)
return nodes[i], nil
})
for i := len(builder.hooks) - 1; i >= 0; i-- {
mut = builder.hooks[i](mut)
}
mutators[i] = mut
}(i, ctx)
}
if len(mutators) > 0 {
if _, err := mutators[0].Mutate(ctx, gcb.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX calls Save and panics if Save returns an error.
func (gcb *GuildCreateBulk) SaveX(ctx context.Context) []*Guild {
v, err := gcb.Save(ctx)
if err != nil {
panic(err)
}
return v
}

Some files were not shown because too many files have changed in this diff Show more