Compare commits
145
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd2e479361
|
||
|
|
593d6c552e
|
||
|
|
198c3e7952
|
||
|
|
d1eb5f05af
|
||
|
|
67cc71b05c
|
||
|
|
eeabf6308e | ||
|
|
db701b6c3e | ||
|
|
6fb3a2251d | ||
|
|
185ff03d37 | ||
|
|
efd86465e5 | ||
|
|
a973babd3b | ||
|
|
3e3d7de9f1 | ||
|
|
1bb20a3c16 | ||
|
|
eb43a08b39 | ||
|
|
5b95741deb | ||
|
|
e67f8b3684 | ||
|
|
a4e38eb3ae | ||
|
|
f4e30a780f | ||
|
|
ca8fc36e76 | ||
|
|
9a238bbbdc | ||
|
|
77785aa562 | ||
|
|
b462b3a64b | ||
|
|
13da7a2b2d | ||
|
|
59576f3321 | ||
|
|
c06d53532f | ||
|
|
12acd92a02 | ||
|
|
b7446e0307 | ||
|
|
1f2ac29ca8 | ||
|
|
0f77d80408 | ||
|
|
626efeff74 | ||
|
|
b963c070ea | ||
|
|
9ab0c0fe71 | ||
|
|
3e87a3df02 | ||
|
|
4852c42e8d | ||
|
|
b29d7b4dab | ||
|
|
5ffbd5fead | ||
|
|
2f96c6f806 | ||
|
|
a011f3cd24 | ||
|
|
0041bd4c67 | ||
|
|
7b1db25ccb | ||
|
|
4e5a3ee1a8 | ||
|
|
270319c615 | ||
|
|
d80fe268d7 | ||
|
|
01573b1dff | ||
|
|
530c5f489c | ||
|
|
70d5d4ef10 | ||
|
|
4f8dfd0499 | ||
|
|
8c281fe9ce | ||
|
|
642163896f | ||
|
|
db403d5f01 | ||
|
|
eb5b128cde | ||
|
|
5738d9e27f | ||
|
|
d87c64df03 | ||
|
|
8edc6fd318 | ||
|
|
d50e415bf3 | ||
|
|
f46036c3c0 | ||
|
|
2497b04be1 | ||
|
|
1ade3850a4 | ||
|
|
485ee3f635 | ||
|
|
b85bd69368 | ||
|
|
12901509a0 | ||
|
|
c0187d2671 | ||
|
|
bc03e1bd91 | ||
|
|
cc298b4d86 | ||
|
|
3ccf7684f3 | ||
|
|
827e9c7b65 | ||
|
|
f449101d49 | ||
|
|
f62de5ae83 | ||
|
|
e09824dbd3 | ||
|
|
25026d7010 | ||
|
|
776b3638d9 | ||
|
|
70baa24953 | ||
|
|
b60135b6f8 | ||
|
|
3b338f0f53 | ||
|
|
dc20dcf959 | ||
|
|
c62f0f2f47 | ||
|
|
21a7515797 | ||
|
|
cab3b15993 | ||
|
|
060b98f456 | ||
|
|
c717d96c3d | ||
|
|
f922a81fb1 | ||
|
|
5d48fddaae | ||
|
|
dfe645d023 | ||
|
|
19425cc03a | ||
|
|
2cb24b0d01 | ||
|
|
62bd23399c | ||
|
|
0e280ed843 | ||
|
|
588117e0d0 | ||
|
|
22fd99c673 | ||
|
|
715af8c1bc | ||
|
|
ff5cfb5f3b | ||
|
|
ec1be803c8 | ||
|
|
3d835ab5f4 | ||
|
|
6e83bc6bd9 | ||
|
|
f60de139c0 | ||
|
|
a8ee028292 | ||
|
|
081b21d58c | ||
|
|
454cced2a7 | ||
|
|
106333c26b | ||
|
|
6df9d6366f | ||
|
|
5940bc8e22 | ||
|
|
c01562cec5 | ||
|
|
70c1d2d35b | ||
|
|
121a21e1c6 | ||
|
|
f85c475cfd | ||
|
|
a8ea92c140 | ||
|
|
84311836f2 | ||
|
|
28691e72fb | ||
|
|
ccfecd0965 | ||
|
|
e2f97afa6d | ||
|
|
4188343429 | ||
|
|
b8c9e8fd39 | ||
|
|
fec57e421f | ||
|
|
6a4d326e57 | ||
|
|
532be87f30 | ||
|
|
7596d96a24 | ||
|
|
ace7d8ac54 | ||
|
|
be3fa68eca | ||
|
|
85e498d353 | ||
|
|
e0491b63b3 | ||
|
|
f7f0f5fc8c | ||
|
|
4ad96efc13 | ||
|
|
3a8dec15fa | ||
|
|
4cf439a826 | ||
|
|
ba0b7235e2 | ||
|
|
248a566fea | ||
|
|
0cd69aa6b3 | ||
|
|
38d0f69f9f | ||
|
|
9c511db33e | ||
|
|
1306ba6fde | ||
|
|
eedf34022e | ||
|
|
fe4dca9307 | ||
|
|
1cc9437300 | ||
|
|
f1df8472ef | ||
|
|
df8f8f2fa6 | ||
|
|
cfe683c53c | ||
|
|
b611dd7c87 | ||
|
|
426b4c99b7 | ||
|
|
c77ae4cfac | ||
|
|
30ea8d8c8d | ||
|
|
4a88008b8d | ||
|
|
75697c44dc | ||
|
|
e840f6b651 | ||
|
|
df14091e04 | ||
|
|
9c18544dde |
@@ -0,0 +1,5 @@
|
||||
# Service release contract
|
||||
|
||||
Butler resolves this repository's protected source revision to verified immutable images. The platform updates only image references in the existing production Compose file and restarts only the already running application services. It preserves current environment, storage, routes, and provider configuration. It retains previous application images and restores them if readiness fails.
|
||||
|
||||
Migration and maintenance images are pinned when declared, but this release operation does not run database migrations or maintenance jobs. A release requiring a schema change needs the corresponding explicit platform migration first. No homelab image-pin commit is required for an ordinary compatible application release.
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"deployment": "geeksbot-release",
|
||||
"environment": "production",
|
||||
"images": {
|
||||
"geeksbot_release_geeksbot_image": {
|
||||
"name": "geeksbot",
|
||||
"tag": "sha-{revision}"
|
||||
}
|
||||
},
|
||||
"revision_variable": "geeksbot_release_revision"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
.git
|
||||
.github
|
||||
.gitea
|
||||
.env
|
||||
.idea
|
||||
geeksbot
|
||||
@@ -0,0 +1,158 @@
|
||||
name: Build and Push Container
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- v*
|
||||
workflow_dispatch: null
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number
|
||||
|| github.run_id }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: butler-ci
|
||||
env:
|
||||
REGISTRY: gitea.wayfinderak.com
|
||||
IMAGE_NAME: gitea.wayfinderak.com/wayfinderak/geeksbot
|
||||
container:
|
||||
options: --dns 172.16.30.10
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: https://github.com/actions/checkout@v4
|
||||
|
||||
- name: Select relevant delivery work
|
||||
id: delivery
|
||||
env:
|
||||
DELIVERY_EVENT: ${{ github.event_name }}
|
||||
DELIVERY_REF: ${{ github.ref }}
|
||||
DELIVERY_SHA: ${{ github.sha }}
|
||||
DELIVERY_BASE: ${{ github.event.pull_request.base.sha || github.event.before }}
|
||||
run: |
|
||||
cd .
|
||||
bash scripts/ci-select.sh
|
||||
- name: Install Go and Docker CLI if needed
|
||||
if: ${{ steps.delivery.outputs.run == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
need_apt=0
|
||||
need_apk=0
|
||||
if ! command -v go >/dev/null 2>&1 || ! command -v docker >/dev/null 2>&1; then
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
need_apt=1
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
need_apk=1
|
||||
else
|
||||
echo "No supported package manager found" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$need_apt" -eq 1 ]; then
|
||||
apt-get update
|
||||
if ! command -v go >/dev/null 2>&1; then
|
||||
apt-get install -y golang-go
|
||||
fi
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
apt-get install -y docker.io curl dnsutils iputils-ping
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$need_apk" -eq 1 ]; then
|
||||
if ! command -v go >/dev/null 2>&1; then
|
||||
apk add --no-cache go
|
||||
fi
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
apk add --no-cache docker-cli curl bind-tools iputils
|
||||
fi
|
||||
fi
|
||||
|
||||
go version
|
||||
docker version
|
||||
|
||||
- name: Run tests
|
||||
if: ${{ steps.delivery.outputs.run == 'true' }}
|
||||
run: go test ./...
|
||||
|
||||
- name: Log in to Gitea Container Registry
|
||||
if: ${{ (steps.delivery.outputs.run == 'true') && github.event_name != 'pull_request' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for attempt in 1 2 3; do
|
||||
echo "docker login attempt $attempt"
|
||||
if echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "$REGISTRY" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin; then
|
||||
exit 0
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
echo "docker login failed after 3 attempts" >&2
|
||||
exit 1
|
||||
|
||||
- name: Determine image tags
|
||||
if: ${{ steps.delivery.outputs.run == 'true' }}
|
||||
id: meta
|
||||
shell: bash
|
||||
env:
|
||||
REF: ${{ gitea.ref }}
|
||||
REF_NAME: ${{ gitea.ref_name }}
|
||||
SHA: ${{ gitea.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tags=("$IMAGE_NAME:sha-$SHA")
|
||||
|
||||
if [[ "$REF" == refs/tags/* ]]; then
|
||||
version="$REF_NAME"
|
||||
tags+=("$IMAGE_NAME:$version")
|
||||
tags+=("$IMAGE_NAME:latest")
|
||||
else
|
||||
branch="$REF_NAME"
|
||||
branch_safe="$(echo "$branch" | tr '/_' '--')"
|
||||
sha_short="$(echo "$SHA" | cut -c1-7)"
|
||||
tags+=("$IMAGE_NAME:$branch_safe")
|
||||
tags+=("$IMAGE_NAME:$branch_safe-$sha_short")
|
||||
if [[ "$branch" == "main" || "$branch" == "master" ]]; then
|
||||
tags+=("$IMAGE_NAME:latest")
|
||||
fi
|
||||
fi
|
||||
|
||||
printf 'tags<<EOF\n' >> "$GITHUB_OUTPUT"
|
||||
printf '%s\n' "${tags[@]}" >> "$GITHUB_OUTPUT"
|
||||
printf 'EOF\n' >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build image
|
||||
if: ${{ steps.delivery.outputs.run == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mapfile -t tags <<'EOF'
|
||||
${{ steps.meta.outputs.tags }}
|
||||
EOF
|
||||
|
||||
build_args=()
|
||||
for tag in "${tags[@]}"; do
|
||||
build_args+=(--tag "$tag")
|
||||
done
|
||||
|
||||
docker build --label "org.opencontainers.image.revision=$GITHUB_SHA" "${build_args[@]}" .
|
||||
|
||||
- name: Push image
|
||||
if: ${{ (steps.delivery.outputs.run == 'true') && github.event_name != 'pull_request' }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
while IFS= read -r tag; do
|
||||
[ -n "$tag" ] || continue
|
||||
docker push "$tag"
|
||||
done <<'EOF'
|
||||
${{ steps.meta.outputs.tags }}
|
||||
EOF
|
||||
+54
-53
@@ -1,63 +1,64 @@
|
||||
name: CI
|
||||
name: Build and Push Container
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push to master or development
|
||||
# with a tag like v1.0.0 or v1.0.0-dev
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+
|
||||
- v[0-9]+.[0-9]+.[0-9]+-[a-zA-Z]+
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
tags:
|
||||
- v*
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY: gitea.wayfinderak.com
|
||||
IMAGE_NAME: wayfinderak/geeksbot
|
||||
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Get Version
|
||||
id: get_version
|
||||
uses: battila7/get-version-action@v2.0.0
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Golang 1.15
|
||||
uses: actions/setup-go@v1
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
go-version: 1.15
|
||||
|
||||
- name: Install go-bindata
|
||||
uses: cedrickring/golang-action@1.6.0
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Prepare image tags
|
||||
id: prep
|
||||
shell: bash
|
||||
run: |
|
||||
short_sha="${GITHUB_SHA::7}"
|
||||
tags="${REGISTRY}/${IMAGE_NAME}:sha-${short_sha}"
|
||||
|
||||
if [[ "${GITHUB_REF_TYPE}" == "branch" && ("${GITHUB_REF_NAME}" == "master" || "${GITHUB_REF_NAME}" == "main") ]]; then
|
||||
tags+=$'\n'"${REGISTRY}/${IMAGE_NAME}:latest"
|
||||
fi
|
||||
|
||||
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
|
||||
version="${GITHUB_REF_NAME#v}"
|
||||
tags+=$'\n'"${REGISTRY}/${IMAGE_NAME}:${version}"
|
||||
fi
|
||||
|
||||
{
|
||||
echo 'tags<<EOF'
|
||||
echo "$tags"
|
||||
echo 'EOF'
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build and push image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
args: go get -u github.com/go-bindata/go-bindata/...
|
||||
|
||||
- name: Build migrations
|
||||
run: go-bindata -pkg migrations -o $GITHUB_WORKSPACE/internal/database/migrations/bindata.go $GITHUB_WORKSPACE/internal/database/migrations/
|
||||
|
||||
- name: Build container image
|
||||
env:
|
||||
IMAGE_TAG: ${{ steps.get_version.outputs.version-without-v }}
|
||||
run: docker build -t registry.digitalocean.com/djpianalto/geeksbot:$IMAGE_TAG .
|
||||
|
||||
- name: Install doctl
|
||||
uses: digitalocean/action-doctl@v2
|
||||
with:
|
||||
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
|
||||
|
||||
- name: Login to DigitalOcean Container Registry with short-lived credentials
|
||||
run: doctl registry login --expiry-seconds 600
|
||||
|
||||
- name: Push image to DigitalOcean Container Registry
|
||||
run: docker push registry.digitalocean.com/djpianalto/geeksbot
|
||||
|
||||
- name: Update deployment file
|
||||
run: TAG=${{ steps.get_version.outputs.version-without-v }} && sed -i 's|<IMAGE>|registry.digitalocean.com/djpianalto/geeksbot:'${TAG}'|' $GITHUB_WORKSPACE/deployment.yml
|
||||
|
||||
- name: Save DigitalOcean kubeconfig with short-lived credentials
|
||||
run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 discord-bots
|
||||
|
||||
- name: Deploy to DigitalOcean Kubernetes
|
||||
run: kubectl apply -f $GITHUB_WORKSPACE/deployment.yml
|
||||
|
||||
- name: Verify deployment
|
||||
run: kubectl rollout status deployment/geeksbot
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.prep.outputs.tags }}
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
.env
|
||||
.idea
|
||||
|
||||
portainer-app.env
|
||||
|
||||
+10
-12
@@ -1,20 +1,18 @@
|
||||
FROM golang:1.14-alpine as dev
|
||||
FROM golang:1.22-alpine AS builder
|
||||
|
||||
WORKDIR /go/src/Geeksbot
|
||||
COPY ./go.mod .
|
||||
COPY ./go.sum .
|
||||
WORKDIR /src
|
||||
RUN apk add --no-cache ca-certificates git tzdata
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
RUN go install github.com/dustinpianalto/geeksbot/...
|
||||
ARG TARGETARCH=amd64
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH go build -o /out/geeksbot ./cmd/geeksbot
|
||||
|
||||
CMD [ "go", "run", "cmd/geeksbot/main.go"]
|
||||
FROM alpine:3.20
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
|
||||
from alpine
|
||||
COPY --from=builder /out/geeksbot /usr/local/bin/geeksbot
|
||||
|
||||
WORKDIR /bin
|
||||
|
||||
COPY --from=dev /go/bin/geeksbot ./geeksbot
|
||||
|
||||
CMD [ "geeksbot" ]
|
||||
ENTRYPOINT ["/usr/local/bin/geeksbot"]
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Portainer deployment notes
|
||||
|
||||
Generated from the current Kubernetes deployment in namespace `discord-bots`. Secret values are in the local `portainer-*.env` files.
|
||||
|
||||
## Kubernetes source
|
||||
|
||||
- Deployment: `geeksbot`
|
||||
- Replicas: `1`
|
||||
- Rolling update: maxSurge `1`, maxUnavailable `1`
|
||||
- minReadySeconds: `120`
|
||||
- Labels/selectors: `app=geeksbot`
|
||||
- Image pull secrets: `none required for Portainer stack`
|
||||
|
||||
## Containers
|
||||
|
||||
- `pgbouncer`: image `timoha/pgbouncer:1.15.0`; env: DATABASE_URL, SERVER_TLS_SSLMODE, AUTH_TYPE; ports: 5432; requests: {'cpu': '500m', 'memory': '256Mi'}; limits: {'cpu': '1', 'memory': '512Mi'}
|
||||
- `geeksbot`: image `gitea.wayfinderak.com/wayfinderak/geeksbot:latest`; env: DATABASE_URL, DISCORD_TOKEN; ports: none; requests: {'cpu': '1', 'memory': '512Mi'}; limits: {'cpu': '2', 'memory': '1Gi'}
|
||||
|
||||
## Portainer files
|
||||
|
||||
- `portainer-stack.yml` - Docker Compose stack to paste/use in Portainer.
|
||||
- `portainer-app.env` - bot runtime secrets/env.
|
||||
|
||||
## Portainer database connection
|
||||
|
||||
This Portainer stack does not include pgbouncer. `DATABASE_URL` in `portainer-app.env` points directly at the external PostgreSQL service copied from the Kubernetes pgbouncer upstream URL.
|
||||
+6
-5
@@ -9,9 +9,10 @@ type Channel struct {
|
||||
}
|
||||
|
||||
type ChannelService interface {
|
||||
Channel(id string) (*Channel, error)
|
||||
CreateChannel(c *Channel) (*Channel, error)
|
||||
DeleteChannel(c *Channel) error
|
||||
GuildChannels(g *Guild) ([]*Channel, error)
|
||||
UpdateChannel(c *Channel) (*Channel, error)
|
||||
Channel(id string) (Channel, error)
|
||||
CreateChannel(c Channel) (Channel, error)
|
||||
DeleteChannel(c Channel) error
|
||||
GuildChannels(g Guild) ([]Channel, error)
|
||||
UpdateChannel(c Channel) (Channel, error)
|
||||
GetOrCreateChannel(id string, guild_id string) (Channel, error)
|
||||
}
|
||||
|
||||
+13
-21
@@ -6,10 +6,11 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/dustinpianalto/discordgo"
|
||||
"github.com/dustinpianalto/disgoman"
|
||||
"github.com/dustinpianalto/geeksbot/internal/database"
|
||||
"github.com/dustinpianalto/geeksbot/internal/exts"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/exts"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/database"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/services"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -21,17 +22,16 @@ func main() {
|
||||
}
|
||||
dg.State.MaxMessageCount = 100
|
||||
dg.StateEnabled = true
|
||||
dg.LogLevel = 3
|
||||
dg.Debug = false
|
||||
|
||||
dg.Identify = discordgo.Identify{
|
||||
Intents: discordgo.MakeIntent(discordgo.IntentsAll),
|
||||
}
|
||||
|
||||
database.ConnectDatabase(os.Getenv("DATABASE_URL"))
|
||||
//postgres.InitializeDatabase()
|
||||
//utils.LoadTestData()
|
||||
|
||||
//us := &postgres.UserService{DB: postgres.DB}
|
||||
//gs := &postgres.GuildService{DB: postgres.DB}
|
||||
//database.RunMigrations()
|
||||
services.InitializeServices()
|
||||
|
||||
owners := []string{
|
||||
"351794468870946827",
|
||||
@@ -49,18 +49,9 @@ func main() {
|
||||
|
||||
// Add Command Handlers
|
||||
exts.AddCommandHandlers(&manager)
|
||||
//services.InitalizeServices(us, gs)
|
||||
|
||||
//if _, ok := handler.Commands["help"]; !ok {
|
||||
// handler.AddDefaultHelpCommand()
|
||||
//}
|
||||
|
||||
dg.AddHandler(manager.OnMessage)
|
||||
dg.AddHandler(manager.StatusManager.OnReady)
|
||||
//dg.AddHandler(guild_management.OnMessageUpdate)
|
||||
//dg.AddHandler(guild_management.OnMessageDelete)
|
||||
//dg.AddHandler(user_management.OnGuildMemberAddLogging)
|
||||
//dg.AddHandler(user_management.OnGuildMemberRemoveLogging)
|
||||
|
||||
err = dg.Open()
|
||||
if err != nil {
|
||||
@@ -71,9 +62,6 @@ func main() {
|
||||
// Start the Error handler in a goroutine
|
||||
go ErrorHandler(manager.ErrorChannel)
|
||||
|
||||
// Start the Logging handler in a goroutine
|
||||
//go logging.LoggingHandler(logging.LoggingChannel)
|
||||
|
||||
log.Println("The Bot is now running.")
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
|
||||
@@ -87,7 +75,11 @@ func main() {
|
||||
}
|
||||
|
||||
func getPrefixes(guildID string) []string {
|
||||
return []string{"G.", "g."}
|
||||
guild, err := services.GuildService.Guild(guildID)
|
||||
if err != nil || len(guild.Prefixes) == 0 {
|
||||
return []string{"G$", "g$"}
|
||||
}
|
||||
return guild.Prefixes
|
||||
}
|
||||
|
||||
func ErrorHandler(ErrorChan chan disgoman.CommandError) {
|
||||
|
||||
+37
-1
@@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: geeksbot
|
||||
namespace: default
|
||||
namespace: discord-bots
|
||||
labels:
|
||||
app: geeksbot
|
||||
spec:
|
||||
@@ -21,8 +21,42 @@ spec:
|
||||
app: geeksbot
|
||||
spec:
|
||||
containers:
|
||||
- name: pgbouncer
|
||||
image: timoha/pgbouncer:1.15.0
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "0.5"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "1"
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: geeksbot
|
||||
key: pgbouncer_url
|
||||
- name: SERVER_TLS_SSLMODE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: geeksbot
|
||||
key: pgbouncer_ssl
|
||||
- name: AUTH_TYPE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: geeksbot
|
||||
key: pgbouncer_auth
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
- name: geeksbot
|
||||
image: <IMAGE>
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "1"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "2"
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
@@ -34,3 +68,5 @@ spec:
|
||||
secretKeyRef:
|
||||
name: geeksbot
|
||||
key: discord_token
|
||||
imagePullSecrets:
|
||||
- name: registry-1
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
services:
|
||||
geeksbot:
|
||||
image: ${IMAGE:-gitea.wayfinderak.com/wayfinderak/geeksbot:${IMAGE_TAG:-latest}}
|
||||
container_name: geeksbot
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
DISCORD_TOKEN: ${DISCORD_TOKEN}
|
||||
@@ -1,12 +1,13 @@
|
||||
module github.com/dustinpianalto/geeksbot
|
||||
module gitea.wayfinderak.com/wayfinderak/geeksbot
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/bwmarrin/discordgo v0.22.1
|
||||
github.com/dustinpianalto/disgoman v0.0.15
|
||||
github.com/go-bindata/go-bindata v3.1.2+incompatible // indirect
|
||||
github.com/golang-migrate/migrate v3.5.4+incompatible // indirect
|
||||
github.com/bwmarrin/discordgo v0.29.0 // indirect
|
||||
github.com/dustinpianalto/discordgo v0.0.4
|
||||
github.com/dustinpianalto/disgoman v0.0.26
|
||||
github.com/golang-migrate/migrate/v4 v4.14.1
|
||||
github.com/gorcon/rcon v1.3.1
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/lib/pq v1.8.0
|
||||
)
|
||||
|
||||
@@ -33,19 +33,22 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
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/AlekSi/pointer v1.0.0 h1:KWCWzsvFxNLcmM5XmiqHsGTTsuwZMsLFwWF9Y+//bNE=
|
||||
github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
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/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0=
|
||||
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/bwmarrin/discordgo v0.20.2/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
|
||||
github.com/bwmarrin/discordgo v0.22.1 h1:254fNYyfqJWKbPzO5g8j/nUvRgj4dNlI19EB8rnkpt8=
|
||||
github.com/bwmarrin/discordgo v0.22.1/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
|
||||
github.com/bwmarrin/discordgo v0.29.0 h1:FmWeXFaKUwrcL3Cx65c20bTRW+vOb6k8AnaP+EgjDno=
|
||||
github.com/bwmarrin/discordgo v0.29.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
@@ -57,22 +60,31 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/cockroach-go v0.0.0-20190925194419-606b3d062051/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
|
||||
github.com/containerd/containerd v1.4.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.1 h1:pASeJT3R3YyVn+94qEPk0SnU1OQ20Jd/T+SPKy9xehY=
|
||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
|
||||
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/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dhui/dktest v0.3.3 h1:DBuH/9GFaWbDRa42qsut/hbQu+srAQ0rPWnUoiGX7CA=
|
||||
github.com/dhui/dktest v0.3.3/go.mod h1:EML9sP4sqJELHn4jV7B0TY8oF6077nk83/tz7M56jcQ=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible h1:iWPIG7pWIsCwT6ZtHnTUpoVMnete7O/pzd9HFE3+tn8=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustinpianalto/disgoman v0.0.15 h1:kdIw6jhC82WBut7+4BarqxBw06dozU+Hu47LQzkkoGM=
|
||||
github.com/dustinpianalto/disgoman v0.0.15/go.mod h1:v3FM6n+4dH9XlvO+IDx6MN3DUnGq6YVDBvy1A1k202g=
|
||||
github.com/dustinpianalto/discordgo v0.0.4 h1:KlIkMzDH4jKRbs5IxeqeIXtNTDVcDi/sHV1gaKYEnPg=
|
||||
github.com/dustinpianalto/discordgo v0.0.4/go.mod h1:LKY7UDCPJMChgrowLagHjDSj1gWbt3Hx+6bRFjpaVg8=
|
||||
github.com/dustinpianalto/disgoman v0.0.26 h1:7p6hDbNgEehUgOHigY/lHDY4P2VklJiZmOn674ka1h0=
|
||||
github.com/dustinpianalto/disgoman v0.0.26/go.mod h1:WsDb+7XIm2MJ6xhxRAiXlzSPuSYIGSr4rWRmACeoing=
|
||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
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=
|
||||
@@ -80,9 +92,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw=
|
||||
github.com/go-bindata/go-bindata v1.0.0 h1:DZ34txDXWn1DyWa+vQf7V9ANc2ILTtrEjtlsdJRF26M=
|
||||
github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE=
|
||||
github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo=
|
||||
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=
|
||||
@@ -91,10 +100,8 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
||||
github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang-migrate/migrate v1.3.2 h1:QAlFV1QF9zdkzy/jujlBVkVu+L/+k18cg8tuY1/4JDY=
|
||||
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
|
||||
github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk=
|
||||
github.com/golang-migrate/migrate/v4 v4.14.1 h1:qmRd/rNGjM1r3Ve5gHd5ZplytrD02UcItYNxJ3iUHHE=
|
||||
github.com/golang-migrate/migrate/v4 v4.14.1/go.mod h1:l7Ks0Au6fYHuUIxUhQ0rcVX1uLlJg54C/VvW7tvxSz0=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
@@ -123,6 +130,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||
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/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -135,6 +143,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
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 v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
@@ -152,15 +161,17 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
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/gorcon/rcon v1.3.1 h1:z6a5iOlojfdkvA1qaKEng7QfCJuCzYlC9BUDs6/M+74=
|
||||
github.com/gorcon/rcon v1.3.1/go.mod h1:2gztBPSV2WxkPkqV4jiJkdHs+NT46mNSGb8JxbPesx4=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
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/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -207,9 +218,11 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
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/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
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/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
@@ -226,6 +239,7 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY=
|
||||
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
|
||||
@@ -234,12 +248,16 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
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_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
@@ -252,6 +270,7 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/snowflakedb/glog v0.0.0-20180824191149-f5055e6f21ce/go.mod h1:EB/w24pR5VKI60ecFnKqXzxX3dOorz1rnVicQTQrGM0=
|
||||
github.com/snowflakedb/gosnowflake v1.3.5/go.mod h1:13Ky+lxzIm3VqNDZJdyvu9MCGy+WgRdYFdXp96UcLZU=
|
||||
@@ -262,6 +281,7 @@ github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
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.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
|
||||
@@ -283,8 +303,6 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA=
|
||||
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-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
@@ -295,6 +313,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
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=
|
||||
@@ -358,6 +378,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -411,14 +433,19 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
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=
|
||||
@@ -471,6 +498,7 @@ golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8T
|
||||
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/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=
|
||||
@@ -527,6 +555,7 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3 h1:sg8vLDNIxFPHTchfhH1E3AI32BL3f23oie38xUWnJM8=
|
||||
google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/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=
|
||||
@@ -541,6 +570,7 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
|
||||
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/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
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=
|
||||
@@ -551,8 +581,10 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
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/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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
@@ -562,7 +594,9 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
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=
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
package geeksbot
|
||||
|
||||
import "database/sql"
|
||||
|
||||
type Guild struct {
|
||||
ID string
|
||||
NewPatronMessage string
|
||||
NewPatronMessage sql.NullString
|
||||
Prefixes []string
|
||||
}
|
||||
|
||||
type Role struct {
|
||||
ID string
|
||||
RoleType int
|
||||
RoleType string
|
||||
Guild Guild
|
||||
}
|
||||
|
||||
type GuildService interface {
|
||||
Guild(id string) (*Guild, error)
|
||||
CreateGuild(g *Guild) (*Guild, error)
|
||||
DeleteGuild(g *Guild) error
|
||||
UpdateGuild(g *Guild) (*Guild, error)
|
||||
GuildRoles(g *Guild) ([]*Role, error)
|
||||
CreateRole(r *Role) (*Role, error)
|
||||
Role(id string) (*Role, error)
|
||||
UpdateRole(r *Role) (*Role, error)
|
||||
DeleteRole(r *Role) error
|
||||
Guild(id string) (Guild, error)
|
||||
CreateGuild(g Guild) (Guild, error)
|
||||
DeleteGuild(g Guild) error
|
||||
UpdateGuild(g Guild) (Guild, error)
|
||||
GuildRoles(g Guild) ([]Role, error)
|
||||
CreateRole(r Role) (Role, error)
|
||||
Role(id string) (Role, error)
|
||||
UpdateRole(r Role) (Role, error)
|
||||
DeleteRole(r Role) error
|
||||
GetOrCreateGuild(id string) (Guild, error)
|
||||
CreateOrUpdateRole(r Role) (Role, error)
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/dustinpianalto/geeksbot/internal/database/migrations"
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
"github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
bindata "github.com/golang-migrate/migrate/v4/source/go_bindata"
|
||||
)
|
||||
|
||||
var (
|
||||
db *sql.DB
|
||||
)
|
||||
|
||||
func ConnectDatabase(dbConnString string) {
|
||||
s := bindata.Resource(migrations.AssetNames(),
|
||||
func(name string) ([]byte, error) {
|
||||
return migrations.Asset(name)
|
||||
})
|
||||
db, err := sql.Open("postgres", dbConnString)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("Can't connect to the database: %w", err))
|
||||
}
|
||||
log.Println("Database Connected.")
|
||||
db.SetMaxOpenConns(75)
|
||||
db.SetMaxIdleConns(5)
|
||||
db.SetConnMaxLifetime(300)
|
||||
d, err := bindata.WithInstance(s)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("Cannot load migrations: %w", err))
|
||||
}
|
||||
instance, err := postgres.WithInstance(db, &postgres.Config{})
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("Cannot create db driver: %w", err))
|
||||
}
|
||||
m, err := migrate.NewWithInstance("go-bindata", d, "postgres", instance)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("Cannot create migration instance: %w", err))
|
||||
}
|
||||
m.Up()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package discord_utils
|
||||
|
||||
import "github.com/dustinpianalto/disgoman"
|
||||
|
||||
func GetChannelName(ctx disgoman.Context, id string) string {
|
||||
channel, err := ctx.Session.Channel(id)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return channel.Name
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package discord_utils
|
||||
|
||||
import (
|
||||
"github.com/dustinpianalto/disgoman"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/services"
|
||||
)
|
||||
|
||||
func IsGuildMod(ctx disgoman.Context, user geeksbot.User) bool {
|
||||
discordCloser, err := ctx.Session.GuildMember(ctx.Guild.ID, user.ID)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
guildRoles, err := services.GuildService.GuildRoles(geeksbot.Guild{ID: ctx.Guild.ID})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, role := range guildRoles {
|
||||
if role.RoleType == "moderator" {
|
||||
for _, rID := range discordCloser.Roles {
|
||||
if rID == role.ID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsGuildAdmin(ctx disgoman.Context, user geeksbot.User) bool {
|
||||
discordCloser, err := ctx.Session.GuildMember(ctx.Guild.ID, user.ID)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
guildRoles, err := services.GuildService.GuildRoles(geeksbot.Guild{ID: ctx.Guild.ID})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, role := range guildRoles {
|
||||
if role.RoleType == "admin" {
|
||||
for _, rID := range discordCloser.Roles {
|
||||
if rID == role.ID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package discord_utils
|
||||
|
||||
import "github.com/dustinpianalto/disgoman"
|
||||
|
||||
func SendErrorMessage(ctx disgoman.Context, msg string, err error) {
|
||||
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
|
||||
Context: ctx,
|
||||
Message: msg,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package discord_utils
|
||||
|
||||
import "github.com/dustinpianalto/disgoman"
|
||||
|
||||
func GetDisplayName(ctx disgoman.Context, id string) string {
|
||||
member, err := ctx.Session.GuildMember(ctx.Guild.ID, id)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if member.Nick != "" {
|
||||
return member.Nick
|
||||
}
|
||||
return member.User.Username
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package arcon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/dustinpianalto/disgoman"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/discord_utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/services"
|
||||
"github.com/gorcon/rcon"
|
||||
)
|
||||
|
||||
var ListplayersCommand = &disgoman.Command{
|
||||
Name: "listplayers",
|
||||
Aliases: nil,
|
||||
Description: "List the players currently connected to a ARK server.",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: listplayersCommandFunc,
|
||||
}
|
||||
|
||||
func listplayersCommandFunc(ctx disgoman.Context, args []string) {
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error getting Guild from the database", err)
|
||||
return
|
||||
}
|
||||
author, err := services.UserService.GetOrCreateUser(ctx.Message.Author.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Sorry, there was a problem getting your user.", err)
|
||||
return
|
||||
}
|
||||
if !discord_utils.IsGuildAdmin(ctx, author) && !discord_utils.IsGuildMod(ctx, author) {
|
||||
return
|
||||
}
|
||||
if len(args) == 0 {
|
||||
servers, err := services.ServerService.GuildServers(guild)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Could not find any servers for this guild", err)
|
||||
return
|
||||
}
|
||||
for _, server := range servers {
|
||||
go listplayers(ctx, server)
|
||||
}
|
||||
return
|
||||
}
|
||||
serverName := strings.Join(args, " ")
|
||||
server, err := services.ServerService.ServerByName(serverName, guild)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx,
|
||||
fmt.Sprintf("Could not find **%s** in this guild.", serverName),
|
||||
err,
|
||||
)
|
||||
return
|
||||
}
|
||||
listplayers(ctx, server)
|
||||
}
|
||||
|
||||
func listplayers(ctx disgoman.Context, server geeksbot.Server) {
|
||||
msg, err := ctx.Send(fmt.Sprintf("**Getting data for %s**", server.Name))
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "There was an error getting the player list", err)
|
||||
return
|
||||
}
|
||||
conn, err := rcon.Dial(fmt.Sprintf("%s:%d", server.IPAddr, server.Port), server.Password)
|
||||
if err != nil {
|
||||
_, _ = ctx.Session.ChannelMessageEdit(ctx.Channel.ID, msg.ID,
|
||||
fmt.Sprintf("**Could not open connection to %s**", server.Name),
|
||||
)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
response, err := conn.Execute("listplayers")
|
||||
if err != nil {
|
||||
_, _ = ctx.Session.ChannelMessageEdit(ctx.Channel.ID, msg.ID,
|
||||
fmt.Sprintf("**There was a problem getting a response from %s**", server.Name),
|
||||
)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(response, "No Players") {
|
||||
_, _ = ctx.Session.ChannelMessageEdit(ctx.Channel.ID, msg.ID,
|
||||
fmt.Sprintf("**%s: %s**", server.Name, response),
|
||||
)
|
||||
return
|
||||
}
|
||||
players := strings.Split(response, "\n")
|
||||
for i, player := range players {
|
||||
parts := strings.Split(player, ", ")
|
||||
steamID := parts[len(parts)-1]
|
||||
user, err := services.UserService.GetBySteamID(steamID)
|
||||
if err == nil {
|
||||
duser, err := ctx.Session.GuildMember(ctx.Guild.ID, user.ID)
|
||||
if err == nil {
|
||||
players[i] = fmt.Sprintf("%s (%s)", player, duser.Mention())
|
||||
}
|
||||
}
|
||||
}
|
||||
_, _ = ctx.Session.ChannelMessageEdit(ctx.Channel.ID, msg.ID,
|
||||
fmt.Sprintf("**%s:**%s", server.Name, strings.Join(players, "\n")),
|
||||
)
|
||||
}
|
||||
|
||||
var BroadcastCommand = &disgoman.Command{
|
||||
Name: "broadcast",
|
||||
Aliases: nil,
|
||||
Description: "Broadcast a message to ARK servers.",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: broadcastCommandFunc,
|
||||
}
|
||||
|
||||
func broadcastCommandFunc(ctx disgoman.Context, args []string) {
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error getting Guild from the database", err)
|
||||
return
|
||||
}
|
||||
author, err := services.UserService.GetOrCreateUser(ctx.Message.Author.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Sorry, there was a problem getting your user.", err)
|
||||
return
|
||||
}
|
||||
if !discord_utils.IsGuildAdmin(ctx, author) && !discord_utils.IsGuildMod(ctx, author) {
|
||||
return
|
||||
}
|
||||
message := strings.Join(args[1:len(args)], " ")
|
||||
if strings.ToLower(args[0]) == "all" {
|
||||
servers, err := services.ServerService.GuildServers(guild)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Could not find any servers for this guild", err)
|
||||
return
|
||||
}
|
||||
for _, server := range servers {
|
||||
go broadcast(ctx, server, message)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
serverName := strings.Title(strings.ReplaceAll(args[0], "_", " "))
|
||||
server, err := services.ServerService.ServerByName(serverName, guild)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("Could not find %s", serverName), err)
|
||||
return
|
||||
}
|
||||
broadcast(ctx, server, message)
|
||||
}
|
||||
}
|
||||
|
||||
func broadcast(ctx disgoman.Context, server geeksbot.Server, message string) {
|
||||
msg, err := ctx.Send(fmt.Sprintf("**Broadcasting to: %s**", server.Name))
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "There was an error getting the player list", err)
|
||||
return
|
||||
}
|
||||
conn, err := rcon.Dial(fmt.Sprintf("%s:%d", server.IPAddr, server.Port), server.Password)
|
||||
if err != nil {
|
||||
_, _ = ctx.Session.ChannelMessageEdit(ctx.Channel.ID, msg.ID,
|
||||
fmt.Sprintf("**Could not open connection to %s**", server.Name),
|
||||
)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
userName := discord_utils.GetDisplayName(ctx, ctx.Message.Author.ID)
|
||||
response, err := conn.Execute(fmt.Sprintf("broadcast %s: %s", userName, message))
|
||||
if err != nil {
|
||||
_, _ = ctx.Session.ChannelMessageEdit(ctx.Channel.ID, msg.ID,
|
||||
fmt.Sprintf("**There was a problem getting a response from %s**", server.Name),
|
||||
)
|
||||
return
|
||||
}
|
||||
log.Printf("%T - %#v", response, response)
|
||||
if strings.Contains(response, "Server received, But no response!!") {
|
||||
_, _ = ctx.Session.ChannelMessageEdit(ctx.Channel.ID, msg.ID,
|
||||
fmt.Sprintf("**%s Broadcast Successful**", server.Name),
|
||||
)
|
||||
return
|
||||
}
|
||||
_, _ = ctx.Session.ChannelMessageEdit(ctx.Channel.ID, msg.ID,
|
||||
fmt.Sprintf("**Broadcasting to %s Failed!**", server.Name),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package guild
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/dustinpianalto/disgoman"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/discord_utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/services"
|
||||
)
|
||||
|
||||
var AddPrefixCommand = &disgoman.Command{
|
||||
Name: "addPrefix",
|
||||
Aliases: []string{"ap"},
|
||||
Description: "Add a prefix for use in this guild.",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: disgoman.PermissionManageServer,
|
||||
Invoke: addPrefixCommandFunc,
|
||||
}
|
||||
|
||||
func addPrefixCommandFunc(ctx disgoman.Context, args []string) {
|
||||
if len(args) == 0 {
|
||||
discord_utils.SendErrorMessage(ctx, "Please include at least one prefix to add", nil)
|
||||
return
|
||||
}
|
||||
guild, err := services.GuildService.Guild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Guild not configured, adding new guild to the database", nil)
|
||||
guild = geeksbot.Guild{
|
||||
ID: ctx.Guild.ID,
|
||||
Prefixes: args,
|
||||
}
|
||||
guild, err = services.GuildService.CreateGuild(guild)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error adding guild to database.", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
guild.Prefixes = append(guild.Prefixes, args...)
|
||||
guild.Prefixes = utils.RemoveDuplicateStrings(guild.Prefixes)
|
||||
guild, err = services.GuildService.UpdateGuild(guild)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error adding prefixes to guild.", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
_, err = ctx.Send(fmt.Sprintf("Prefixes Updates.\nThe Prefixes for this guild are currently %#v", guild.Prefixes))
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error sending update message", err)
|
||||
}
|
||||
}
|
||||
|
||||
var RemovePrefixCommand = &disgoman.Command{
|
||||
Name: "removePrefix",
|
||||
Aliases: []string{"rp"},
|
||||
Description: "Remove a prefix so it can't be used in this guild",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: disgoman.PermissionManageServer,
|
||||
Invoke: removePrefixCommandFunc,
|
||||
}
|
||||
|
||||
func removePrefixCommandFunc(ctx disgoman.Context, args []string) {
|
||||
if len(args) == 0 {
|
||||
discord_utils.SendErrorMessage(ctx, "Please include at least one prefix to remove", nil)
|
||||
return
|
||||
}
|
||||
guild, err := services.GuildService.Guild(ctx.Guild.ID)
|
||||
var removed []string
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Guild not configured, adding new guild to the database", nil)
|
||||
guild = geeksbot.Guild{
|
||||
ID: ctx.Guild.ID,
|
||||
Prefixes: []string{},
|
||||
}
|
||||
guild, err = services.GuildService.CreateGuild(guild)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error adding guild to database.", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
for _, a := range args {
|
||||
l := len(guild.Prefixes)
|
||||
for i := 0; i < l; i++ {
|
||||
if a == guild.Prefixes[i] {
|
||||
guild.Prefixes = append(guild.Prefixes[:i], guild.Prefixes[i+1:]...)
|
||||
l--
|
||||
i--
|
||||
removed = append(removed, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
removed = utils.RemoveDuplicateStrings(removed)
|
||||
guild.Prefixes = utils.RemoveDuplicateStrings(guild.Prefixes)
|
||||
guild, err = services.GuildService.UpdateGuild(guild)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error removing prefixes from guild.", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
_, err = ctx.Send(fmt.Sprintf("Prefixes Updates.\n"+
|
||||
"The Prefixes for this guild are currently %#v\n"+
|
||||
"Removed: %#v", guild.Prefixes, removed))
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error sending update message", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
package guild
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/dustinpianalto/discordgo"
|
||||
"github.com/dustinpianalto/disgoman"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/discord_utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/services"
|
||||
)
|
||||
|
||||
var AddModeratorRoleCommand = &disgoman.Command{
|
||||
Name: "addMod",
|
||||
Aliases: []string{"addModerator", "addModRole"},
|
||||
Description: "Add a role which is allowed to run moderator commands",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: disgoman.PermissionManageServer,
|
||||
Invoke: addModeratorRoleCommandFunc,
|
||||
}
|
||||
|
||||
func addModeratorRoleCommandFunc(ctx disgoman.Context, args []string) {
|
||||
var count int
|
||||
added := make(map[string]bool)
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Something went wrong getting the guild", err)
|
||||
return
|
||||
}
|
||||
roles := append(args, ctx.Message.MentionRoles...)
|
||||
if len(roles) > 0 {
|
||||
for _, id := range roles {
|
||||
if strings.HasPrefix(id, "<@&") && strings.HasSuffix(id, ">") {
|
||||
continue
|
||||
}
|
||||
if _, ok := added[id]; ok {
|
||||
continue
|
||||
}
|
||||
if _, err = ctx.Session.State.Role(ctx.Guild.ID, id); err != nil {
|
||||
_, _ = ctx.Send(fmt.Sprintf("%s does not reference a valid role for this guild.", id))
|
||||
continue
|
||||
}
|
||||
_, err := services.GuildService.CreateOrUpdateRole(geeksbot.Role{
|
||||
ID: id,
|
||||
RoleType: "moderator",
|
||||
Guild: guild,
|
||||
})
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("There was a problem adding <@&%s>", id), err)
|
||||
continue
|
||||
}
|
||||
added[id] = true
|
||||
count++
|
||||
_, _ = ctx.Send(fmt.Sprintf("Added <@&%s> as a moderator role.", id))
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("Added %d moderator %s.", count, utils.PluralizeString("role", count)))
|
||||
} else {
|
||||
_, _ = ctx.Send("Please include at least one role to make a moderator role.")
|
||||
}
|
||||
}
|
||||
|
||||
var AddAdminRoleCommand = &disgoman.Command{
|
||||
Name: "addAdmin",
|
||||
Aliases: []string{"addAdminRole"},
|
||||
Description: "Add a role which is allowed to run admin commands",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: disgoman.PermissionManageServer,
|
||||
Invoke: addAdminRoleCommandFunc,
|
||||
}
|
||||
|
||||
func addAdminRoleCommandFunc(ctx disgoman.Context, args []string) {
|
||||
var count int
|
||||
added := make(map[string]bool)
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Something went wrong getting the guild", err)
|
||||
return
|
||||
}
|
||||
roles := append(args, ctx.Message.MentionRoles...)
|
||||
if len(roles) > 0 {
|
||||
for _, id := range roles {
|
||||
if strings.HasPrefix(id, "<@&") && strings.HasSuffix(id, ">") {
|
||||
continue
|
||||
}
|
||||
if _, ok := added[id]; ok {
|
||||
continue
|
||||
}
|
||||
if _, err = ctx.Session.State.Role(ctx.Guild.ID, id); err != nil {
|
||||
_, _ = ctx.Send(fmt.Sprintf("%s does not reference a valid role for this guild.", id))
|
||||
continue
|
||||
}
|
||||
_, err := services.GuildService.CreateOrUpdateRole(geeksbot.Role{
|
||||
ID: id,
|
||||
RoleType: "admin",
|
||||
Guild: guild,
|
||||
})
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("There was a problem adding <@&%s>", id), err)
|
||||
continue
|
||||
}
|
||||
added[id] = true
|
||||
count++
|
||||
_, _ = ctx.Send(fmt.Sprintf("Added <@&%s> as an admin role.", id))
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("Added %d admin %s.", count, utils.PluralizeString("role", count)))
|
||||
} else {
|
||||
_, _ = ctx.Send("Please include at least one role to make an admin role.")
|
||||
}
|
||||
}
|
||||
|
||||
var RemoveModRoleCommand = &disgoman.Command{
|
||||
Name: "removeMod",
|
||||
Aliases: []string{"removeModeratorRole", "removeModRole", "removeAdmin", "removeAdminRole"},
|
||||
Description: "Remove a role or several roles from the moderator or admin list",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: disgoman.PermissionManageServer,
|
||||
Invoke: removeModRoleCommandFunc,
|
||||
}
|
||||
|
||||
func removeModRoleCommandFunc(ctx disgoman.Context, args []string) {
|
||||
var count int
|
||||
added := make(map[string]bool)
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Something went wrong getting the guild", err)
|
||||
return
|
||||
}
|
||||
roles := append(args, ctx.Message.MentionRoles...)
|
||||
if len(roles) > 0 {
|
||||
for _, id := range roles {
|
||||
if strings.HasPrefix(id, "<@&") && strings.HasSuffix(id, ">") {
|
||||
continue
|
||||
}
|
||||
if _, ok := added[id]; ok {
|
||||
continue
|
||||
}
|
||||
if _, err = ctx.Session.State.Role(ctx.Guild.ID, id); err != nil {
|
||||
if r, err := services.GuildService.Role(id); err != nil {
|
||||
_, _ = ctx.Send(fmt.Sprintf("%s does not reference a valid role for this guild.", id))
|
||||
continue
|
||||
} else {
|
||||
err = services.GuildService.DeleteRole(r)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Something went wrong deleting the role", err)
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("Deleted <@&%s> as a no longer a valid role.", id))
|
||||
continue
|
||||
}
|
||||
}
|
||||
_, err := services.GuildService.CreateOrUpdateRole(geeksbot.Role{
|
||||
ID: id,
|
||||
RoleType: "normal",
|
||||
Guild: guild,
|
||||
})
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("There was a problem updating <@&%s>", id), err)
|
||||
continue
|
||||
}
|
||||
added[id] = true
|
||||
count++
|
||||
_, _ = ctx.Send(fmt.Sprintf("Set <@&%s> as a normal role.", id))
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("Set %d %s to normal.", count, utils.PluralizeString("role", count)))
|
||||
} else {
|
||||
_, _ = ctx.Send("Please include at least one role to remove from the moderator or admin lists.")
|
||||
}
|
||||
}
|
||||
|
||||
var MakeRoleSelfAssignableCommand = &disgoman.Command{
|
||||
Name: "make-role-self-assignable",
|
||||
Aliases: []string{"makesar", "addsar"},
|
||||
Description: "Makes the passed in role self assignable by anyone",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: disgoman.PermissionManageServer,
|
||||
Invoke: makeRoleSelfAssignableCommandFunc,
|
||||
}
|
||||
|
||||
func makeRoleSelfAssignableCommandFunc(ctx disgoman.Context, args []string) {
|
||||
added := make(map[string]bool)
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Something went wrong getting the guild", err)
|
||||
return
|
||||
}
|
||||
|
||||
roles := append(args, ctx.Message.MentionRoles...)
|
||||
if len(roles) > 0 {
|
||||
for _, id := range roles {
|
||||
if strings.HasPrefix(id, "<@&") && strings.HasSuffix(id, ">") {
|
||||
continue
|
||||
}
|
||||
if _, ok := added[id]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
var role *discordgo.Role
|
||||
var err error
|
||||
if role, err = ctx.Session.State.Role(ctx.Guild.ID, id); err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%s does not reference a valid role for this guild", id), err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = services.GuildService.CreateOrUpdateRole(geeksbot.Role{
|
||||
ID: role.ID,
|
||||
RoleType: "sar",
|
||||
Guild: guild,
|
||||
})
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("There was a problem updating <@&%s>", role.ID), err)
|
||||
return
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("%s is now self assignable", role.Name))
|
||||
|
||||
}
|
||||
} else {
|
||||
_, _ = ctx.Send("Please include at least one role to make self assignable")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var RemoveSelfAssignableCommand = &disgoman.Command{
|
||||
Name: "remove-self-assignable-role",
|
||||
Aliases: []string{"removesar"},
|
||||
Description: "Makes a role that was previously self assignable not so",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: disgoman.PermissionManageServer,
|
||||
Invoke: removeSelfAssignableRoleCommandFunc,
|
||||
}
|
||||
|
||||
func removeSelfAssignableRoleCommandFunc(ctx disgoman.Context, args []string) {
|
||||
removed := make(map[string]bool)
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Something went wrong getting the guild", err)
|
||||
return
|
||||
}
|
||||
|
||||
roles := append(args, ctx.Message.MentionRoles...)
|
||||
if len(roles) > 0 {
|
||||
for _, id := range roles {
|
||||
if strings.HasPrefix(id, "<@&") && strings.HasSuffix(id, ">") {
|
||||
continue
|
||||
}
|
||||
if _, ok := removed[id]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
var err error
|
||||
var role *discordgo.Role
|
||||
if role, err = ctx.Session.State.Role(ctx.Guild.ID, id); err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%s does not reference a valid role for this guild", id), err)
|
||||
return
|
||||
}
|
||||
_, err = services.GuildService.CreateOrUpdateRole(geeksbot.Role{
|
||||
ID: role.ID,
|
||||
RoleType: "normal",
|
||||
Guild: guild,
|
||||
})
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("There was a problem updating <@&%s>", role.ID), err)
|
||||
return
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("%s's self assignability has been removed.", role.Name))
|
||||
}
|
||||
} else {
|
||||
_, _ = ctx.Send("Please include at least one role to make self assignable")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var SelfAssignRoleCommand = &disgoman.Command{
|
||||
Name: "giverole",
|
||||
Aliases: []string{"iwant", "givetome", "addrole"},
|
||||
Description: "Assigns a person the passed in role if it is self assignable",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: selfAssignRoleCommandFunc,
|
||||
}
|
||||
|
||||
func selfAssignRoleCommandFunc(ctx disgoman.Context, args []string) {
|
||||
added := make(map[string]bool)
|
||||
roles := append(args, ctx.Message.MentionRoles...)
|
||||
if len(roles) > 0 {
|
||||
for _, id := range roles {
|
||||
var roleID string
|
||||
if strings.HasPrefix(id, "<@&") && strings.HasSuffix(id, ">") {
|
||||
continue
|
||||
} else if _, err := strconv.Atoi(id); err == nil {
|
||||
roleID = id
|
||||
} else {
|
||||
for _, role := range ctx.Guild.Roles {
|
||||
if strings.ToLower(id) == strings.ToLower(role.Name) {
|
||||
roleID = role.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := added[id]; ok {
|
||||
continue
|
||||
}
|
||||
var role *discordgo.Role
|
||||
var err error
|
||||
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%s does not reference a valid role for this guild", roleID), err)
|
||||
return
|
||||
}
|
||||
if memberHasRole(ctx.Member, role.ID) {
|
||||
_, _ = ctx.Send(fmt.Sprintf("You already have the %s role silly...", role.Name))
|
||||
return
|
||||
}
|
||||
r, err := services.GuildService.Role(role.ID)
|
||||
if err != nil || r.RoleType != "sar" {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("You aren't allowed to assign yourself the %s role", role.Name), err)
|
||||
return
|
||||
}
|
||||
err = ctx.Session.GuildMemberRoleAdd(ctx.Guild.ID, ctx.User.ID, role.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "There was a problem adding that role to you.", err)
|
||||
return
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("Congratulations! The %s role has been added to your... Ummm... Thing.", role.Name))
|
||||
}
|
||||
} else {
|
||||
_, _ = ctx.Send("Please include at least one role to make self assignable")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var UnAssignRoleCommand = &disgoman.Command{
|
||||
Name: "removerole",
|
||||
Aliases: []string{"idon'twant"},
|
||||
Description: "Removes a role from a person if the role is self assignable",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: unAssignRoleCommandFunc,
|
||||
}
|
||||
|
||||
func unAssignRoleCommandFunc(ctx disgoman.Context, args []string) {
|
||||
removed := make(map[string]bool)
|
||||
roles := append(args, ctx.Message.MentionRoles...)
|
||||
if len(roles) > 0 {
|
||||
for _, id := range roles {
|
||||
var roleID string
|
||||
if strings.HasPrefix(id, "<@&") && strings.HasSuffix(id, ">") {
|
||||
continue
|
||||
} else if _, err := strconv.Atoi(id); err == nil {
|
||||
roleID = id
|
||||
} else {
|
||||
for _, role := range ctx.Guild.Roles {
|
||||
if strings.ToLower(id) == strings.ToLower(role.Name) {
|
||||
roleID = role.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := removed[id]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
var role *discordgo.Role
|
||||
var err error
|
||||
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%s does not reference a valid role for this guild", roleID), err)
|
||||
return
|
||||
}
|
||||
if !memberHasRole(ctx.Member, role.ID) {
|
||||
_, _ = ctx.Send(fmt.Sprintf("I can't remove the %s role from you because you don't have it...", role.Name))
|
||||
return
|
||||
}
|
||||
r, err := services.GuildService.Role(role.ID)
|
||||
if err != nil || r.RoleType != "sar" {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("You aren't allowed to assign yourself the %s role", role.Name), err)
|
||||
return
|
||||
}
|
||||
err = ctx.Session.GuildMemberRoleRemove(ctx.Guild.ID, ctx.User.ID, role.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "There was a problem removing that role from your account", err)
|
||||
return
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("Sad to see you go... but the %s role has been removed.", role.Name))
|
||||
}
|
||||
} else {
|
||||
_, _ = ctx.Send("Please include at least one role to make self assignable")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func memberHasRole(m *discordgo.Member, id string) bool {
|
||||
for _, r := range m.Roles {
|
||||
if r == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
+27
-7
@@ -2,10 +2,13 @@ package exts
|
||||
|
||||
import (
|
||||
"github.com/dustinpianalto/disgoman"
|
||||
"github.com/dustinpianalto/geeksbot/internal/exts/utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/exts/arcon"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/exts/guild"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/exts/requests"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/exts/utils"
|
||||
)
|
||||
|
||||
func AddCommandHandlers(h *disgoman.CommandManager) {
|
||||
func AddCommandHandlers(g *disgoman.CommandManager) {
|
||||
// Arguments:
|
||||
// name - command name - string
|
||||
// desc - command description - string
|
||||
@@ -14,9 +17,26 @@ func AddCommandHandlers(h *disgoman.CommandManager) {
|
||||
// perms - permissisions required - anpan.Permission (int)
|
||||
// type - command type, sets where the command is available
|
||||
// run - function to run - func(anpan.Context, []string) / CommandRunFunc
|
||||
_ = h.AddCommand(utils.UserCommand)
|
||||
_ = h.AddCommand(utils.SayCommand)
|
||||
_ = h.AddCommand(utils.GitCommand)
|
||||
_ = h.AddCommand(utils.InviteCommand)
|
||||
_ = h.AddCommand(utils.PingCommand)
|
||||
_ = g.AddCommand(utils.UserCommand)
|
||||
_ = g.AddCommand(utils.AddUserCommand)
|
||||
_ = g.AddCommand(utils.SayCommand)
|
||||
_ = g.AddCommand(utils.GitCommand)
|
||||
_ = g.AddCommand(utils.InviteCommand)
|
||||
_ = g.AddCommand(utils.PingCommand)
|
||||
_ = g.AddCommand(guild.AddPrefixCommand)
|
||||
_ = g.AddCommand(guild.RemovePrefixCommand)
|
||||
_ = g.AddCommand(guild.AddModeratorRoleCommand)
|
||||
_ = g.AddCommand(guild.AddAdminRoleCommand)
|
||||
_ = g.AddCommand(guild.RemoveModRoleCommand)
|
||||
_ = g.AddCommand(guild.MakeRoleSelfAssignableCommand)
|
||||
_ = g.AddCommand(guild.RemoveSelfAssignableCommand)
|
||||
_ = g.AddCommand(guild.SelfAssignRoleCommand)
|
||||
_ = g.AddCommand(guild.UnAssignRoleCommand)
|
||||
_ = g.AddCommand(requests.RequestCommand)
|
||||
_ = g.AddCommand(requests.CloseCommand)
|
||||
_ = g.AddCommand(requests.ListCommand)
|
||||
_ = g.AddCommand(requests.ViewCommand)
|
||||
_ = g.AddCommand(requests.CommentCommand)
|
||||
_ = g.AddCommand(arcon.ListplayersCommand)
|
||||
_ = g.AddCommand(arcon.BroadcastCommand)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,449 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dustinpianalto/disgoman"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/discord_utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/services"
|
||||
)
|
||||
|
||||
var RequestCommand = &disgoman.Command{
|
||||
Name: "request",
|
||||
Aliases: nil,
|
||||
Description: "Submit a request for the guild staff",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: requestCommandFunc,
|
||||
}
|
||||
|
||||
func requestCommandFunc(ctx disgoman.Context, args []string) {
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error getting Guild from the database", err)
|
||||
return
|
||||
}
|
||||
requestMsg := strings.Join(args, " ")
|
||||
author, err := services.UserService.GetOrCreateUser(ctx.Message.Author.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error creating the request. Could not get user.", err)
|
||||
return
|
||||
}
|
||||
channel, err := services.ChannelService.GetOrCreateChannel(ctx.Message.ChannelID, ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error creating the request. Could not get channel.", err)
|
||||
return
|
||||
}
|
||||
int64ID, _ := strconv.ParseInt(ctx.Message.ID, 10, 64)
|
||||
s := discord_utils.ParseSnowflake(int64ID)
|
||||
message, err := services.MessageService.CreateMessage(geeksbot.Message{
|
||||
ID: ctx.Message.ID,
|
||||
CreatedAt: s.CreationTime,
|
||||
Content: ctx.Message.Content,
|
||||
Channel: channel,
|
||||
Author: author,
|
||||
})
|
||||
request := geeksbot.Request{
|
||||
Author: author,
|
||||
Channel: channel,
|
||||
Guild: guild,
|
||||
Content: requestMsg,
|
||||
RequestedAt: s.CreationTime,
|
||||
Completed: false,
|
||||
Message: message,
|
||||
}
|
||||
request, err = services.RequestService.CreateRequest(request)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error creating the request", err)
|
||||
return
|
||||
}
|
||||
channels, err := services.ChannelService.GuildChannels(guild)
|
||||
if err == nil {
|
||||
var mentionRolesString string
|
||||
roles, err := services.GuildService.GuildRoles(guild)
|
||||
if err == nil {
|
||||
for _, r := range roles {
|
||||
if r.RoleType == "admin" || r.RoleType == "moderator" {
|
||||
mentionRolesString += fmt.Sprintf("<@&%s> ", r.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, c := range channels {
|
||||
if c.Admin {
|
||||
_, _ = ctx.Session.ChannelMessageSend(c.ID,
|
||||
fmt.Sprintf("%s\n"+
|
||||
"New Request ID %d\n"+
|
||||
"%s has requested assistance: \n"+
|
||||
"```\n%s\n```\n"+
|
||||
"Requested At: %s\n"+
|
||||
"In: %s",
|
||||
mentionRolesString,
|
||||
request.ID,
|
||||
ctx.Message.Author.Mention(),
|
||||
request.Content,
|
||||
request.RequestedAt.UTC().Format(time.UnixDate),
|
||||
ctx.Channel.Mention(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err = ctx.Send(fmt.Sprintf("%s The admin have recieved your request.\n "+
|
||||
"If you would like to close or add a comment to this request please reference ID `%v`",
|
||||
ctx.Message.Author.Mention(), request.ID,
|
||||
))
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "There was an error sending the message. The request was created.", err)
|
||||
}
|
||||
}
|
||||
|
||||
var CloseCommand = &disgoman.Command{
|
||||
Name: "close",
|
||||
Aliases: nil,
|
||||
Description: "Close a request and mark it as completed.",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: closeCommandFunc,
|
||||
}
|
||||
|
||||
func closeCommandFunc(ctx disgoman.Context, args []string) {
|
||||
var ids []int64
|
||||
var reason string
|
||||
_, err := strconv.ParseInt(args[len(args)-1], 10, 64)
|
||||
if err != nil {
|
||||
reason = args[len(args)-1]
|
||||
args = args[0 : len(args)-1]
|
||||
}
|
||||
for _, a := range args {
|
||||
a = strings.Trim(a, ",")
|
||||
id, err := strconv.ParseInt(a, 10, 64)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%s is not a valid request id", a), err)
|
||||
continue
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
discord_utils.SendErrorMessage(ctx, "No requests to close", nil)
|
||||
return
|
||||
}
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error getting Guild from the database", err)
|
||||
return
|
||||
}
|
||||
closer, err := services.UserService.GetOrCreateUser(ctx.Message.Author.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error closing the request. Could not get user.", err)
|
||||
return
|
||||
}
|
||||
int64ID, _ := strconv.ParseInt(ctx.Message.ID, 10, 64)
|
||||
s := discord_utils.ParseSnowflake(int64ID)
|
||||
for _, id := range ids {
|
||||
request, err := services.RequestService.Request(id)
|
||||
if err != nil || request.Guild.ID != guild.ID {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%d is not a request in this guild.", id), err)
|
||||
continue
|
||||
}
|
||||
if request.Author != closer && !closer.IsStaff && !closer.IsAdmin {
|
||||
if !discord_utils.IsGuildMod(ctx, closer) && !discord_utils.IsGuildAdmin(ctx, closer) {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("You are not authorized to close %d", id), nil)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if request.Completed {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%d is already closed", id), err)
|
||||
continue
|
||||
}
|
||||
request.Completed = true
|
||||
request.CompletedAt.Valid = true
|
||||
request.CompletedAt.Time = s.CreationTime
|
||||
request.CompletedBy = &closer
|
||||
if reason != "" {
|
||||
request.CompletedMessage.Valid = true
|
||||
request.CompletedMessage.String = reason
|
||||
}
|
||||
request, err = services.RequestService.UpdateRequest(request)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("Error closing %d", id), err)
|
||||
continue
|
||||
}
|
||||
_, err = ctx.Send(fmt.Sprintf("%d has been closed", request.ID))
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "There was an error sending the message. The request was closed.", err)
|
||||
}
|
||||
dmChannel, err := ctx.Session.UserChannelCreate(request.Author.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, _ = ctx.Session.ChannelMessageSend(dmChannel.ID,
|
||||
fmt.Sprintf("%s has closed request %d which you opened in the %s channel.\n```%s```\n",
|
||||
discord_utils.GetDisplayName(ctx, request.CompletedBy.ID),
|
||||
request.ID,
|
||||
discord_utils.GetChannelName(ctx, request.Channel.ID),
|
||||
request.Content,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
var ListCommand = &disgoman.Command{
|
||||
Name: "list",
|
||||
Aliases: []string{"request_list", "requests_list"},
|
||||
Description: "List your open requests or all open requests if the caller is a moderator",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: listCommandFunc,
|
||||
}
|
||||
|
||||
func listCommandFunc(ctx disgoman.Context, args []string) {
|
||||
user, err := services.UserService.GetOrCreateUser(ctx.Message.Author.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error closing the request. Could not get user.", err)
|
||||
return
|
||||
}
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error getting Guild from the database", err)
|
||||
return
|
||||
}
|
||||
|
||||
var requests []geeksbot.Request
|
||||
if discord_utils.IsGuildMod(ctx, user) || discord_utils.IsGuildAdmin(ctx, user) {
|
||||
requests, err = services.RequestService.GuildRequests(guild, false)
|
||||
} else {
|
||||
requests, err = services.RequestService.UserRequests(user, false)
|
||||
}
|
||||
|
||||
for _, request := range requests {
|
||||
var authorName string
|
||||
author, err := ctx.Session.GuildMember(guild.ID, request.Author.ID)
|
||||
if err != nil {
|
||||
authorName = "Unknown"
|
||||
} else {
|
||||
if author.Nick == "" {
|
||||
authorName = author.User.Username
|
||||
} else {
|
||||
authorName = author.Nick
|
||||
}
|
||||
}
|
||||
|
||||
var channelName string
|
||||
channel, err := ctx.Session.Channel(request.Channel.ID)
|
||||
if err != nil {
|
||||
channelName = "Unknown"
|
||||
} else {
|
||||
channelName = channel.Name
|
||||
}
|
||||
commentCount, err := services.RequestService.RequestCommentCount(request)
|
||||
if err != nil {
|
||||
commentCount = 0
|
||||
}
|
||||
_, _ = ctx.Send(fmt.Sprintf("```md\n"+
|
||||
"< Request ID Requested By >\n"+
|
||||
"< %-11d %23s >\n"+
|
||||
"%s\n\n"+
|
||||
"Comments: %d\n"+
|
||||
"Requested At: %s\n"+
|
||||
"In: %s\n"+
|
||||
"```",
|
||||
request.ID,
|
||||
authorName,
|
||||
request.Content,
|
||||
commentCount,
|
||||
request.RequestedAt.Format("2006-01-02 15:04:05 MST"),
|
||||
channelName,
|
||||
))
|
||||
}
|
||||
|
||||
_, _ = ctx.Send(fmt.Sprintf("```There %s currently %d open %s```", utils.PluralizeString("is", len(requests)), len(requests), utils.PluralizeString("request", len(requests))))
|
||||
}
|
||||
|
||||
var CommentCommand = &disgoman.Command{
|
||||
Name: "comment",
|
||||
Aliases: []string{"update", "add_comment"},
|
||||
Description: "Add a comment to an existing request.",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: commentCommandFunc,
|
||||
}
|
||||
|
||||
func commentCommandFunc(ctx disgoman.Context, args []string) {
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error getting Guild from the database", err)
|
||||
return
|
||||
}
|
||||
id, err := strconv.ParseInt(args[0], 10, 64)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Please include the ID of the request to update.", err)
|
||||
return
|
||||
}
|
||||
message := strings.Join(args[1:len(args)], " ")
|
||||
author, err := services.UserService.GetOrCreateUser(ctx.Message.Author.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Sorry, there was an issue finding your user account", err)
|
||||
return
|
||||
}
|
||||
request, err := services.RequestService.Request(id)
|
||||
if err != nil || request.Guild.ID != guild.ID {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%d is not a valid request for this guild", id), err)
|
||||
return
|
||||
}
|
||||
int64ID, _ := strconv.ParseInt(ctx.Message.ID, 10, 64)
|
||||
s := discord_utils.ParseSnowflake(int64ID)
|
||||
comment := geeksbot.Comment{
|
||||
Author: author,
|
||||
Request: request,
|
||||
CommentAt: s.CreationTime,
|
||||
Content: message,
|
||||
}
|
||||
comment, err = services.RequestService.CreateComment(comment)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "There was a problem adding your comment", err)
|
||||
return
|
||||
}
|
||||
channels, err := services.ChannelService.GuildChannels(guild)
|
||||
if err == nil {
|
||||
comments, _ := services.RequestService.RequestComments(request)
|
||||
var commentString string
|
||||
var commentStrings []string
|
||||
commentString = fmt.Sprintf("Comment added:\n```md\n"+
|
||||
"< Request ID Requested By >\n"+
|
||||
"< %-11d %23s >\n"+
|
||||
"%s\n\n"+
|
||||
"Comments: Not Implemented Yet\n"+
|
||||
"Requested At: %s\n"+
|
||||
"In: %s\n"+
|
||||
"```",
|
||||
request.ID,
|
||||
discord_utils.GetDisplayName(ctx, request.Author.ID),
|
||||
request.Content,
|
||||
request.RequestedAt.Format("2006-01-02 15:04:05"),
|
||||
discord_utils.GetChannelName(ctx, request.Channel.ID),
|
||||
)
|
||||
for _, c := range comments {
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
cs := fmt.Sprintf("```md\n%s\n- %s At %s\n```\n",
|
||||
c.Content,
|
||||
discord_utils.GetDisplayName(ctx, c.Author.ID),
|
||||
c.CommentAt.Format("2006-01-02 15:04:05"),
|
||||
)
|
||||
if len(commentString+cs) >= 2000 {
|
||||
commentStrings = append(commentStrings, commentString)
|
||||
commentString = ""
|
||||
}
|
||||
commentString += cs
|
||||
}
|
||||
commentStrings = append(commentStrings, commentString)
|
||||
for _, c := range channels {
|
||||
if c.Admin {
|
||||
for _, s := range commentStrings {
|
||||
_, _ = ctx.Session.ChannelMessageSend(c.ID, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Println(err)
|
||||
}
|
||||
_, err = ctx.Send(fmt.Sprintf("%s your comment has been added.", ctx.Message.Author.Mention()))
|
||||
dmChannel, err := ctx.Session.UserChannelCreate(request.Author.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, _ = ctx.Session.ChannelMessageSend(dmChannel.ID,
|
||||
fmt.Sprintf("%s has add a comment to request %d which you opened in the %s channel.\n```%s```\n```%s```",
|
||||
discord_utils.GetDisplayName(ctx, author.ID),
|
||||
request.ID,
|
||||
discord_utils.GetChannelName(ctx, ctx.Channel.ID),
|
||||
request.Content,
|
||||
message,
|
||||
))
|
||||
|
||||
}
|
||||
|
||||
var ViewCommand = &disgoman.Command{
|
||||
Name: "view",
|
||||
Aliases: nil,
|
||||
Description: "View the details about a request.",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: viewCommandFunc,
|
||||
}
|
||||
|
||||
func viewCommandFunc(ctx disgoman.Context, args []string) {
|
||||
guild, err := services.GuildService.GetOrCreateGuild(ctx.Guild.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Error getting Guild from the database", err)
|
||||
return
|
||||
}
|
||||
id, err := strconv.ParseInt(args[0], 10, 64)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Please include the ID of the request to view.", err)
|
||||
return
|
||||
}
|
||||
request, err := services.RequestService.Request(id)
|
||||
if err != nil || request.Guild.ID != guild.ID {
|
||||
discord_utils.SendErrorMessage(ctx, fmt.Sprintf("%d is not a valid request in this guild", id), err)
|
||||
return
|
||||
}
|
||||
requestor, err := services.UserService.GetOrCreateUser(ctx.Message.Author.ID)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "Sorry, there was an issue finding your user account", err)
|
||||
return
|
||||
}
|
||||
if request.Author.ID != ctx.Message.Author.ID &&
|
||||
!discord_utils.IsGuildMod(ctx, requestor) &&
|
||||
!discord_utils.IsGuildAdmin(ctx, requestor) {
|
||||
discord_utils.SendErrorMessage(ctx, "You are not authorized to view that request", nil)
|
||||
return
|
||||
}
|
||||
comments, err := services.RequestService.RequestComments(request)
|
||||
if err != nil {
|
||||
discord_utils.SendErrorMessage(ctx, "There was an error getting the comments.", err)
|
||||
}
|
||||
var commentString string
|
||||
var commentStrings []string
|
||||
commentString = fmt.Sprintf("```md\n"+
|
||||
"< Request ID Requested By >\n"+
|
||||
"< %-11d %23s >\n"+
|
||||
"%s\n\n"+
|
||||
"Requested At: %s\n"+
|
||||
"In: %s\n"+
|
||||
"```",
|
||||
request.ID,
|
||||
discord_utils.GetDisplayName(ctx, request.Author.ID),
|
||||
request.Content,
|
||||
request.RequestedAt.Format("2006-01-02 15:04:05"),
|
||||
discord_utils.GetChannelName(ctx, request.Channel.ID),
|
||||
)
|
||||
for _, c := range comments {
|
||||
cs := fmt.Sprintf("```md\n%s\n- %s At %s\n```\n",
|
||||
c.Content,
|
||||
discord_utils.GetDisplayName(ctx, c.Author.ID),
|
||||
c.CommentAt.Format("2006-01-02 15:04:05"),
|
||||
)
|
||||
if len(commentString+cs) >= 2000 {
|
||||
commentStrings = append(commentStrings, commentString)
|
||||
commentString = ""
|
||||
}
|
||||
commentString += cs
|
||||
}
|
||||
commentStrings = append(commentStrings, commentString)
|
||||
for _, c := range commentStrings {
|
||||
_, _ = ctx.Send(c)
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/dustinpianalto/discordgo"
|
||||
"github.com/dustinpianalto/disgoman"
|
||||
"github.com/dustinpianalto/geeksbot/internal/discord_utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/internal/discord_utils"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/services"
|
||||
)
|
||||
|
||||
var PingCommand = &disgoman.Command{
|
||||
@@ -108,9 +110,9 @@ var GitCommand = &disgoman.Command{
|
||||
|
||||
func gitCommandFunc(ctx disgoman.Context, _ []string) {
|
||||
embed := &discordgo.MessageEmbed{
|
||||
Title: "Hi there, My code is on Github",
|
||||
Title: "Hi there, my code is on Gitea",
|
||||
Color: 0,
|
||||
URL: "https://github.com/dustinpianalto/Geeksbot",
|
||||
URL: "https://gitea.wayfinderak.com/wayfinderak/geeksbot",
|
||||
}
|
||||
_, err := ctx.Session.ChannelMessageSendEmbed(ctx.Channel.ID, embed)
|
||||
if err != nil {
|
||||
@@ -211,10 +213,9 @@ func userCommandFunc(ctx disgoman.Context, args []string) {
|
||||
Inline: false,
|
||||
}
|
||||
|
||||
guildJoinTime, _ := member.JoinedAt.Parse()
|
||||
guildJoinedField := &discordgo.MessageEmbedField{
|
||||
Name: "Joined Guild:",
|
||||
Value: discord_utils.ParseDateString(guildJoinTime),
|
||||
Value: discord_utils.ParseDateString(member.JoinedAt),
|
||||
Inline: false,
|
||||
}
|
||||
|
||||
@@ -246,3 +247,34 @@ func userCommandFunc(ctx disgoman.Context, args []string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var AddUserCommand = &disgoman.Command{
|
||||
Name: "adduser",
|
||||
Aliases: nil,
|
||||
Description: "Get user info",
|
||||
OwnerOnly: false,
|
||||
Hidden: false,
|
||||
RequiredPermissions: 0,
|
||||
Invoke: addUserCommandFunc,
|
||||
}
|
||||
|
||||
func addUserCommandFunc(ctx disgoman.Context, args []string) {
|
||||
if ctx.Message.Author.ID == ctx.CommandManager.Owners[0] {
|
||||
user := geeksbot.User{
|
||||
ID: ctx.Message.Author.ID,
|
||||
IsActive: true,
|
||||
IsStaff: true,
|
||||
IsAdmin: true,
|
||||
}
|
||||
user, err := services.UserService.CreateUser(user)
|
||||
if err != nil {
|
||||
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
|
||||
Context: ctx,
|
||||
Message: "Error with adding user",
|
||||
Error: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.Session.MessageReactionAdd(ctx.Channel.ID, ctx.Message.ID, "✅")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package utils
|
||||
|
||||
func RemoveDuplicateStrings(s []string) []string {
|
||||
keys := make(map[string]bool)
|
||||
o := []string{}
|
||||
|
||||
for _, e := range s {
|
||||
if _, v := keys[e]; !v {
|
||||
keys[e] = true
|
||||
o = append(o, e)
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func PluralizeString(s string, i int) string {
|
||||
if i == 1 {
|
||||
return s
|
||||
}
|
||||
if s == "is" {
|
||||
return "are"
|
||||
}
|
||||
return s + "s"
|
||||
}
|
||||
+13
-12
@@ -1,23 +1,24 @@
|
||||
package geeksbot
|
||||
|
||||
import "github.com/bwmarrin/discordgo"
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
ID string
|
||||
CreatedAt int64
|
||||
ModifiedAt int64
|
||||
CreatedAt time.Time
|
||||
ModifiedAt sql.NullTime
|
||||
Content string
|
||||
PreviousContent []string
|
||||
Channel *Channel
|
||||
Author *User
|
||||
Embed *discordgo.MessageEmbed
|
||||
PreviousEmbeds []*discordgo.MessageEmbed
|
||||
Channel Channel
|
||||
Author User
|
||||
}
|
||||
|
||||
type MessageService interface {
|
||||
Message(id string) (*Message, error)
|
||||
CreateMessage(m *Message) (*Message, error)
|
||||
DeleteMessage(m *Message) error
|
||||
ChannelMessages(c *Channel) ([]*Message, error)
|
||||
UpdateMessage(m *Message) (*Message, error)
|
||||
Message(id string) (Message, error)
|
||||
CreateMessage(m Message) (Message, error)
|
||||
DeleteMessage(m Message) error
|
||||
ChannelMessages(c Channel) ([]Message, error)
|
||||
UpdateMessage(m Message) (Message, error)
|
||||
}
|
||||
|
||||
+18
-15
@@ -1,31 +1,34 @@
|
||||
package geeksbot
|
||||
|
||||
import "database/sql"
|
||||
|
||||
type PatreonCreator struct {
|
||||
ID int
|
||||
Creator string
|
||||
Link string
|
||||
Guild *Guild
|
||||
Guild Guild
|
||||
}
|
||||
|
||||
type PatreonTier struct {
|
||||
ID int
|
||||
Name string
|
||||
Description string
|
||||
Creator *PatreonCreator
|
||||
Role *Role
|
||||
Description sql.NullString
|
||||
Creator PatreonCreator
|
||||
Role Role
|
||||
NextTier *PatreonTier
|
||||
}
|
||||
|
||||
type PatreonService interface {
|
||||
PatreonCreatorByID(id int) (*PatreonCreator, error)
|
||||
PatreonCreatorByName(name string) (*PatreonCreator, error)
|
||||
CreatePatreonCreator(c *PatreonCreator) (*PatreonCreator, error)
|
||||
UpdatePatreonCreator(c *PatreonCreator) (*PatreonCreator, error)
|
||||
DeletePatreonCreator(c *PatreonCreator) error
|
||||
PatreonTierByID(id int) (*PatreonTier, error)
|
||||
PatreonTierByName(name string) (*PatreonTier, error)
|
||||
CreatePatreonTier(t *PatreonTier) (*PatreonTier, error)
|
||||
UpdatePatreonTier(t *PatreonTier) (*PatreonTier, error)
|
||||
DeletePatreonTier(t *PatreonTier) error
|
||||
GuildPatreonCreators(g *Guild) ([]*PatreonCreator, error)
|
||||
PatreonCreatorByID(id int) (PatreonCreator, error)
|
||||
PatreonCreatorByName(name string, guild Guild) (PatreonCreator, error)
|
||||
CreatePatreonCreator(c PatreonCreator) (PatreonCreator, error)
|
||||
UpdatePatreonCreator(c PatreonCreator) (PatreonCreator, error)
|
||||
DeletePatreonCreator(c PatreonCreator) error
|
||||
PatreonTierByID(id int) (PatreonTier, error)
|
||||
PatreonTierByName(name string, creator string) (PatreonTier, error)
|
||||
CreatePatreonTier(t PatreonTier) (PatreonTier, error)
|
||||
UpdatePatreonTier(t PatreonTier) (PatreonTier, error)
|
||||
DeletePatreonTier(t PatreonTier) error
|
||||
GuildPatreonCreators(g Guild) ([]PatreonCreator, error)
|
||||
CreatorPatreonTiers(c PatreonCreator) ([]PatreonTier, error)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
)
|
||||
|
||||
type channelService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s channelService) Channel(id string) (geeksbot.Channel, error) {
|
||||
var channel geeksbot.Channel
|
||||
var guild_id string
|
||||
queryString := "SELECT id, guild_id, admin, default_channel, new_patron FROM channels WHERE id = $1"
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&channel.ID, &guild_id, &channel.Admin, &channel.Default, &channel.NewPatron)
|
||||
if err != nil {
|
||||
return geeksbot.Channel{}, err
|
||||
}
|
||||
guild, err := GuildService.Guild(guild_id)
|
||||
if err != nil {
|
||||
return geeksbot.Channel{}, err
|
||||
}
|
||||
channel.Guild = guild
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
func (s channelService) CreateChannel(c geeksbot.Channel) (geeksbot.Channel, error) {
|
||||
queryString := "INSERT INTO channels (id, guild_id, admin, default_channel, new_patron) VALUES ($1, $2, $3, $4, $5)"
|
||||
_, err := s.db.Exec(queryString, c.ID, c.Guild.ID, c.Admin, c.Default, c.NewPatron)
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (s channelService) DeleteChannel(c geeksbot.Channel) error {
|
||||
queryString := "DELETE FROM channels WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, c.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s channelService) UpdateChannel(c geeksbot.Channel) (geeksbot.Channel, error) {
|
||||
queryString := "UPDATE channels SET admin = $2, default_channel = $3, new_patron = $4 WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, c.ID, c.Admin, c.Default, c.NewPatron)
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (s channelService) GuildChannels(g geeksbot.Guild) ([]geeksbot.Channel, error) {
|
||||
var channels []geeksbot.Channel
|
||||
queryString := "SELECT id FROM channels WHERE guild_id = $1"
|
||||
rows, err := s.db.Query(queryString, g.ID)
|
||||
if err != nil {
|
||||
return channels, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id string
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
channel, err := s.Channel(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
channels = append(channels, channel)
|
||||
}
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
func (s channelService) GetOrCreateChannel(id string, guild_id string) (geeksbot.Channel, error) {
|
||||
channel, err := s.Channel(id)
|
||||
if err == sql.ErrNoRows {
|
||||
var guild geeksbot.Guild
|
||||
guild, err = GuildService.GetOrCreateGuild(guild_id)
|
||||
if err != nil {
|
||||
return geeksbot.Channel{}, err
|
||||
}
|
||||
channel, err = s.CreateChannel(geeksbot.Channel{
|
||||
ID: id,
|
||||
Guild: guild,
|
||||
Admin: false,
|
||||
Default: false,
|
||||
NewPatron: false,
|
||||
})
|
||||
}
|
||||
return channel, err
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/database/migrations"
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
"github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
bindata "github.com/golang-migrate/migrate/v4/source/go_bindata"
|
||||
)
|
||||
|
||||
var (
|
||||
db *sql.DB
|
||||
GuildService guildService
|
||||
UserService userService
|
||||
ChannelService channelService
|
||||
MessageService messageService
|
||||
RequestService requestService
|
||||
PatreonService patreonService
|
||||
ServerService serverService
|
||||
)
|
||||
|
||||
func ConnectDatabase(dbConnString string) {
|
||||
var err error
|
||||
db, err = sql.Open("postgres", dbConnString)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("can't connect to the database: %w", err))
|
||||
}
|
||||
|
||||
db.SetMaxOpenConns(5)
|
||||
db.SetMaxIdleConns(2)
|
||||
db.SetConnMaxLifetime(30 * time.Minute)
|
||||
db.SetConnMaxIdleTime(5 * time.Minute)
|
||||
|
||||
if err = db.Ping(); err != nil {
|
||||
log.Fatal(fmt.Errorf("can't ping the database: %w", err))
|
||||
}
|
||||
|
||||
log.Println("Database Connected.")
|
||||
initServices()
|
||||
log.Println("Services Initialized")
|
||||
}
|
||||
|
||||
func RunMigrations() {
|
||||
s := bindata.Resource(migrations.AssetNames(),
|
||||
func(name string) ([]byte, error) {
|
||||
return migrations.Asset(name)
|
||||
})
|
||||
d, err := bindata.WithInstance(s)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("cannot load migrations: %w", err))
|
||||
}
|
||||
instance, err := postgres.WithInstance(db, &postgres.Config{})
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("cannot create db driver: %w", err))
|
||||
}
|
||||
m, err := migrate.NewWithInstance("go-bindatafoo", d, "postgres", instance)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("cannot create migration instance: %w", err))
|
||||
}
|
||||
err = m.Up()
|
||||
if err != nil {
|
||||
if err.Error() == "no change" {
|
||||
log.Println(err)
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
log.Println("Migrations Run")
|
||||
|
||||
}
|
||||
|
||||
func initServices() {
|
||||
GuildService = guildService{db: db}
|
||||
UserService = userService{db: db}
|
||||
ChannelService = channelService{db: db}
|
||||
MessageService = messageService{db: db}
|
||||
PatreonService = patreonService{db: db}
|
||||
RequestService = requestService{db: db}
|
||||
ServerService = serverService{db: db}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
type guildService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s guildService) Guild(id string) (geeksbot.Guild, error) {
|
||||
var g geeksbot.Guild
|
||||
queryString := "SELECT id, new_patron_message, prefixes FROM guilds WHERE id = $1"
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&g.ID, &g.NewPatronMessage, pq.Array(&g.Prefixes))
|
||||
if err != nil {
|
||||
return geeksbot.Guild{}, err
|
||||
}
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (s guildService) CreateGuild(g geeksbot.Guild) (geeksbot.Guild, error) {
|
||||
queryString := "INSERT INTO guilds (id, new_patron_message, prefixes) VALUES ($1, $2, $3)"
|
||||
_, err := s.db.Exec(queryString, g.ID, g.NewPatronMessage, pq.Array(g.Prefixes))
|
||||
return g, err
|
||||
}
|
||||
|
||||
func (s guildService) DeleteGuild(g geeksbot.Guild) error {
|
||||
queryString := "DELETE FROM guilds WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, g.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s guildService) UpdateGuild(g geeksbot.Guild) (geeksbot.Guild, error) {
|
||||
queryString := "UPDATE guilds SET new_patron_message = $2, prefixes = $3 WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, g.ID, g.NewPatronMessage, pq.Array(g.Prefixes))
|
||||
return g, err
|
||||
}
|
||||
|
||||
func (s guildService) GuildRoles(g geeksbot.Guild) ([]geeksbot.Role, error) {
|
||||
var roles []geeksbot.Role
|
||||
queryString := "SELECT id FROM roles WHERE guild_id = $1"
|
||||
rows, err := s.db.Query(queryString, g.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id string
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
role, err := s.Role(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
roles = append(roles, role)
|
||||
}
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (s guildService) CreateRole(r geeksbot.Role) (geeksbot.Role, error) {
|
||||
queryString := "INSERT INTO roles (id, role_type, guild_id) VALUES ($1, $2, $3)"
|
||||
_, err := s.db.Exec(queryString, r.ID, r.RoleType, r.Guild.ID)
|
||||
return r, err
|
||||
}
|
||||
|
||||
func (s guildService) Role(id string) (geeksbot.Role, error) {
|
||||
var role geeksbot.Role
|
||||
var guild_id string
|
||||
queryString := "SELECT id, role_type, guild_id FROM roles WHERE id = $1"
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&role.ID, &role.RoleType, &guild_id)
|
||||
if err != nil {
|
||||
return geeksbot.Role{}, err
|
||||
}
|
||||
guild, err := s.Guild(guild_id)
|
||||
if err != nil {
|
||||
return geeksbot.Role{}, err
|
||||
}
|
||||
role.Guild = guild
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func (s guildService) UpdateRole(r geeksbot.Role) (geeksbot.Role, error) {
|
||||
queryString := "UPDATE roles SET role_type = $2 WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, r.ID, r.RoleType)
|
||||
return r, err
|
||||
}
|
||||
|
||||
func (s guildService) DeleteRole(r geeksbot.Role) error {
|
||||
queryString := "DELETE FROM roles WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, r.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s guildService) GetOrCreateGuild(id string) (geeksbot.Guild, error) {
|
||||
guild, err := s.Guild(id)
|
||||
if err == sql.ErrNoRows {
|
||||
guild = geeksbot.Guild{
|
||||
ID: id,
|
||||
Prefixes: []string{},
|
||||
}
|
||||
guild, err = s.CreateGuild(guild)
|
||||
}
|
||||
return guild, err
|
||||
}
|
||||
|
||||
func (s guildService) CreateOrUpdateRole(r geeksbot.Role) (geeksbot.Role, error) {
|
||||
role, err := s.CreateRole(r)
|
||||
if err != nil && err.Error() == `pq: duplicate key value violates unique constraint "roles_pkey"` {
|
||||
role, err = s.UpdateRole(r)
|
||||
}
|
||||
return role, err
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
type messageService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s messageService) Message(id string) (geeksbot.Message, error) {
|
||||
var m geeksbot.Message
|
||||
var channel_id string
|
||||
var author_id string
|
||||
queryString := `SELECT m.id, m.created_at, m.modified_at, m.content,
|
||||
m.previous_content, m.channel_id, m.author_id
|
||||
FROM messages as m
|
||||
WHERE m.id = $1`
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&m.ID, &m.CreatedAt, &m.ModifiedAt, &m.Content,
|
||||
pq.Array(&m.PreviousContent), &channel_id, &author_id)
|
||||
if err != nil {
|
||||
return geeksbot.Message{}, err
|
||||
}
|
||||
author, err := UserService.User(author_id)
|
||||
if err != nil {
|
||||
return geeksbot.Message{}, err
|
||||
}
|
||||
m.Author = author
|
||||
channel, err := ChannelService.Channel(channel_id)
|
||||
if err != nil {
|
||||
return geeksbot.Message{}, err
|
||||
}
|
||||
m.Channel = channel
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (s messageService) CreateMessage(m geeksbot.Message) (geeksbot.Message, error) {
|
||||
queryString := `INSERT INTO messages (id, created_at, content, channel_id, author_id)
|
||||
VALUES ($1, $2, $3, $4, $5)`
|
||||
_, err := s.db.Exec(queryString, m.ID, m.CreatedAt, m.Content, m.Channel.ID, m.Author.ID)
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (s messageService) UpdateMessage(m geeksbot.Message) (geeksbot.Message, error) {
|
||||
var content string
|
||||
var previousContent []string
|
||||
queryString := "SELECT content, previous_content FROM messages WHERE id = $1"
|
||||
row := s.db.QueryRow(queryString, m.ID)
|
||||
err := row.Scan(&content, &previousContent)
|
||||
if err != nil {
|
||||
return geeksbot.Message{}, err
|
||||
}
|
||||
if m.Content != content {
|
||||
previousContent = append(previousContent, content)
|
||||
}
|
||||
queryString = "UPDATE messages SET modified_at = $2, content = $3, previous_content = $4 WHERE id = $1"
|
||||
_, err = s.db.Exec(queryString, m.ID, m.ModifiedAt, m.Content, previousContent)
|
||||
m.PreviousContent = previousContent
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (s messageService) DeleteMessage(m geeksbot.Message) error {
|
||||
queryString := "DELETE FROM messages WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, m.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s messageService) ChannelMessages(c geeksbot.Channel) ([]geeksbot.Message, error) {
|
||||
var messages []geeksbot.Message
|
||||
queryString := `SELECT id FROM messages WHERE channel_id = $1`
|
||||
rows, err := s.db.Query(queryString, c.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id string
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
m, err := s.Message(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
messages = append(messages, m)
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
+4
-4
@@ -5,7 +5,7 @@ BEGIN;
|
||||
prefixes varchar(10)[],
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
CREATE TYPE IF NOT EXISTS role_type as ENUM (
|
||||
CREATE TYPE role_type as ENUM (
|
||||
'normal',
|
||||
'moderator',
|
||||
'admin',
|
||||
@@ -25,7 +25,7 @@ BEGIN;
|
||||
id varchar(30),
|
||||
guild_id varchar(30),
|
||||
admin boolean,
|
||||
default boolean,
|
||||
default_channel boolean,
|
||||
new_patron boolean,
|
||||
PRIMARY KEY(id),
|
||||
CONSTRAINT fk_guild
|
||||
@@ -45,7 +45,7 @@ BEGIN;
|
||||
id varchar(30),
|
||||
created_at timestamp,
|
||||
modified_at timestamp,
|
||||
content varchar(2000)
|
||||
content varchar(2000),
|
||||
previous_content varchar(2000)[],
|
||||
channel_id varchar(30),
|
||||
author_id varchar(30),
|
||||
@@ -89,7 +89,7 @@ BEGIN;
|
||||
REFERENCES roles(id)
|
||||
ON DELETE SET NULL,
|
||||
CONSTRAINT fk_tier
|
||||
FOREIGN_KEY(next_tier)
|
||||
FOREIGN KEY(next_tier)
|
||||
REFERENCES patreon_tier(id)
|
||||
ON DELETE SET NULL
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE requests DROP COLUMN guild_id;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE requests
|
||||
ADD COLUMN guild_id varchar(30) CONSTRAINT fk_guild REFERENCES guilds(id) ON DELETE CASCADE;
|
||||
@@ -0,0 +1,48 @@
|
||||
BEGIN;
|
||||
ALTER TABLE users
|
||||
ALTER COLUMN active DROP NOT NULL,
|
||||
ALTER COLUMN staff DROP NOT NULL,
|
||||
ALTER COLUMN admin DROP NOT NULL;
|
||||
ALTER TABLE channels
|
||||
ALTER COLUMN guild_id DROP NOT NULL,
|
||||
ALTER COLUMN admin DROP NOT NULL,
|
||||
ALTER COLUMN default_channel DROP NOT NULL,
|
||||
ALTER COLUMN new_patron DROP NOT NULL;
|
||||
ALTER TABLE messages
|
||||
ALTER COLUMN created_at DROP NOT NULL,
|
||||
ALTER COLUMN content DROP NOT NULL,
|
||||
ALTER COLUMN channel_id DROP NOT NULL,
|
||||
ALTER COLUMN author_id DROP NOT NULL;
|
||||
ALTER TABLE messages
|
||||
ADD COLUMN embed json,
|
||||
ADD COLUMN previous_embeds json[];
|
||||
ALTER TABLE patreon_creators
|
||||
ALTER COLUMN creator DROP NOT NULL,
|
||||
ALTER COLUMN link DROP NOT NULL,
|
||||
ALTER COLUMN guild_id DROP NOT NULL;
|
||||
ALTER TABLE patreon_creators
|
||||
RENAME TO patreon_creator;
|
||||
ALTER TABLE patreon_tiers
|
||||
ALTER COLUMN name DROP NOT NULL,
|
||||
ALTER COLUMN creator DROP NOT NULL,
|
||||
ALTER COLUMN role DROP NOT NULL;
|
||||
ALTER TABLE patreon_tiers
|
||||
RENAME TO patreon_tier;
|
||||
ALTER TABLE requests
|
||||
ALTER COLUMN author_id DROP NOT NULL,
|
||||
ALTER COLUMN channel_id DROP NOT NULL,
|
||||
ALTER COLUMN content DROP NOT NULL,
|
||||
ALTER COLUMN requested_at DROP NOT NULL,
|
||||
ALTER COLUMN completed DROP NOT NULL,
|
||||
ALTER COLUMN message_id DROP NOT NULL,
|
||||
ALTER COLUMN guild_id DROP NOT NULL;
|
||||
ALTER TABLE roles
|
||||
ALTER COLUMN role_type DROP NOT NULL,
|
||||
ALTER COLUMN guild_id DROP NOT NULL;
|
||||
ALTER TABLE servers
|
||||
ALTER COLUMN name DROP NOT NULL,
|
||||
ALTER COLUMN ip_address DROP NOT NULL,
|
||||
ALTER COLUMN port DROP NOT NULL,
|
||||
ALTER COLUMN password DROP NOT NULL,
|
||||
ALTER COLUMN guild_id DROP NOT NULL;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,48 @@
|
||||
BEGIN;
|
||||
ALTER TABLE users
|
||||
ALTER COLUMN active SET NOT NULL,
|
||||
ALTER COLUMN staff SET NOT NULL,
|
||||
ALTER COLUMN admin SET NOT NULL;
|
||||
ALTER TABLE channels
|
||||
ALTER COLUMN guild_id SET NOT NULL,
|
||||
ALTER COLUMN admin SET NOT NULL,
|
||||
ALTER COLUMN default_channel SET NOT NULL,
|
||||
ALTER COLUMN new_patron SET NOT NULL;
|
||||
ALTER TABLE messages
|
||||
ALTER COLUMN created_at SET NOT NULL,
|
||||
ALTER COLUMN content SET NOT NULL,
|
||||
ALTER COLUMN channel_id SET NOT NULL,
|
||||
ALTER COLUMN author_id SET NOT NULL;
|
||||
ALTER TABLE messages
|
||||
DROP COLUMN embed,
|
||||
DROP COLUMN previous_embeds;
|
||||
ALTER TABLE patreon_creator
|
||||
ALTER COLUMN creator SET NOT NULL,
|
||||
ALTER COLUMN link SET NOT NULL,
|
||||
ALTER COLUMN guild_id SET NOT NULL;
|
||||
ALTER TABLE patreon_creator
|
||||
RENAME TO patreon_creators;
|
||||
ALTER TABLE patreon_tier
|
||||
ALTER COLUMN name SET NOT NULL,
|
||||
ALTER COLUMN creator SET NOT NULL,
|
||||
ALTER COLUMN role SET NOT NULL;
|
||||
ALTER TABLE patreon_tier
|
||||
RENAME TO patreon_tiers;
|
||||
ALTER TABLE requests
|
||||
ALTER COLUMN author_id SET NOT NULL,
|
||||
ALTER COLUMN channel_id SET NOT NULL,
|
||||
ALTER COLUMN content SET NOT NULL,
|
||||
ALTER COLUMN requested_at SET NOT NULL,
|
||||
ALTER COLUMN completed SET NOT NULL,
|
||||
ALTER COLUMN message_id SET NOT NULL,
|
||||
ALTER COLUMN guild_id SET NOT NULL;
|
||||
ALTER TABLE roles
|
||||
ALTER COLUMN role_type SET NOT NULL,
|
||||
ALTER COLUMN guild_id SET NOT NULL;
|
||||
ALTER TABLE servers
|
||||
ALTER COLUMN name SET NOT NULL,
|
||||
ALTER COLUMN ip_address SET NOT NULL,
|
||||
ALTER COLUMN port SET NOT NULL,
|
||||
ALTER COLUMN password SET NOT NULL,
|
||||
ALTER COLUMN guild_id SET NOT NULL;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,14 @@
|
||||
BEGIN;
|
||||
CREATE TYPE role_type_new AS ENUM (
|
||||
'normal',
|
||||
'moderator',
|
||||
'admin',
|
||||
'patreon',
|
||||
);
|
||||
UPDATE roles SET role_type = 'normal' WHERE role_type = 'sar';
|
||||
ALTER TABLE roles
|
||||
ALTER COLUMN roles TYPE role_type_new;
|
||||
USING (roles::text::role_type_new)
|
||||
DROP TYPE role_type;
|
||||
ALTER TYPE role_type_new RENAME TO role_type;
|
||||
COMMIT;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TYPE role_type ADD VALUE 'sar';
|
||||
@@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
ALTER TABLE messages
|
||||
ALTER COLUMN previous_content DROP NOT NULL;
|
||||
ALTER TABLE messages
|
||||
ALTER COLUMN previous_content DROP DEFAULT;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
ALTER TABLE messages
|
||||
ALTER COLUMN previous_content SET NOT NULL;
|
||||
ALTER TABLE messages
|
||||
ALTER COLUMN previous_content SET DEFAULT array[]::varchar[];
|
||||
COMMIT;
|
||||
@@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
ALTER TABLE servers
|
||||
DROP COLUMN ftp_port,
|
||||
DROP COLUMN ftp_username,
|
||||
DROP COLUMN ftp_password;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
ALTER TABLE servers
|
||||
ADD COLUMN ftp_port int4,
|
||||
ADD COLUMN ftp_username varchar(200),
|
||||
ADD COLUMN ftp_password varchar(200);
|
||||
COMMIT;
|
||||
@@ -0,0 +1,267 @@
|
||||
// Code generated for package migrations by go-bindata DO NOT EDIT. (@generated)
|
||||
// sources:
|
||||
// 000001_init_schema.down.sql
|
||||
// 000001_init_schema.up.sql
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
name string
|
||||
size int64
|
||||
mode os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
// Name return file name
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
|
||||
// Size return file size
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
|
||||
// Mode return file mode
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
|
||||
// Mode return file modify time
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
|
||||
// IsDir return file whether a directory
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return fi.mode&os.ModeDir != 0
|
||||
}
|
||||
|
||||
// Sys return file is sys mode
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var __000001_init_schemaDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\xcf\x3d\x0e\xc2\x30\x0c\x86\xe1\x3d\xa7\xf0\x3d\x32\x51\x08\x28\x12\xa5\x15\xcd\x00\x53\x15\x15\xab\x54\xca\x4f\xb1\x13\x24\x6e\xcf\x0c\x83\x61\xf6\x23\x7d\x7e\x1b\x73\xb0\x27\xad\x00\x00\x76\xe7\xae\x07\xb7\x69\x8e\x06\xec\x1e\xcc\xc5\x0e\x6e\x00\x46\x7a\x22\xb1\x20\xa6\x1c\x23\xa6\x22\x11\xc2\x47\x45\x16\xc9\xea\x0b\x61\x4e\x63\x59\x90\xfe\x60\x13\xa1\x2f\x59\x92\x11\x99\xfd\x8c\xd2\x66\xe5\x1f\x65\x77\x9f\x12\x06\xb1\x2c\x87\xcf\x89\x6b\xff\x7d\x1e\xcb\x6b\x15\xdf\x98\xeb\x12\x6e\xac\xd5\xb6\x6b\x5b\xeb\xb4\x7a\x07\x00\x00\xff\xff\x57\xde\x8f\x03\x93\x01\x00\x00")
|
||||
|
||||
func _000001_init_schemaDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__000001_init_schemaDownSql,
|
||||
"000001_init_schema.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _000001_init_schemaDownSql() (*asset, error) {
|
||||
bytes, err := _000001_init_schemaDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000001_init_schema.down.sql", size: 403, mode: os.FileMode(420), modTime: time.Unix(1611206279, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __000001_init_schemaUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x58\x5d\x6f\xa3\x38\x14\x7d\xef\xaf\xf0\x5b\x12\x69\x1f\xba\xbb\xda\xa7\x3e\xd1\xc4\xad\xd0\x26\xa4\x22\x54\xbb\xd1\x68\x84\xdc\x70\x93\x7a\x0a\x36\x63\x3b\x69\xfb\xef\x47\x50\x3e\x1c\xc0\xe0\x51\x99\x6a\xca\x53\xe4\x7b\xb1\x8f\xcf\x3d\xf7\x83\x5c\xe3\x5b\xd7\xbb\xba\x40\x08\xa1\xb9\x8f\x9d\x00\xa3\xc0\xb9\x5e\x62\xe4\xde\x20\x6f\x1d\x20\xfc\xbf\xbb\x09\x36\xe8\x70\xa4\x71\x24\xd1\x34\xf7\xcb\x1e\x1a\xa1\x13\x11\xbb\x47\x22\xa6\x7f\x5f\xce\xfe\xa8\xd6\x19\x3c\x87\x29\x51\x82\xb3\x30\x01\x29\xc9\x01\x2a\xbf\x3f\x2f\x2f\x75\xcf\x54\xc0\x9e\xbe\x80\xd4\xec\xb3\x2f\x5f\x6b\xfb\x9d\xef\xae\x1c\x7f\x8b\xfe\xc5\xdb\x29\x8d\x66\xf9\xfa\xec\x1c\xe8\xf6\x0e\x23\xc1\x63\x08\xd5\x6b\x0a\x88\x48\x84\xbd\xfb\x95\x06\x72\xc2\xb8\x48\x48\x3c\xa9\x37\x9d\x24\x3c\x02\x41\x14\x17\xfa\x22\x89\x12\xca\xf4\x85\xec\x06\xc0\xd9\xa4\xeb\xd0\x0e\x76\x32\x0c\x36\xe4\xd4\x58\xab\x5f\xb5\x31\xa7\x38\x34\xbd\xda\x60\xa3\x36\xcc\xd7\xde\x26\xf0\x1d\xd7\x0b\xd0\xfe\x29\xcc\x37\xa9\x6c\xd9\x73\xb3\xf6\xb1\x7b\xeb\xe5\x2f\x96\x47\xcc\xce\x3c\xb2\xc7\xc7\x37\xd8\xc7\xde\x1c\x97\xa1\x9e\x76\x79\xad\x3d\xb4\xc0\x4b\x1c\x60\x34\x77\x36\x73\x67\x81\x2d\xf9\xd9\x3d\x12\xc6\x20\xb6\xa1\xa8\x9f\x85\x3c\x50\xe8\x81\xf3\x18\x08\xab\x97\x23\xd8\x93\x63\xac\xc2\xe2\x9c\xb6\x43\xad\xca\xb6\xed\x53\x33\x7b\x94\x20\x6c\x68\x95\x0a\x48\x62\xa6\x75\xa7\xe8\x09\xda\xd4\x48\x45\xf6\xfb\xf6\xb2\x21\x0a\x16\x09\xdb\x71\x83\xa2\x4a\xd8\x5c\x62\x27\x80\x28\x88\x42\xa2\x90\xa2\x09\x48\x45\x92\xb4\xb6\x26\x3c\xa2\x7b\x6a\x34\xef\x38\x53\xc0\x54\xb5\xf3\x5f\xad\x6a\x74\xa2\xfc\x28\xc3\x4e\x3f\xbd\x2e\x15\x22\x33\x93\x79\x54\x8f\x5c\x18\xcd\x90\x3c\x40\x84\xbe\x49\xce\x3a\x0e\xcf\x8d\x32\xb7\xf6\x94\x42\x93\x44\x0b\x64\x46\x91\xd6\xc8\x7b\x65\x5a\x66\xab\x9d\x50\x4d\x60\x32\x65\x1a\x91\x54\x1c\xf5\x02\xc9\xc5\x3d\x80\x62\x83\x03\xe4\xdd\x2f\x97\x96\x6a\x2b\x0a\x7b\x98\x4b\x89\x8b\x73\xd1\x51\xa6\xe0\x00\x02\xdd\x62\x0f\xfb\x4e\x80\x17\xc8\x59\xfe\xe7\x6c\x37\xc8\xd9\x20\x77\x81\xbd\xc0\x0d\xb6\x0d\x35\x72\xa1\xb7\x37\x2d\x32\x31\x65\x4f\xba\x86\xac\x4b\xdc\xa7\x2e\x47\x25\xbd\x8a\x42\x83\xdb\x9f\x24\x97\x91\x04\x0c\xcc\x46\x20\x77\x82\xa6\x8a\x72\x66\x1a\x2d\xca\xd0\x14\x67\x9e\x37\x60\xd3\xdc\xf2\xa2\xde\x60\xb7\x5e\xb2\xcd\xbe\xb7\x43\xcd\xd9\xf7\x66\xef\x0d\x49\x43\x9e\xef\xcb\xc0\xec\xb2\x46\x34\x99\xb1\x17\x4a\x3e\xd3\x58\x26\x9f\x09\x41\xc6\xa7\x11\x41\xc5\xb8\x15\x23\x99\xe3\xb8\xa5\x40\xc0\xf7\x23\x48\x25\xdf\x53\x03\x06\x6a\xfd\x50\xab\x68\xf6\x9a\x86\x8c\x0b\x84\x3d\x2d\x2d\x49\x63\xb0\xb0\xb7\x7b\x75\xfd\xea\xc3\x6b\x37\xb6\xa2\x2f\xf7\x60\x2f\x77\x18\x98\xf3\x2d\xd3\xe7\x83\xfa\xc5\x40\xce\xfc\x56\x2d\x54\x0f\x92\x19\x91\xe6\x34\x5a\x37\x35\x21\x2a\x42\x6d\x04\x53\x8b\xa6\x17\x4a\x39\xf3\x8d\xfb\x91\xc1\x93\x04\xd8\x2f\xcd\xe7\x22\x21\xc3\x7a\xdf\xb3\x7c\xc8\x8e\xb7\x9c\x3e\x3f\x73\x8e\x14\x2c\x98\x5b\x4b\xc5\x52\x7f\x83\x29\xea\xef\xa8\x22\x90\x20\x4e\xad\x2f\xa2\xd1\x46\x0f\x9a\x86\x24\x8a\x04\x48\xed\x4f\x8b\x7f\xf4\x8f\x08\x2e\x54\x5b\x19\x29\x91\xf2\x99\x8b\xc8\x30\x0e\x92\x18\x84\x92\xe1\x50\xaf\xe8\x9f\x1a\x29\xdb\xf3\xc1\x2d\x72\xa7\xa1\xba\x2e\x41\x29\xca\x0e\x72\xd0\xd1\x52\xb3\xf9\xf5\x06\xeb\x6a\x8b\x84\x31\xca\xeb\x50\x35\xfb\xe0\x19\xda\x04\x43\x8f\x9d\x11\x4d\x23\xc0\x1f\x41\x8f\x2e\x97\x7e\x5c\xe3\x96\xfd\x21\x5c\x4d\x85\x1a\xb1\x75\x48\x79\x4c\x7c\x65\x49\x9a\xaf\x57\x2b\x37\xb8\xba\xf8\x11\x00\x00\xff\xff\xb3\xc0\x11\x7f\x4a\x15\x00\x00")
|
||||
|
||||
func _000001_init_schemaUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__000001_init_schemaUpSql,
|
||||
"000001_init_schema.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _000001_init_schemaUpSql() (*asset, error) {
|
||||
bytes, err := _000001_init_schemaUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000001_init_schema.up.sql", size: 5450, mode: os.FileMode(420), modTime: time.Unix(1611216889, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Asset loads and returns the asset for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.bytes, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
func MustAsset(name string) []byte {
|
||||
a, err := Asset(name)
|
||||
if err != nil {
|
||||
panic("asset: Asset(" + name + "): " + err.Error())
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// AssetInfo loads and returns the asset info for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.info, nil
|
||||
}
|
||||
return nil, fmt.Errorf("AssetInfo %s not found", name)
|
||||
}
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_bindata))
|
||||
for name := range _bindata {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"000001_init_schema.down.sql": _000001_init_schemaDownSql,
|
||||
"000001_init_schema.up.sql": _000001_init_schemaUpSql,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
// following hierarchy:
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(cannonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
rv := make([]string, 0, len(node.Children))
|
||||
for childName := range node.Children {
|
||||
rv = append(rv, childName)
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"000001_init_schema.down.sql": &bintree{_000001_init_schemaDownSql, map[string]*bintree{}},
|
||||
"000001_init_schema.up.sql": &bintree{_000001_init_schemaUpSql, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
func RestoreAsset(dir, name string) error {
|
||||
data, err := Asset(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := AssetInfo(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RestoreAssets restores an asset under the given directory recursively
|
||||
func RestoreAssets(dir, name string) error {
|
||||
children, err := AssetDir(name)
|
||||
// File
|
||||
if err != nil {
|
||||
return RestoreAsset(dir, name)
|
||||
}
|
||||
// Dir
|
||||
for _, child := range children {
|
||||
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
)
|
||||
|
||||
type patreonService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s patreonService) PatreonCreatorByID(id int) (geeksbot.PatreonCreator, error) {
|
||||
var creator geeksbot.PatreonCreator
|
||||
var gID string
|
||||
queryString := "SELECT id, creator, link, guild_id FROM patreon_creator WHERE id = $1"
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&creator.ID, &creator.Creator, &creator.Link, &gID)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonCreator{}, err
|
||||
}
|
||||
guild, err := GuildService.Guild(gID)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonCreator{}, err
|
||||
}
|
||||
creator.Guild = guild
|
||||
return creator, nil
|
||||
}
|
||||
|
||||
func (s patreonService) PatreonCreatorByName(name string, g geeksbot.Guild) (geeksbot.PatreonCreator, error) {
|
||||
var id int
|
||||
queryString := "SELECT id FROM patreon_creator WHERE creator = $1 AND guild_id = $2"
|
||||
err := s.db.QueryRow(queryString, name, g.ID).Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonCreator{}, nil
|
||||
}
|
||||
creator, err := s.PatreonCreatorByID(id)
|
||||
return creator, err
|
||||
}
|
||||
|
||||
func (s patreonService) CreatePatreonCreator(c geeksbot.PatreonCreator) (geeksbot.PatreonCreator, error) {
|
||||
var id int
|
||||
queryString := `INSERT INTO patreon_creator (creator, link, guild_id) VALUES ($1, $2, $3) RETURNING id`
|
||||
err := s.db.QueryRow(queryString, c.Creator, c.Link, c.Guild.ID).Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonCreator{}, err
|
||||
}
|
||||
c.ID = id
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (s patreonService) UpdatePatreonCreator(c geeksbot.PatreonCreator) (geeksbot.PatreonCreator, error) {
|
||||
queryString := `UPDATE patreon_creator SET creator = $2, link = $3 WHERE id = $1`
|
||||
_, err := s.db.Exec(queryString, c.ID, c.Creator, c.Link)
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (s patreonService) DeletePatreonCreator(c geeksbot.PatreonCreator) error {
|
||||
queryString := `DELETE FROM patreon_creator WHERE id = $1`
|
||||
_, err := s.db.Exec(queryString, c.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s patreonService) PatreonTierByID(id int) (geeksbot.PatreonTier, error) {
|
||||
var tier geeksbot.PatreonTier
|
||||
var cID int
|
||||
var rID string
|
||||
var next int
|
||||
queryString := `SELECT id, name, description, creator, role, next_tier FROM patreon_tier WHERE id = id`
|
||||
err := s.db.QueryRow(queryString, id).Scan(&tier.ID, &tier.Name, &tier.Description, &cID, &rID, &next)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonTier{}, err
|
||||
}
|
||||
creator, err := s.PatreonCreatorByID(cID)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonTier{}, err
|
||||
}
|
||||
tier.Creator = creator
|
||||
role, err := GuildService.Role(rID)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonTier{}, err
|
||||
}
|
||||
tier.Role = role
|
||||
if next == -1 {
|
||||
tier.NextTier = nil
|
||||
return tier, nil
|
||||
}
|
||||
nextTier, err := s.PatreonTierByID(next)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonTier{}, err
|
||||
}
|
||||
tier.NextTier = &nextTier
|
||||
return tier, nil
|
||||
}
|
||||
|
||||
func (s patreonService) PatreonTierByName(name string, creator string) (geeksbot.PatreonTier, error) {
|
||||
var id int
|
||||
queryString := `SELECT id FROM patreon_tier WHERE name = $1 AND creator = $2`
|
||||
err := s.db.QueryRow(queryString, name, creator).Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonTier{}, err
|
||||
}
|
||||
tier, err := s.PatreonTierByID(id)
|
||||
return tier, err
|
||||
}
|
||||
|
||||
func (s patreonService) CreatePatreonTier(t geeksbot.PatreonTier) (geeksbot.PatreonTier, error) {
|
||||
var id int
|
||||
queryString := `INSERT INTO patreon_tier (name, description, creator, role, next_tier)
|
||||
VALUES ($1, $2, $3, $4, $5) RETURNING id`
|
||||
err := s.db.QueryRow(queryString, t.Name, t.Description, t.Creator.ID, t.Role.ID, t.NextTier.ID).Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.PatreonTier{}, err
|
||||
}
|
||||
t.ID = id
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (s patreonService) UpdatePatreonTier(t geeksbot.PatreonTier) (geeksbot.PatreonTier, error) {
|
||||
queryString := `UPDATE patreon_tier SET name = $2, description = $3, role = $4, next_tier = $5 WHERE id = $1`
|
||||
_, err := s.db.Exec(queryString, t.ID, t.Name, t.Description, t.Role.ID, t.NextTier.ID)
|
||||
return t, err
|
||||
}
|
||||
|
||||
func (s patreonService) DeletePatreonTier(t geeksbot.PatreonTier) error {
|
||||
queryString := `DELETE FROM patreon_tier WHERE id = $1`
|
||||
_, err := s.db.Exec(queryString, t.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s patreonService) GuildPatreonCreators(g geeksbot.Guild) ([]geeksbot.PatreonCreator, error) {
|
||||
var creators []geeksbot.PatreonCreator
|
||||
queryString := `SELECT id FROM patreon_creator WHERE guild_id = $1`
|
||||
rows, err := s.db.Query(queryString, g.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id int
|
||||
err := rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
creator, err := s.PatreonCreatorByID(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
creators = append(creators, creator)
|
||||
}
|
||||
return creators, nil
|
||||
}
|
||||
|
||||
func (s patreonService) CreatorPatreonTiers(c geeksbot.PatreonCreator) ([]geeksbot.PatreonTier, error) {
|
||||
var tiers []geeksbot.PatreonTier
|
||||
queryString := `SELECT id FROM patreon_tier WHERE creator = $1`
|
||||
rows, err := s.db.Query(queryString, c.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id int
|
||||
err := rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
tier, err := s.PatreonTierByID(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
tiers = append(tiers, tier)
|
||||
}
|
||||
return tiers, nil
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
)
|
||||
|
||||
type requestService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s requestService) Request(id int64) (geeksbot.Request, error) {
|
||||
var r geeksbot.Request
|
||||
var aID string
|
||||
var cID string
|
||||
var gID string
|
||||
var uID sql.NullString
|
||||
var mID string
|
||||
queryString := `SELECT id, author_id, channel_id, guild_id, content, requested_at, completed,
|
||||
completed_at, completed_by, message_id, completed_message FROM requests
|
||||
WHERE id = $1`
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&r.ID, &aID, &cID, &gID, &r.Content, &r.RequestedAt, &r.Completed,
|
||||
&r.CompletedAt, &uID, &mID, &r.CompletedMessage)
|
||||
if err != nil {
|
||||
return geeksbot.Request{}, err
|
||||
}
|
||||
author, err := UserService.User(aID)
|
||||
if err != nil {
|
||||
return geeksbot.Request{}, err
|
||||
}
|
||||
guild, err := GuildService.Guild(gID)
|
||||
if err != nil {
|
||||
return geeksbot.Request{}, err
|
||||
}
|
||||
channel, err := ChannelService.Channel(cID)
|
||||
if err != nil {
|
||||
return geeksbot.Request{}, err
|
||||
}
|
||||
if !uID.Valid {
|
||||
r.CompletedBy = nil
|
||||
} else {
|
||||
completedBy, err := UserService.User(uID.String)
|
||||
if err != nil {
|
||||
return geeksbot.Request{}, err
|
||||
}
|
||||
r.CompletedBy = &completedBy
|
||||
}
|
||||
message, err := MessageService.Message(mID)
|
||||
if err != nil {
|
||||
return geeksbot.Request{}, err
|
||||
}
|
||||
r.Author = author
|
||||
r.Guild = guild
|
||||
r.Channel = channel
|
||||
r.Message = message
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (s requestService) UserRequests(u geeksbot.User, completed bool) ([]geeksbot.Request, error) {
|
||||
var requests []geeksbot.Request
|
||||
var queryString string
|
||||
if completed {
|
||||
queryString = "SELECT id FROM requests WHERE author_id = $1"
|
||||
} else {
|
||||
queryString = "SELECT id FROM requests WHERE author_id = $1 AND completed = False"
|
||||
}
|
||||
rows, err := s.db.Query(queryString, u.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id int64
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
request, err := s.Request(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
requests = append(requests, request)
|
||||
}
|
||||
return requests, nil
|
||||
}
|
||||
|
||||
func (s requestService) GuildRequests(g geeksbot.Guild, completed bool) ([]geeksbot.Request, error) {
|
||||
var requests []geeksbot.Request
|
||||
var queryString string
|
||||
if completed {
|
||||
queryString = "SELECT id FROM requests WHERE guild_id = $1"
|
||||
} else {
|
||||
queryString = "SELECT id FROM requests WHERE guild_id = $1 AND completed = False"
|
||||
}
|
||||
rows, err := s.db.Query(queryString, g.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id int64
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
request, err := s.Request(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
requests = append(requests, request)
|
||||
}
|
||||
return requests, nil
|
||||
|
||||
}
|
||||
|
||||
func (s requestService) CreateRequest(r geeksbot.Request) (geeksbot.Request, error) {
|
||||
queryString := `INSERT INTO requests
|
||||
(author_id, channel_id, guild_id, content, requested_at,
|
||||
completed, completed_at, completed_by, message_id, completed_message)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id`
|
||||
var id int64
|
||||
var completedByID sql.NullString
|
||||
if r.CompletedBy == nil {
|
||||
completedByID.String = ""
|
||||
completedByID.Valid = false
|
||||
} else {
|
||||
completedByID.String = r.CompletedBy.ID
|
||||
completedByID.Valid = true
|
||||
}
|
||||
err := s.db.QueryRow(queryString,
|
||||
r.Author.ID,
|
||||
r.Channel.ID,
|
||||
r.Guild.ID,
|
||||
r.Content,
|
||||
r.RequestedAt,
|
||||
r.Completed,
|
||||
r.CompletedAt,
|
||||
completedByID,
|
||||
r.Message.ID,
|
||||
r.CompletedMessage).Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.Request{}, err
|
||||
}
|
||||
r.ID = id
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (s requestService) UpdateRequest(r geeksbot.Request) (geeksbot.Request, error) {
|
||||
queryString := `UPDATE requests SET
|
||||
completed = $2, completed_at = $3, completed_by = $4, completed_message = $5
|
||||
WHERE id = $1`
|
||||
_, err := s.db.Exec(queryString, r.ID, r.Completed, r.CompletedAt, r.CompletedBy.ID, r.CompletedMessage)
|
||||
return r, err
|
||||
}
|
||||
|
||||
func (s requestService) DeleteRequest(r geeksbot.Request) error {
|
||||
queryString := "DELETE FROM requests WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, r.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s requestService) Comment(id int64) (geeksbot.Comment, error) {
|
||||
var c geeksbot.Comment
|
||||
var aID string
|
||||
var rID int64
|
||||
queryString := "SELECT id, author_id, request_id, comment_at, content FROM comments WHERE id = $1"
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&c.ID, &aID, &rID, &c.CommentAt, &c.Content)
|
||||
if err != nil {
|
||||
return geeksbot.Comment{}, err
|
||||
}
|
||||
author, err := UserService.User(aID)
|
||||
if err != nil {
|
||||
return geeksbot.Comment{}, err
|
||||
}
|
||||
c.Author = author
|
||||
request, err := s.Request(rID)
|
||||
if err != nil {
|
||||
return geeksbot.Comment{}, err
|
||||
}
|
||||
c.Request = request
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (s requestService) RequestComments(r geeksbot.Request) ([]geeksbot.Comment, error) {
|
||||
var comments []geeksbot.Comment
|
||||
queryString := "SELECT id FROM comments WHERE request_id = $1"
|
||||
rows, err := s.db.Query(queryString, r.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id int64
|
||||
err := rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
comment, err := s.Comment(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
comments = append(comments, comment)
|
||||
}
|
||||
return comments, nil
|
||||
}
|
||||
|
||||
func (s requestService) RequestCommentCount(r geeksbot.Request) (int, error) {
|
||||
var count int
|
||||
queryString := "SELECT COUNT(id) FROM comments WHERE request_id = $1"
|
||||
row := s.db.QueryRow(queryString, r.ID)
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (s requestService) CreateComment(c geeksbot.Comment) (geeksbot.Comment, error) {
|
||||
queryString := `INSERT INTO comments (author_id, request_id, comment_at, content)
|
||||
VALUES ($1, $2, $3, $4) RETURNING id`
|
||||
var id int64
|
||||
err := s.db.QueryRow(queryString, c.Author.ID, c.Request.ID, c.CommentAt, c.Content).Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.Comment{}, err
|
||||
}
|
||||
c.ID = id
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (s requestService) DeleteComment(c geeksbot.Comment) error {
|
||||
queryString := "DELETE FROM comments WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, c.ID)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
)
|
||||
|
||||
type serverService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s serverService) ServerByID(id int) (geeksbot.Server, error) {
|
||||
var server geeksbot.Server
|
||||
var guildID string
|
||||
var aChanID sql.NullString
|
||||
var iChanID sql.NullString
|
||||
var iMsgID sql.NullString
|
||||
var sMsgID sql.NullString
|
||||
queryString := `SELECT id, name, ip_address, port, password, alerts_channel_id,
|
||||
guild_id, info_channel_id, info_message_id, settings_message_id,
|
||||
ftp_port, ftp_username, ftp_password
|
||||
FROM servers WHERE id = $1`
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&server.ID, &server.Name, &server.IPAddr, &server.Port, &server.Password,
|
||||
&aChanID, &guildID, &iChanID, &iMsgID, &sMsgID, &server.FTPPort, &server.FTPUser, &server.FTPPass)
|
||||
if err != nil {
|
||||
return geeksbot.Server{}, err
|
||||
}
|
||||
guild, err := GuildService.Guild(guildID)
|
||||
if err != nil {
|
||||
return geeksbot.Server{}, err
|
||||
}
|
||||
if !aChanID.Valid {
|
||||
server.AlertsChannel = nil
|
||||
} else {
|
||||
alertChannel, err := ChannelService.Channel(aChanID.String)
|
||||
if err != nil {
|
||||
return geeksbot.Server{}, err
|
||||
}
|
||||
server.AlertsChannel = &alertChannel
|
||||
}
|
||||
if !iChanID.Valid {
|
||||
server.InfoChannel = nil
|
||||
} else {
|
||||
infoChannel, err := ChannelService.Channel(iChanID.String)
|
||||
if err != nil {
|
||||
return geeksbot.Server{}, err
|
||||
}
|
||||
server.InfoChannel = &infoChannel
|
||||
}
|
||||
if !iMsgID.Valid {
|
||||
server.InfoMessage = nil
|
||||
} else {
|
||||
infoMessage, err := MessageService.Message(iMsgID.String)
|
||||
if err != nil {
|
||||
return geeksbot.Server{}, err
|
||||
}
|
||||
server.InfoMessage = &infoMessage
|
||||
}
|
||||
if !sMsgID.Valid {
|
||||
server.SettingsMessage = nil
|
||||
} else {
|
||||
settingsMessage, err := MessageService.Message(sMsgID.String)
|
||||
if err != nil {
|
||||
return geeksbot.Server{}, err
|
||||
}
|
||||
server.SettingsMessage = &settingsMessage
|
||||
}
|
||||
server.Guild = guild
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func (s serverService) ServerByName(name string, guild geeksbot.Guild) (geeksbot.Server, error) {
|
||||
var id int
|
||||
queryString := "SELECT id FROM servers WHERE LOWER(name) = LOWER($1) AND guild_id = $2"
|
||||
row := s.db.QueryRow(queryString, name, guild.ID)
|
||||
err := row.Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.Server{}, err
|
||||
}
|
||||
server, err := s.ServerByID(id)
|
||||
return server, err
|
||||
}
|
||||
|
||||
func (s serverService) CreateServer(server geeksbot.Server) (geeksbot.Server, error) {
|
||||
var id int
|
||||
queryString := `INSERT INTO servers (name, ip_address, port, password, alerts_channel_id,
|
||||
guild_id, info_channel_id, info_message_id, settings_message_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id`
|
||||
err := s.db.QueryRow(queryString,
|
||||
server.Name,
|
||||
server.IPAddr,
|
||||
server.Port,
|
||||
server.Password,
|
||||
server.AlertsChannel,
|
||||
server.Guild,
|
||||
server.InfoChannel,
|
||||
server.InfoMessage,
|
||||
server.SettingsMessage,
|
||||
).Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.Server{}, err
|
||||
}
|
||||
server.ID = id
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func (s serverService) DeleteServer(server geeksbot.Server) error {
|
||||
queryString := `DELETE FROM servers WHERE id = $1`
|
||||
_, err := s.db.Exec(queryString, server.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s serverService) UpdateServer(server geeksbot.Server) (geeksbot.Server, error) {
|
||||
queryString := `UPDATE servers SET name = $2, ip_address = $3, port = $4, password = $5,
|
||||
alerts_channel_id = $6, info_channel_id = $7, info_message_id = $8,
|
||||
settings_message_id = $9, ftp_port = $10, ftp_username = $11,
|
||||
ftp_password = $12 WHERE id = $1`
|
||||
_, err := s.db.Exec(queryString,
|
||||
server.Name,
|
||||
server.IPAddr,
|
||||
server.Port,
|
||||
server.Password,
|
||||
server.AlertsChannel.ID,
|
||||
server.InfoChannel.ID,
|
||||
server.InfoMessage.ID,
|
||||
server.SettingsMessage.ID,
|
||||
server.FTPPort,
|
||||
server.FTPUser,
|
||||
server.FTPPass,
|
||||
)
|
||||
return server, err
|
||||
}
|
||||
|
||||
func (s serverService) GuildServers(g geeksbot.Guild) ([]geeksbot.Server, error) {
|
||||
var servers []geeksbot.Server
|
||||
queryString := `SELECT id FROM servers WHERE guild_id = $1`
|
||||
rows, err := s.db.Query(queryString, g.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
var id int
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
server, err := s.ServerByID(id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
servers = append(servers, server)
|
||||
}
|
||||
return servers, nil
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
)
|
||||
|
||||
type userService struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s userService) User(id string) (geeksbot.User, error) {
|
||||
var user geeksbot.User
|
||||
queryString := "SELECT id, steam_id, active, staff, admin FROM users WHERE id = $1"
|
||||
row := s.db.QueryRow(queryString, id)
|
||||
err := row.Scan(&user.ID, &user.SteamID, &user.IsActive, &user.IsStaff, &user.IsAdmin)
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (s userService) CreateUser(u geeksbot.User) (geeksbot.User, error) {
|
||||
queryString := "INSERT INTO users (id, steam_id, active, staff, admin) VALUES ($1, $2, $3, $4, $5)"
|
||||
var err error
|
||||
_, err = s.db.Exec(queryString, u.ID, u.SteamID, u.IsActive, u.IsStaff, u.IsAdmin)
|
||||
return u, err
|
||||
}
|
||||
|
||||
func (s userService) DeleteUser(u geeksbot.User) error {
|
||||
queryString := "DELETE FROM users WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, u.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s userService) UpdateUser(u geeksbot.User) (geeksbot.User, error) {
|
||||
queryString := "UPDATE users SET steam_id = $2, active = $3, staff = $4, admin = $5 WHERE id = $1"
|
||||
_, err := s.db.Exec(queryString, u.ID, u.SteamID, u.IsActive, u.IsStaff, u.IsAdmin)
|
||||
return u, err
|
||||
}
|
||||
|
||||
func (s userService) GetOrCreateUser(id string) (geeksbot.User, error) {
|
||||
user, err := s.User(id)
|
||||
if err == sql.ErrNoRows {
|
||||
user, err = s.CreateUser(geeksbot.User{
|
||||
ID: id,
|
||||
IsActive: true,
|
||||
IsAdmin: false,
|
||||
IsStaff: false,
|
||||
})
|
||||
}
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (s userService) GetBySteamID(steamID string) (geeksbot.User, error) {
|
||||
var id string
|
||||
queryString := "SELECT id FROM users WHERE steam_id = $1"
|
||||
err := s.db.QueryRow(queryString, steamID).Scan(&id)
|
||||
if err != nil {
|
||||
return geeksbot.User{}, err
|
||||
}
|
||||
user, err := s.User(id)
|
||||
return user, err
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot"
|
||||
"gitea.wayfinderak.com/wayfinderak/geeksbot/pkg/database"
|
||||
)
|
||||
|
||||
var (
|
||||
GuildService geeksbot.GuildService
|
||||
UserService geeksbot.UserService
|
||||
ChannelService geeksbot.ChannelService
|
||||
MessageService geeksbot.MessageService
|
||||
PatreonService geeksbot.PatreonService
|
||||
RequestService geeksbot.RequestService
|
||||
ServerService geeksbot.ServerService
|
||||
)
|
||||
|
||||
func InitializeServices() {
|
||||
GuildService = database.GuildService
|
||||
UserService = database.UserService
|
||||
ChannelService = database.ChannelService
|
||||
MessageService = database.MessageService
|
||||
PatreonService = database.PatreonService
|
||||
RequestService = database.RequestService
|
||||
ServerService = database.ServerService
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
DATABASE_URL=postgresql://USER:PASSWORD@HOST:5432/geeksbot?sslmode=disable
|
||||
DISCORD_TOKEN=replace-me
|
||||
STEAM_API_KEY=replace-me
|
||||
@@ -0,0 +1,9 @@
|
||||
services:
|
||||
geeksbot:
|
||||
image: gitea.wayfinderak.com/wayfinderak/geeksbot:latest
|
||||
container_name: geeksbot
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- ./portainer-app.env
|
||||
mem_limit: 1g
|
||||
cpus: "2.0"
|
||||
+24
-19
@@ -1,37 +1,42 @@
|
||||
package geeksbot
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
ID int64
|
||||
Author *User
|
||||
Channel *Channel
|
||||
Author User
|
||||
Channel Channel
|
||||
Guild Guild
|
||||
Content string
|
||||
RequestedAt time.Time
|
||||
CompletedAt time.Time
|
||||
Completed bool
|
||||
CompletedAt sql.NullTime
|
||||
CompletedBy *User
|
||||
Message *Message
|
||||
CompletedMessage string
|
||||
Message Message
|
||||
CompletedMessage sql.NullString
|
||||
}
|
||||
|
||||
type Comment struct {
|
||||
ID int64
|
||||
Author *User
|
||||
Request *Request
|
||||
Author User
|
||||
Request Request
|
||||
CommentAt time.Time
|
||||
Content string
|
||||
}
|
||||
|
||||
type RequestService interface {
|
||||
Request(id int64) (*Request, error)
|
||||
UserRequests(u *User, completed bool) ([]*Request, error)
|
||||
GuildRequests(g *Guild, completed bool) ([]*Request, error)
|
||||
CreateRequest(r *Request) (*Request, error)
|
||||
UpdateRequest(r *Request) (*Request, error)
|
||||
DeleteRequest(r *Request) error
|
||||
Comment(id int64) (*Comment, error)
|
||||
RequestComments(r *Request) ([]*Comment, error)
|
||||
RequestCommentCount(r *Request) (int, error)
|
||||
CreateComment(c *Comment) (*Comment, error)
|
||||
DeleteComment(c *Comment) error
|
||||
Request(id int64) (Request, error)
|
||||
UserRequests(u User, completed bool) ([]Request, error)
|
||||
GuildRequests(g Guild, completed bool) ([]Request, error)
|
||||
CreateRequest(r Request) (Request, error)
|
||||
UpdateRequest(r Request) (Request, error)
|
||||
DeleteRequest(r Request) error
|
||||
Comment(id int64) (Comment, error)
|
||||
RequestComments(r Request) ([]Comment, error)
|
||||
RequestCommentCount(r Request) (int, error)
|
||||
CreateComment(c Comment) (Comment, error)
|
||||
DeleteComment(c Comment) error
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# Keep required jobs alive; only skip reviewed non-runtime documentation paths.
|
||||
set -euo pipefail
|
||||
base="${DELIVERY_BASE:-}"
|
||||
head="$(git rev-parse HEAD)"
|
||||
run=true
|
||||
if [[ "${DELIVERY_REF:-}" != refs/tags/* && "$head" == "${DELIVERY_SHA:-}" && "${DELIVERY_EVENT:-}" =~ ^(push|pull_request)$ && "$base" =~ ^[0-9a-f]{40}$ && "$base" != 0000000000000000000000000000000000000000 ]]; then
|
||||
if ! git cat-file -e "$base^{commit}" 2>/dev/null; then
|
||||
if [[ -n "${DELIVERY_FETCH_TOKEN:-}" ]]; then
|
||||
git -c "http.extraHeader=Authorization: token ${DELIVERY_FETCH_TOKEN}" fetch --quiet --depth=1 origin "$base" >/dev/null 2>&1 || true
|
||||
else
|
||||
git fetch --quiet --depth=1 origin "$base" >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
if git cat-file -e "$base^{commit}" 2>/dev/null; then
|
||||
paths="$(mktemp)"
|
||||
trap 'rm -f -- "$paths"' EXIT
|
||||
# Snapshot comparison is conservative when main advanced during a PR.
|
||||
# Both rename sides remain visible, including names containing newlines.
|
||||
if git diff --no-renames --name-only -z "$base" "$head" > "$paths"; then
|
||||
run=false
|
||||
while IFS= read -r -d '' path; do
|
||||
case "$path" in
|
||||
README.md|CHANGELOG.md|LICENSE|LICENSE.md) ;;
|
||||
*) run=true; break ;;
|
||||
esac
|
||||
done < "$paths"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ "$run" == false ]]; then
|
||||
echo 'Only reviewed non-runtime documentation changed; build and validation are not applicable.'
|
||||
else
|
||||
echo 'Runtime, unknown inputs, or unavailable event history: run required validation.'
|
||||
fi
|
||||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||||
echo "run=$run" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
printf '%s\n' "$run"
|
||||
@@ -7,17 +7,20 @@ type Server struct {
|
||||
Port int
|
||||
Password string
|
||||
AlertsChannel *Channel
|
||||
Guild *Guild
|
||||
Guild Guild
|
||||
InfoChannel *Channel
|
||||
InfoMessage *Message
|
||||
SettingsMessage *Message
|
||||
FTPPort int
|
||||
FTPUser string
|
||||
FTPPass string
|
||||
}
|
||||
|
||||
type ServerService interface {
|
||||
ServerByID(id int) (*Server, error)
|
||||
ServerByName(name string) (*Server, error)
|
||||
CreateServer(s *Server) (*Server, error)
|
||||
DeleteServer(s *Server) error
|
||||
UpdateServer(s *Server) (*Server, error)
|
||||
GuildServers(g *Guild) ([]*Server, error)
|
||||
ServerByID(id int) (Server, error)
|
||||
ServerByName(name string, guild Guild) (Server, error)
|
||||
CreateServer(s Server) (Server, error)
|
||||
DeleteServer(s Server) error
|
||||
UpdateServer(s Server) (Server, error)
|
||||
GuildServers(g Guild) ([]Server, error)
|
||||
}
|
||||
|
||||
@@ -11,8 +11,10 @@ type User struct {
|
||||
}
|
||||
|
||||
type UserService interface {
|
||||
User(id string) (*User, error)
|
||||
CreateUser(u *User) (*User, error)
|
||||
DeleteUser(u *User) error
|
||||
UpdateUser(u *User) (*User, error)
|
||||
User(id string) (User, error)
|
||||
CreateUser(u User) (User, error)
|
||||
DeleteUser(u User) error
|
||||
UpdateUser(u User) (User, error)
|
||||
GetOrCreateUser(id string) (User, error)
|
||||
GetBySteamID(steamID string) (User, error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user