Compare commits

..

62 Commits

Author SHA1 Message Date
Dustin Pianalto
aea88c632e Add pgbouncer
Some checks failed
CI / build (push) Has been cancelled
2021-10-10 20:26:32 -08:00
Dustin Pianalto
dd60c9067b Add pgbouncer
Some checks failed
CI / build (push) Has been cancelled
2021-10-10 19:56:13 -08:00
Dustin Pianalto
03818d6102 Add pgbouncer
Some checks failed
CI / build (push) Has been cancelled
2021-10-10 19:31:01 -08:00
Dustin Pianalto
4e1ca8a700 Add pgbouncer
Some checks failed
CI / build (push) Has been cancelled
2021-10-10 19:23:52 -08:00
Dustin Pianalto
be0ed2a40d Add pgbouncer
Some checks failed
CI / build (push) Has been cancelled
2021-10-10 18:37:26 -08:00
Dustin Pianalto
af07976c78 Add pgbouncer
Some checks failed
CI / build (push) Has been cancelled
2021-10-10 18:18:40 -08:00
Dusty.P
fb4f43c234
Update deployment.yml
Some checks failed
CI / build (push) Has been cancelled
2021-10-05 23:45:08 -08:00
Dustin Pianalto
34a6c0cdd3 Merge branch 'master' of github.com:dustinpianalto/Goff
Some checks failed
CI / build (push) Has been cancelled
2021-10-05 23:34:30 -08:00
Dusty.P
a6cde5c69c
Update main.yml
Some checks failed
CI / build (push) Has been cancelled
2021-10-05 23:09:00 -08:00
Dustin Pianalto
a2420f19c9 Update deployment
Some checks failed
CI / build (push) Has been cancelled
2021-10-02 16:18:48 -08:00
Dustin Pianalto
2019dc4643 Update GH action and deployment
Some checks failed
CI / build (push) Has been cancelled
2021-10-02 14:13:28 -08:00
Dustin Pianalto
9bb35bb30a Don't check roles when adding
Some checks failed
CI / build (push) Has been cancelled
2021-08-18 14:24:20 -08:00
Dustin Pianalto
3cad5680b0 Add guild member update handler
Some checks failed
CI / build (push) Has been cancelled
2021-08-18 11:26:25 -08:00
Dustin Pianalto
f97494626f Don't add auto role until after membership check
Some checks failed
CI / build (push) Has been cancelled
2021-08-18 11:01:24 -08:00
Dustin Pianalto
b5a55a1b77 Don't add auto role until after membership check 2021-08-18 11:00:31 -08:00
Dustin Pianalto
02b5842107 Add milliseconds to timestamp
Some checks failed
CI / build (push) Has been cancelled
2021-07-23 12:54:23 -08:00
Dustin Pianalto
d345044b3a Add milliseconds to timestamp
Some checks failed
CI / build (push) Has been cancelled
2021-07-23 12:39:35 -08:00
Dustin Pianalto
b3aff0828c Add snowflake command
Some checks failed
CI / build (push) Has been cancelled
2021-07-23 12:34:09 -08:00
Dustin Pianalto
3d4518f961 Don't log message edits if the After is blank (problem with message embeds)
Some checks failed
CI / build (push) Has been cancelled
2021-07-01 19:54:12 -08:00
Dustin Pianalto
37e8fa52af Fix bug in getting tasks
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 12:58:42 -08:00
Dustin Pianalto
a370c76ba4 Add Auto Role Feature
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 02:20:08 -08:00
Dustin Pianalto
2fe9de279d Add Auto Role Feature
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 02:15:42 -08:00
Dustin Pianalto
33776b1129 Add Auto Role Feature
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 02:02:47 -08:00
Dustin Pianalto
733cd87896 Add Auto Role Feature
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 01:58:31 -08:00
Dustin Pianalto
ebf20670df Add Auto Role Feature
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 01:47:22 -08:00
Dustin Pianalto
14c5705473 Add Auto Role Feature
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 01:44:22 -08:00
Dustin Pianalto
c72dcd0ec3 Update actions
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 01:37:41 -08:00
Dustin Pianalto
61d500946e Add Auto Role Feature
Some checks failed
CI / build (push) Has been cancelled
2021-06-22 01:29:38 -08:00
Dustin Pianalto
65bb218260 Initial DO workflow test
Some checks failed
CI / build (push) Has been cancelled
2021-01-13 00:15:42 -09:00
Dustin Pianalto
d8d90a8414 Initial DO workflow test
Some checks failed
CI / build (push) Has been cancelled
2021-01-12 23:29:51 -09:00
Dustin Pianalto
2e95aa0234 Initial DO workflow test
Some checks failed
CI / build (push) Has been cancelled
2021-01-12 23:20:04 -09:00
Dustin Pianalto
480f5b6cc9 Initial DO workflow test
Some checks failed
CI / build (push) Has been cancelled
2021-01-12 23:18:19 -09:00
Dustin Pianalto
97793ad622 Initial DO workflow test
Some checks failed
CI / build (push) Has been cancelled
2021-01-12 23:16:29 -09:00
Dusty.P
d581a9bf32
Merge pull request #8 from dustinpianalto/development
Some checks failed
CI / build (push) Has been cancelled
Add action to deploy to ECS after image is built
2020-10-11 22:33:27 -08:00
Dustin Pianalto
13f80a6972 Add action to deploy to ECS after image is built
Some checks failed
CI / build (push) Has been cancelled
2020-10-11 22:23:05 -08:00
Dusty.P
20bd455a44
Merge pull request #7 from dustinpianalto/development
Some checks failed
CI / build (push) Has been cancelled
Add user to guild on user create
2020-10-09 23:48:07 -08:00
Dustin Pianalto
cadef92efb Add user to guild on user create 2020-10-09 23:43:56 -08:00
Dusty.P
f6f020ff48
Merge pull request #6 from dustinpianalto/development
Some checks failed
CI / build (push) Has been cancelled
Attempt to insert user into db before creating tag
2020-10-09 23:26:02 -08:00
Dustin Pianalto
a93139fcf2 Attempt to insert user into db before creating tag 2020-10-09 23:21:35 -08:00
Dusty.P
d9ddfaf2cc
Merge pull request #5 from dustinpianalto/development
Some checks failed
CI / build (push) Has been cancelled
Deploy v0.0.8
2020-10-09 21:56:52 -08:00
Dustin Pianalto
05d4096766 Change default prefix back for main 2020-10-09 21:46:28 -08:00
Dustin Pianalto
6a33cceebb Reorg and add services 2020-10-09 21:34:47 -08:00
Dustin Pianalto
5cd626a5a4 Merge branch 'development' of github.com:dustinpianalto/Goff into development 2020-09-23 12:05:05 -08:00
Dustin Pianalto
e2f25eaab4 Remove unnecessary rpn package
the rpn parser was moved to it's own repo and already imported in go.mod
2020-09-23 12:04:52 -08:00
Dusty.P
ea058baff5
Create README.md 2020-09-23 11:43:54 -08:00
Dustin Pianalto
d9e1efbaf0 Repo Reorg 2020-09-18 18:39:51 -08:00
Dustin Pianalto
af506f828d Change db variable name 2020-09-14 12:42:25 -08:00
Dustin Pianalto
5c42616a3a Adjust Connection Pool 2020-09-14 12:36:14 -08:00
Dustin Pianalto
6cc5e042d5 Start Restructure of project 2020-09-14 00:10:24 -08:00
Dusty.P
03e6f069c9
Merge pull request #4 from dustinpianalto/development
Add sar and ping role when posting puzzle
2020-09-02 01:54:34 -08:00
Dustin Pianalto
4db28f5c0b Add sar and ping role when posting puzzle
Some checks failed
CI / build (push) Has been cancelled
2020-09-02 01:49:29 -08:00
Dusty.P
d876f4ced9
Merge pull request #3 from dustinpianalto/development
Some checks failed
CI / build (push) Has been cancelled
Fix addtag removing newlines
2020-09-01 21:40:46 -08:00
Dustin Pianalto
fb4d7977aa Fix addtag removing newlines 2020-09-01 21:36:14 -08:00
Dusty.P
68a02e2f24
Merge pull request #2 from dustinpianalto/development
Adding actions and reorg
2020-08-30 22:08:47 -08:00
Dustin Pianalto
30394b35e5 Merge branch 'master' into development
Some checks failed
CI / build (push) Has been cancelled
2020-08-30 21:53:25 -08:00
Dustin Pianalto
87961c5081 Remove branch check and also push latest tag 2020-08-30 17:57:19 -08:00
Dustin Pianalto
562ec6acaf Test github.ref to get branch name
Some checks failed
CI / build (push) Has been cancelled
2020-08-30 17:09:13 -08:00
Dustin Pianalto
3169953f3f Test github.ref to get branch name
Some checks failed
CI / build (push) Has been cancelled
2020-08-30 17:07:37 -08:00
Dustin Pianalto
d119425236 revert to previous method of getting branch name
Some checks failed
CI / build (push) Has been cancelled
2020-08-30 16:51:00 -08:00
Dustin Pianalto
ce1bbbc445 Check branch name 2020-08-30 16:46:05 -08:00
Dusty.P
35882993c2
Update init.go 2020-08-29 18:42:38 -08:00
Dusty.P
85bcb31d56
Merge pull request #1 from dustinpianalto/development
Add Puzzle parser
2020-08-29 18:37:59 -08:00
47 changed files with 2558 additions and 1319 deletions

View File

@ -4,16 +4,12 @@ name: CI
# with a tag like v1.0.0 or v1.0.0-dev
on:
push:
branches:
- master
- development
tags:
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-[a-zA-Z]+
jobs:
build:
if: github.event.base_ref == 'refs/heads/master' || github.event.base_ref == 'refs/heads/development'
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
@ -21,28 +17,48 @@ jobs:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
with:
repositories: goff
- name: Get Version
id: get_version
uses: battila7/get-version-action@v2.0.0
- name: Build, tag, and push image to Amazon ECR
- name: install buildx
id: buildx
uses: crazy-max/ghaction-docker-buildx@v1
with:
version: latest
- name: Docker Login
# You may pin to the exact commit or the version.
# uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
uses: docker/login-action@v1.10.0
with:
registry: ${{ secrets.DR_URL }}
# Username used to log against the Docker registry
username: ${{ secrets.DH_USERNAME }}
# Password or personal access token used to log against the Docker registry
password: ${{ secrets.DH_PASSWORD }}
# Log out from the Docker registry at the end of a job
logout: true
- name: Docker Build & Push
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: goff
IMAGE_TAG: ${{ steps.get_version.outputs.version-without-v }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker buildx build --push \
--tag ${{ secrets.DR_URL }}/goff:$IMAGE_TAG \
--platform linux/amd64,linux/arm/v7,linux/arm64 .
- name: Update deployment file
run: TAG=${{ steps.get_version.outputs.version-without-v }} && sed -i 's|<IMAGE>|${{ secrets.DR_URL }}/goff:'${TAG}'|' $GITHUB_WORKSPACE/deployment.yml
- uses: azure/k8s-set-context@v1
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBE_CONFIG }}
id: setcontext
- name: Deploy to Kubernetes
run: kubectl apply -f $GITHUB_WORKSPACE/deployment.yml
- name: Verify deployment
run: kubectl rollout status deployment/goff -n discord-bots

View File

@ -7,9 +7,9 @@ COPY ./go.sum .
RUN go mod download
COPY . .
RUN go install github.com/dustinpianalto/goff
RUN go install github.com/dustinpianalto/goff/...
CMD [ "go", "run", "goff.go"]
CMD [ "go", "run", "cmd/goff/main.go"]
from alpine

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Goff
A discord bot for fun

BIN
cmd/goff/main Executable file

Binary file not shown.

152
cmd/goff/main.go Normal file
View File

@ -0,0 +1,152 @@
package main
import (
"fmt"
"log"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/exts"
"github.com/dustinpianalto/goff/internal/exts/guild_management"
"github.com/dustinpianalto/goff/internal/exts/logging"
"github.com/dustinpianalto/goff/internal/exts/tasks"
"github.com/dustinpianalto/goff/internal/exts/user_management"
"github.com/dustinpianalto/goff/internal/postgres"
"github.com/dustinpianalto/goff/internal/services"
"github.com/dustinpianalto/goff/pkg/email"
//"github.com/MikeModder/anpan"
"os"
"os/signal"
"syscall"
"github.com/bwmarrin/discordgo"
)
var (
Token string
)
//func init() {
// flag.StringVar(&Token, "t", "", "Bot Token")
// flag.Parse()
//}
func main() {
Token = os.Getenv("DISCORDGO_TOKEN")
dg, err := discordgo.New("Bot " + Token)
if err != nil {
fmt.Println("There was an error when creating the Discord Session, ", err)
return
}
dg.State.MaxMessageCount = 100
dg.StateEnabled = true
dg.Identify = discordgo.Identify{
Intents: discordgo.MakeIntent(discordgo.IntentsAll),
}
postgres.ConnectDatabase(os.Getenv("DATABASE_URL"))
postgres.InitializeDatabase()
//utils.LoadTestData()
us := &postgres.UserService{DB: postgres.DB}
gs := &postgres.GuildService{DB: postgres.DB}
rs := &postgres.RoleService{DB: postgres.DB}
//prefixes := []string{
// "Go.",
//}
owners := []string{
"351794468870946827",
}
manager := disgoman.CommandManager{
Prefixes: getPrefixes,
Owners: owners,
StatusManager: disgoman.GetDefaultStatusManager(),
ErrorChannel: make(chan disgoman.CommandError, 10),
Commands: make(map[string]*disgoman.Command),
IgnoreBots: true,
CheckPermissions: false,
}
// Add Command Handlers
exts.AddCommandHandlers(&manager)
services.InitalizeServices(us, gs, rs)
//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.OnGuildMemberAdd)
dg.AddHandler(user_management.OnGuildMemberRemoveLogging)
dg.AddHandler(user_management.OnGuildMemberRemove)
dg.AddHandler(user_management.OnGuildMemberUpdate)
err = dg.Open()
if err != nil {
fmt.Println("There was an error opening the connection, ", err)
return
}
// Start the Error handler in a goroutine
go ErrorHandler(manager.ErrorChannel)
// Start the Logging handler in a goroutine
go logging.LoggingHandler(logging.LoggingChannel)
// Start the task handler in a goroutine
go tasks.ProcessTasks(dg, 1)
go email.RecieveEmail(dg)
fmt.Println("The Bot is now running.")
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
<-sc
fmt.Println("Shutting Down...")
err = dg.Close()
if err != nil {
fmt.Println(err)
}
}
func getPrefixes(guildID string) []string {
queryString := "Select prefix from prefixes p, x_guilds_prefixes xgp where xgp.guild_id = $1 and xgp.prefix_id = p.id"
rows, err := postgres.DB.Query(queryString, guildID)
if err != nil {
log.Println(err)
return []string{"Go.", "go."}
}
var prefixes []string
for rows.Next() {
var prefix string
err = rows.Scan(&prefix)
if err != nil {
log.Println(err)
return []string{"Go.", "go."}
}
prefixes = append(prefixes, prefix)
}
if len(prefixes) == 0 {
prefixes = append(prefixes, "Go.", "go.")
}
return prefixes
}
func ErrorHandler(ErrorChan chan disgoman.CommandError) {
for ce := range ErrorChan {
msg := ce.Message
if msg == "" {
msg = ce.Error.Error()
}
_, _ = ce.Context.Send(msg)
fmt.Println(ce.Error)
}
}

82
deployment.yml Normal file
View File

@ -0,0 +1,82 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: goff
namespace: discord-bots
labels:
app: goff
spec:
replicas: 1
selector:
matchLabels:
app: goff
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
minReadySeconds: 120
template:
metadata:
labels:
app: goff
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: goff
key: pgbouncer_url
- name: SERVER_TLS_SSLMODE
valueFrom:
secretKeyRef:
name: goff
key: pgbouncer_ssl
- name: AUTH_TYPE
valueFrom:
secretKeyRef:
name: goff
key: pgbouncer_auth
ports:
- containerPort: 5432
- name: goff
image: <IMAGE>
resources:
requests:
memory: "512Mi"
cpu: "1"
limits:
memory: "1Gi"
cpu: "2"
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: goff
key: database_url
- name: DISCORDGO_TOKEN
valueFrom:
secretKeyRef:
name: goff
key: discord_token
- name: GOFF_EMAIL_USERNAME
valueFrom:
secretKeyRef:
name: goff
key: email_username
- name: GOFF_EMAIL_PASSWORD
valueFrom:
secretKeyRef:
name: goff
key: email_password
imagePullSecrets:
- name: registry-1

View File

@ -1,32 +0,0 @@
version: "3"
services:
# goff-db:
# image: postgres
# ports:
# - "5432:5432"
# volumes:
# - "${PWD}/postgres.conf:/etc/postgresql/postgresql.conf"
# - "goff-db:/var/lib/postgresql/data:rw"
# env_file: ${PWD}/.env
goff:
build:
context: .
dockerfile: "${PWD}/Dockerfile"
env_file: ${PWD}/.env
logging:
driver: awslogs
options:
awslogs-region: us-east-1
awslogs-group: "/docker/goff/production"
# depends_on:
# - goff-db
environment:
- DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?sslmode=disable
# links:
# - goff-db:goff.db
#volumes:
# goff-db:
# external: true

View File

@ -1,32 +0,0 @@
version: "3"
services:
# goff-db:
# image: postgres
# ports:
# - "5432:5432"
# volumes:
# - "${PWD}/postgres.conf:/etc/postgresql/postgresql.conf"
# - "goff-db:/var/lib/postgresql/data:rw"
# env_file: ${PWD}/.env
goff:
build:
context: .
dockerfile: "${PWD}/Dockerfile"
env_file: ${PWD}/.env
# logging:
# driver: awslogs
# options:
# awslogs-region: us-east-1
# awslogs-group: "/docker/goff/production"
# depends_on:
# - goff-db
environment:
- DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?sslmode=disable
# links:
# - goff-db:goff.db
#volumes:
# goff-db:
# external: true

View File

@ -1,84 +0,0 @@
package exts
import (
"fmt"
"strconv"
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/rpnparse"
)
func interleave(ctx disgoman.Context, args []string) {
if len(args) == 2 {
x, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
return
}
y, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
return
}
var z = int64(0)
for i := 0; i < 64; i++ {
x_masked_i := x & (1 << i)
y_masked_i := y & (1 << i)
z |= x_masked_i << i
z |= y_masked_i << (i + 1)
}
ctx.Send(fmt.Sprintf("%v", z))
}
}
func deinterleave(ctx disgoman.Context, args []string) {
if len(args) == 1 {
z, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
return
}
var x = int64(0)
var y = int64(0)
i := 0
for z > 0 {
x |= (z & 1) << i
z >>= 1
y |= (z & 1) << i
z >>= 1
i++
}
ctx.Send(fmt.Sprintf("(%v, %v)", x, y))
}
}
func generateRPNCommand(ctx disgoman.Context, args []string) {
rpn, err := rpnparse.GenerateRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(rpn)
}
func parseRPNCommand(ctx disgoman.Context, args []string) {
res, err := rpnparse.ParseRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(fmt.Sprintf("The result is: %v", res))
}
func solveCommand(ctx disgoman.Context, args []string) {
rpn, err := rpnparse.GenerateRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
res, err := rpnparse.ParseRPN(strings.Split(rpn, " "))
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(fmt.Sprintf("The result is: %v", res))
}

View File

@ -1,290 +0,0 @@
package exts
import (
"fmt"
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
)
// Guild management commands
func loggingChannel(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := utils.Database.Exec("UPDATE guilds SET logging_channel='' WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Logging Channel Updated.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
_, err = utils.Database.Exec("UPDATE guilds SET logging_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Logging Channel Updated.")
}
func getLoggingChannel(ctx disgoman.Context, _ []string) {
var channelID string
row := utils.Database.QueryRow("SELECT logging_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The logging channel is not set.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The logging channel is currently %s", channel.Mention()))
return
}
func welcomeChannel(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := utils.Database.Exec("UPDATE guilds SET welcome_channel='' WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Welcomer Disabled.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
_, err = utils.Database.Exec("UPDATE guilds SET welcome_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Welcome Channel Updated.")
return
}
func getWelcomeChannel(ctx disgoman.Context, _ []string) {
var channelID string
row := utils.Database.QueryRow("SELECT welcome_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The welcomer is disabled.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The welcome channel is currently %s", channel.Mention()))
}
func addGuildCommand(ctx disgoman.Context, args []string) {
var guildID string
row := utils.Database.QueryRow("SELECT id FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&guildID)
if err == nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "This guild is already in my database",
Error: err,
}
return
}
_, err = utils.Database.Query("INSERT INTO guilds (id) VALUES ($1)", ctx.Guild.ID)
if err != nil {
fmt.Println(err)
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "There was a problem inserting this guild into the database",
Error: err,
}
return
}
_, _ = ctx.Send("This guild has been added.")
}
func puzzleChannel(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := utils.Database.Exec("UPDATE guilds SET puzzle_channel='' WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Channel Updated.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
_, err = utils.Database.Exec("UPDATE guilds SET puzzle_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Channel Updated.")
}
func getPuzzleChannel(ctx disgoman.Context, _ []string) {
var channelID string
row := utils.Database.QueryRow("SELECT puzzle_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The puzzle channel is not set.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The puzzle channel is currently %s", channel.Mention()))
return
}

View File

@ -1,234 +0,0 @@
package exts
import (
"github.com/dustinpianalto/disgoman"
)
func AddCommandHandlers(h *disgoman.CommandManager) {
// Arguments:
// name - command name - string
// desc - command description - string
// owneronly - only allow owners to run - bool
// hidden - hide command from non-owners - bool
// 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(&disgoman.Command{
Name: "ping",
Aliases: nil,
Description: "Check the bot's ping",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: pingCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "say",
Aliases: nil,
Description: "Repeat a message",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
SanitizeEveryone: true,
Invoke: sayCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "user",
Aliases: nil,
Description: "Get user info",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: userCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "git",
Aliases: nil,
Description: "Show my github link",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: gitCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "tag",
Aliases: nil,
Description: "Get a tag",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: tagCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "addtag",
Aliases: nil,
Description: "Add a tag",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
SanitizeEveryone: true,
Invoke: addTagCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "invite",
Aliases: nil,
Description: "Get the invite link for this bot or others",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: inviteCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "P",
Aliases: nil,
Description: "Interpret a P\" program and return the results",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: pCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "set-logging-channel",
Aliases: []string{"slc"},
Description: "Set the channel logging messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: loggingChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "get-logging-channel",
Aliases: []string{"glc"},
Description: "Gets the channel logging messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getLoggingChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "set-welcome-channel",
Aliases: []string{"swc"},
Description: "Set the channel welcome messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: welcomeChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "get-welcome-channel",
Aliases: []string{"gwc"},
Description: "Gets the channel welcome messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getWelcomeChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "kick",
Aliases: nil,
Description: "Kicks the given user with the given reason",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionKickMembers,
Invoke: kickUserCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "addGuild",
Aliases: nil,
Description: "Adds the current guild to the database",
OwnerOnly: true,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: addGuildCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "ban",
Aliases: []string{"ban-no-delete"},
Description: "Bans the given user with the given reason",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionBanMembers,
Invoke: banUserCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "unban",
Aliases: nil,
Description: "Unbans the given user",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionBanMembers,
Invoke: unbanUserCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "remind",
Aliases: nil,
Description: "Remind me at a later time",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: addReminderCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "encode",
Aliases: []string{"e"},
Description: "Encode 2 numbers",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: interleave,
})
_ = h.AddCommand(&disgoman.Command{
Name: "decode",
Aliases: []string{"d"},
Description: "Decode 1 number into 2",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: deinterleave,
})
_ = h.AddCommand(&disgoman.Command{
Name: "set-puzzle-channel",
Aliases: []string{"spc"},
Description: "Set the channel puzzle messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: puzzleChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "get-puzzle-channel",
Aliases: []string{"gpc"},
Description: "Gets the channel puzzle messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getPuzzleChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "RPN",
Aliases: []string{"rpn"},
Description: "Convert infix to rpn",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: generateRPNCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "ParseRPN",
Aliases: []string{"PRPN", "prpn"},
Description: "Parse RPN string and return the result",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: parseRPNCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "solve",
Aliases: []string{"math", "infix"},
Description: "Solve infix equation and return the result",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: solveCommand,
})
}

16
go.mod
View File

@ -3,12 +3,18 @@ module github.com/dustinpianalto/goff
go 1.14
require (
github.com/bwmarrin/discordgo v0.20.3-0.20200525154655-ca64123b05de
github.com/dustinpianalto/disgoman v0.0.10
github.com/AlekSi/pointer v1.1.0 // indirect
github.com/bwmarrin/discordgo v0.23.2
github.com/dustinpianalto/disgoman v0.0.21
github.com/dustinpianalto/rpnparse v1.0.1
github.com/emersion/go-imap v1.0.5
github.com/emersion/go-message v0.12.0
github.com/emersion/go-imap v1.1.0
github.com/emersion/go-message v0.15.0
github.com/gorilla/websocket v1.4.2 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/lib/pq v1.3.0
github.com/lib/pq v1.10.2
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/sys v0.0.0-20210818153620-00dd8d7831e7 // indirect
golang.org/x/text v0.3.7 // indirect
)

47
go.sum
View File

@ -1,35 +1,68 @@
github.com/AlekSi/pointer v1.0.0 h1:KWCWzsvFxNLcmM5XmiqHsGTTsuwZMsLFwWF9Y+//bNE=
github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8=
github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI=
github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE=
github.com/bwmarrin/discordgo v0.20.2 h1:nA7jiTtqUA9lT93WL2jPjUp8ZTEInRujBdx1C9gkr20=
github.com/bwmarrin/discordgo v0.20.2/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
github.com/bwmarrin/discordgo v0.20.3-0.20200525154655-ca64123b05de h1:0TOVVwGrmv0PA+/vuekQIRY9jJ9rcHYnicIaph3/4S4=
github.com/bwmarrin/discordgo v0.20.3-0.20200525154655-ca64123b05de/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIxDdFM=
github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4=
github.com/bwmarrin/discordgo v0.23.2/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
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/dustinpianalto/disgoman v0.0.10 h1:UzmvMpOi4peF59tXGaNfVU+ePHs1hILa6gQbjxjWQ9g=
github.com/dustinpianalto/disgoman v0.0.10/go.mod h1:v3FM6n+4dH9XlvO+IDx6MN3DUnGq6YVDBvy1A1k202g=
github.com/dustinpianalto/disgoman v0.0.12 h1:dLptU2ZTUZJaLBOKeE6qjuL8gqdAr6ehHSOtfHmUpL8=
github.com/dustinpianalto/disgoman v0.0.12/go.mod h1:v3FM6n+4dH9XlvO+IDx6MN3DUnGq6YVDBvy1A1k202g=
github.com/dustinpianalto/disgoman v0.0.14 h1:hsk56JATBE5eH5GPCDGeiTdYxok4m+edSYiYz5Uj8uo=
github.com/dustinpianalto/disgoman v0.0.14/go.mod h1:v3FM6n+4dH9XlvO+IDx6MN3DUnGq6YVDBvy1A1k202g=
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/disgoman v0.0.21 h1:GfT149ymB/7BAJaKn4DNB66zBAbSB1tdn3E26NGok0o=
github.com/dustinpianalto/disgoman v0.0.21/go.mod h1:v3FM6n+4dH9XlvO+IDx6MN3DUnGq6YVDBvy1A1k202g=
github.com/dustinpianalto/rpnparse v1.0.1 h1:ZvH1/RIe5hh3RGSAXOgtngEDHNPTF+DMh88XFWpQjzY=
github.com/dustinpianalto/rpnparse v1.0.1/go.mod h1:SzFbQb+Eed5gYCtDu/SYEXXwdPtWkDg9oaL1xQtN1BY=
github.com/emersion/go-imap v1.0.5 h1:8xg/d2wo2BBP3AEP5AOaM/6i8887RGyVW2st/IVHWUw=
github.com/emersion/go-imap v1.0.5/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU=
github.com/emersion/go-imap v1.1.0 h1:hAW8Dbi/AwiVO5Wi40FTVuCzVrTmwtEK6De9GSoOy+Y=
github.com/emersion/go-imap v1.1.0/go.mod h1:0hCeak4mA2z9hICM20jeqN6fyV0Oad0lZTyeeAyUS6o=
github.com/emersion/go-message v0.11.1/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY=
github.com/emersion/go-message v0.12.0 h1:mZnv35eZ6lB6EftTQBgYXspOH0FQdhpFhSUhA9i6/Zg=
github.com/emersion/go-message v0.12.0/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY=
github.com/emersion/go-message v0.14.1/go.mod h1:N1JWdZQ2WRUalmdHAX308CWBq747VJ8oUorFI3VCBwU=
github.com/emersion/go-message v0.15.0 h1:urgKGqt2JAc9NFJcgncQcohHdiYb803YTH9OQwHBHIY=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b h1:uhWtEWBHgop1rqEk2klKaxPAkVDCXexai6hSuRQ7Nvs=
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe h1:40SWqY0zE3qCi6ZrtTf5OUdNm5lDnGnjRSq9GgmeTrg=
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/martinlindhe/base36 v1.0.0 h1:eYsumTah144C0A8P1T/AVSUk5ZoLnhfYFM3OGQxB52A=
github.com/martinlindhe/base36 v1.0.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8=
github.com/martinlindhe/base36 v1.1.0 h1:cIwvvwYse/0+1CkUPYH5ZvVIYG3JrILmQEIbLuar02Y=
github.com/martinlindhe/base36 v1.1.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8=
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254 h1:JYoQR67E1vv1WGoeW8DkdFs7vrIEe/5wP+qJItd5tUE=
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254/go.mod h1:DPucAeQGDPUzYUt+NaWw6qsF5SFapWWToxEiVDh2aV0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -37,6 +70,20 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
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-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210818153620-00dd8d7831e7 h1:/bmDWM82ZX7TawqxuI8kVjKI0TXHdSY6pHJArewwHtU=
golang.org/x/sys v0.0.0-20210818153620-00dd8d7831e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5-0.20201125200606-c27b9fd57aec/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

139
goff.go
View File

@ -1,136 +1,9 @@
package main
package goff
import (
"fmt"
"log"
import "github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/events"
"github.com/dustinpianalto/goff/exts"
"github.com/dustinpianalto/goff/utils"
//"github.com/MikeModder/anpan"
"os"
"os/signal"
"syscall"
"github.com/bwmarrin/discordgo"
)
var (
Token string
)
//func init() {
// flag.StringVar(&Token, "t", "", "Bot Token")
// flag.Parse()
//}
func main() {
Token = os.Getenv("DISCORDGO_TOKEN")
dg, err := discordgo.New("Bot " + Token)
if err != nil {
fmt.Println("There was an error when creating the Discord Session, ", err)
return
}
dg.State.MaxMessageCount = 100
utils.ConnectDatabase(os.Getenv("DATABASE_URL"))
utils.InitializeDatabase()
//utils.LoadTestData()
//prefixes := []string{
// "Go.",
//}
owners := []string{
"351794468870946827",
}
// Arguments are:
// prefixes - []string
// owner ids - []string
// ignore bots - bool
// check perms - bool
handler := disgoman.CommandManager{
Prefixes: getPrefixes,
Owners: owners,
StatusManager: disgoman.GetDefaultStatusManager(),
ErrorChannel: make(chan disgoman.CommandError, 10),
Commands: make(map[string]*disgoman.Command),
IgnoreBots: true,
CheckPermissions: false,
}
// Add Command Handlers
exts.AddCommandHandlers(&handler)
//if _, ok := handler.Commands["help"]; !ok {
// handler.AddDefaultHelpCommand()
//}
dg.AddHandler(handler.OnMessage)
dg.AddHandler(handler.StatusManager.OnReady)
dg.AddHandler(events.OnMessageUpdate)
dg.AddHandler(events.OnMessageDelete)
dg.AddHandler(events.OnGuildMemberAddLogging)
dg.AddHandler(events.OnGuildMemberRemoveLogging)
err = dg.Open()
if err != nil {
fmt.Println("There was an error opening the connection, ", err)
return
}
// Start the Error handler in a goroutine
go ErrorHandler(handler.ErrorChannel)
// Start the Logging handler in a goroutine
go utils.LoggingHandler(utils.LoggingChannel)
// Start the task handler in a goroutine
go utils.ProcessTasks(dg, 1)
go utils.RecieveEmail(dg)
fmt.Println("The Bot is now running.")
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
<-sc
fmt.Println("Shutting Down...")
err = dg.Close()
if err != nil {
fmt.Println(err)
}
}
func getPrefixes(guildID string) []string {
queryString := "Select prefix from prefixes p, x_guilds_prefixes xgp where xgp.guild_id = $1 and xgp.prefix_id = p.id"
rows, err := utils.Database.Query(queryString, guildID)
if err != nil {
log.Println(err)
return []string{"Go.", "go."}
}
var prefixes []string
for rows.Next() {
var prefix string
err = rows.Scan(&prefix)
if err != nil {
log.Println(err)
return []string{"Go.", "go."}
}
prefixes = append(prefixes, prefix)
}
return prefixes
}
func ErrorHandler(ErrorChan chan disgoman.CommandError) {
for ce := range ErrorChan {
msg := ce.Message
if msg == "" {
msg = ce.Error.Error()
}
_, _ = ce.Context.Send(msg)
fmt.Println(ce.Error)
}
type CommandManager struct {
UserService UserService
GuildService GuildService
disgoman.CommandManager
}

22
guild.go Normal file
View File

@ -0,0 +1,22 @@
package goff
import "database/sql"
type Guild struct {
ID string
WelcomeMessage string
GoodbyeMessage string
LoggingChannel string
WelcomeChannel string
PuzzleChannel string
PuzzleRole sql.NullString
Prefixes []string
}
type GuildService interface {
Guild(id string) (*Guild, error)
CreateGuild(g *Guild) error
DeleteGuild(g *Guild) error
GuildUsers(g *Guild) ([]*User, error)
UpdateGuild(g *Guild) error
}

View File

@ -1,4 +1,4 @@
package utils
package discord_utils
import (
"fmt"
@ -32,7 +32,7 @@ func ParseDateString(inTime time.Time) string {
} else {
dateString = "Now"
}
stamp := inTime.Format("2006-01-02 15:04:05")
stamp := inTime.Format("2006-01-02 15:04:05.000")
return fmt.Sprintf("%v\n%v", dateString, stamp)
}

View File

@ -1,4 +1,4 @@
package utils
package discord_utils
import "time"
@ -19,7 +19,10 @@ func ParseSnowflake(s int64) Snowflake {
PROCESS_ID_MASK = 0x1F000
INCREMENT_MASK = 0xFFF
)
creationTime := time.Unix(((s>>TIME_BITS_LOC)+DISCORD_EPOCH)/1000.0, 0)
t := (s >> TIME_BITS_LOC) + DISCORD_EPOCH
sec := t / 1000.0
nano := t % 1000.0 * 1000000.0
creationTime := time.Unix(sec, nano)
workerID := (s & WORKER_ID_MASK) >> WORKER_ID_LOC
processID := (s & PROCESS_ID_MASK) >> PROCESS_ID_LOC
increment := s & INCREMENT_MASK

134
internal/exts/fun/fun.go Normal file
View File

@ -0,0 +1,134 @@
package fun
import (
"fmt"
"strconv"
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/rpnparse"
)
var InterleaveCommand = &disgoman.Command{
Name: "encode",
Aliases: []string{"e"},
Description: "Encode 2 numbers",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: interleaveFunc,
}
func interleaveFunc(ctx disgoman.Context, args []string) {
if len(args) == 2 {
x, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
return
}
y, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
return
}
var z = int64(0)
for i := 0; i < 64; i++ {
x_masked_i := x & (1 << i)
y_masked_i := y & (1 << i)
z |= x_masked_i << i
z |= y_masked_i << (i + 1)
}
ctx.Send(fmt.Sprintf("%v", z))
}
}
var DeinterleaveCommand = &disgoman.Command{
Name: "decode",
Aliases: []string{"d"},
Description: "Decode 1 number into 2",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: deinterleaveFunc,
}
func deinterleaveFunc(ctx disgoman.Context, args []string) {
if len(args) == 1 {
z, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
return
}
var x = int64(0)
var y = int64(0)
i := 0
for z > 0 {
x |= (z & 1) << i
z >>= 1
y |= (z & 1) << i
z >>= 1
i++
}
ctx.Send(fmt.Sprintf("(%v, %v)", x, y))
}
}
var GenerateRPNCommand = &disgoman.Command{
Name: "RPN",
Aliases: []string{"rpn"},
Description: "Convert infix to rpn",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: generateRPNFunc,
}
func generateRPNFunc(ctx disgoman.Context, args []string) {
rpn, err := rpnparse.GenerateRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(rpn)
}
var ParseRPNCommand = &disgoman.Command{
Name: "ParseRPN",
Aliases: []string{"PRPN", "prpn"},
Description: "Parse RPN string and return the result",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: parseRPNFunc,
}
func parseRPNFunc(ctx disgoman.Context, args []string) {
res, err := rpnparse.ParseRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(fmt.Sprintf("The result is: %v", res))
}
var SolveCommand = &disgoman.Command{
Name: "solve",
Aliases: []string{"math", "infix"},
Description: "Solve infix equation and return the result",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: solveFunc,
}
func solveFunc(ctx disgoman.Context, args []string) {
rpn, err := rpnparse.GenerateRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
res, err := rpnparse.ParseRPN(strings.Split(rpn, " "))
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(fmt.Sprintf("The result is: %v", res))
}

View File

@ -0,0 +1,476 @@
package guild_management
import (
"database/sql"
"fmt"
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/postgres"
"github.com/dustinpianalto/goff/internal/services"
)
// Guild management commands
var SetLoggingChannelCommand = &disgoman.Command{
Name: "set-logging-channel",
Aliases: []string{"slc"},
Description: "Set the channel logging messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: setLoggingChannelFunc,
}
func setLoggingChannelFunc(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
guild, err := services.GuildService.Guild(ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
if idString == "" {
guild.LoggingChannel = idString
err = services.GuildService.UpdateGuild(guild)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Logging Channel Updated.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
guild.LoggingChannel = channel.ID
err = services.GuildService.UpdateGuild(guild)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Logging Channel Updated.")
}
var GetLoggingChannelCommand = &disgoman.Command{
Name: "get-logging-channel",
Aliases: []string{"glc"},
Description: "Gets the channel logging messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getLoggingChannelFunc,
}
func getLoggingChannelFunc(ctx disgoman.Context, _ []string) {
var channelID string
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The logging channel is not set.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The logging channel is currently %s", channel.Mention()))
return
}
var SetWelcomeChannelCommand = &disgoman.Command{
Name: "set-welcome-channel",
Aliases: []string{"swc"},
Description: "Set the channel welcome messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: setWelcomeChannelFunc,
}
func setWelcomeChannelFunc(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := postgres.DB.Exec("UPDATE guilds SET welcome_channel='' WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Welcomer Disabled.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("UPDATE guilds SET welcome_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Welcome Channel Updated.")
return
}
var GetWelcomeChannelCommand = &disgoman.Command{
Name: "get-welcome-channel",
Aliases: []string{"gwc"},
Description: "Gets the channel welcome messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getWelcomeChannelFunc,
}
func getWelcomeChannelFunc(ctx disgoman.Context, _ []string) {
var channelID string
row := postgres.DB.QueryRow("SELECT welcome_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The welcomer is disabled.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The welcome channel is currently %s", channel.Mention()))
}
var AddGuildCommand = &disgoman.Command{
Name: "addGuild",
Aliases: nil,
Description: "Adds the current guild to the database",
OwnerOnly: true,
Hidden: false,
RequiredPermissions: 0,
Invoke: addGuildCommandFunc,
}
func addGuildCommandFunc(ctx disgoman.Context, args []string) {
var guildID string
row := postgres.DB.QueryRow("SELECT id FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&guildID)
if err == nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "This guild is already in my database",
Error: err,
}
return
}
_, err = postgres.DB.Query("INSERT INTO guilds (id) VALUES ($1)", ctx.Guild.ID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "There was a problem inserting this guild into the database",
Error: err,
}
return
}
_, _ = ctx.Send("This guild has been added.")
}
var SetPuzzleChannelCommand = &disgoman.Command{
Name: "set-puzzle-channel",
Aliases: []string{"spc"},
Description: "Set the channel puzzle messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: setPuzzleChannelFunc,
}
func setPuzzleChannelFunc(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := postgres.DB.Exec("UPDATE guilds SET puzzle_channel='' WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Channel Updated.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("UPDATE guilds SET puzzle_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Channel Updated.")
}
var GetPuzzleChannelCommand = &disgoman.Command{
Name: "get-puzzle-channel",
Aliases: []string{"gpc"},
Description: "Gets the channel puzzle messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getPuzzleChannelFunc,
}
func getPuzzleChannelFunc(ctx disgoman.Context, _ []string) {
var channelID string
row := postgres.DB.QueryRow("SELECT puzzle_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The puzzle channel is not set.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The puzzle channel is currently %s", channel.Mention()))
return
}
var SetPuzzleRoleCommand = &disgoman.Command{
Name: "set-puzzle-role",
Aliases: []string{"spr"},
Description: "Set the role to be pinged when there is a new puzzle",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: setPuzzleRoleFunc,
}
func setPuzzleRoleFunc(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<@&") && strings.HasSuffix(idString, ">") {
idString = idString[3 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := postgres.DB.Exec("UPDATE guilds SET puzzle_role=NULL WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Role Cleared.")
return
}
role, err := ctx.Session.State.Role(ctx.Guild.ID, idString)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("INSERT INTO roles (id, guild_id) VALUES ($1, $2) ON CONFLICT DO NOTHING", role.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, err = postgres.DB.Exec("UPDATE guilds SET puzzle_role=$1 WHERE id=$2;", role.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Role Updated.")
}
var GetPuzzleRoleCommand = &disgoman.Command{
Name: "get-puzzle-role",
Aliases: []string{"gpr"},
Description: "Get the role that will be pinged when there is a new puzzle",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getPuzzleRoleFunc,
}
func getPuzzleRoleFunc(ctx disgoman.Context, _ []string) {
var roleID sql.NullString
row := postgres.DB.QueryRow("SELECT puzzle_role FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&roleID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if !roleID.Valid {
_, _ = ctx.Send("The puzzle role is not set.")
return
}
role, err := ctx.Session.State.Role(ctx.Guild.ID, roleID.String)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the role ID but it does not appear to be a valid role in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The puzzle role is currently %s", role.Mention()))
return
}

View File

@ -1,11 +1,11 @@
package events
package guild_management
import (
"fmt"
"log"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/utils"
"github.com/dustinpianalto/goff/internal/postgres"
)
func OnMessageUpdate(session *discordgo.Session, m *discordgo.MessageUpdate) {
@ -19,7 +19,7 @@ func OnMessageUpdate(session *discordgo.Session, m *discordgo.MessageUpdate) {
return
}
var channelID string
row := utils.Database.QueryRow("SELECT logging_channel FROM guilds where id=$1", msg.GuildID)
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", msg.GuildID)
err := row.Scan(&channelID)
if err != nil || channelID == "" {
return
@ -29,6 +29,9 @@ func OnMessageUpdate(session *discordgo.Session, m *discordgo.MessageUpdate) {
log.Println(err)
return
}
if m.Content == "" {
return
}
embed := &discordgo.MessageEmbed{
Title: fmt.Sprintf("Message Edited: %v", msg.ID),
Description: fmt.Sprintf("**Before:** %v\n**After:** %v\nIn Channel: %v", msg.Content, m.Content, channel.Mention()),
@ -56,7 +59,7 @@ func OnMessageDelete(session *discordgo.Session, m *discordgo.MessageDelete) {
return
}
var channelID string
row := utils.Database.QueryRow("SELECT logging_channel FROM guilds where id=$1", msg.GuildID)
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", msg.GuildID)
err := row.Scan(&channelID)
if err != nil || channelID == "" {
return

59
internal/exts/init.go Normal file
View File

@ -0,0 +1,59 @@
package exts
import (
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/exts/fun"
"github.com/dustinpianalto/goff/internal/exts/guild_management"
"github.com/dustinpianalto/goff/internal/exts/roles"
"github.com/dustinpianalto/goff/internal/exts/tags"
"github.com/dustinpianalto/goff/internal/exts/tasks"
"github.com/dustinpianalto/goff/internal/exts/user_management"
"github.com/dustinpianalto/goff/internal/exts/utils"
"github.com/dustinpianalto/goff/internal/exts/p_interpreter"
)
func AddCommandHandlers(h *disgoman.CommandManager) {
// Arguments:
// name - command name - string
// desc - command description - string
// owneronly - only allow owners to run - bool
// hidden - hide command from non-owners - bool
// 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)
_ = h.AddCommand(utils.SnowflakeCommand)
_ = h.AddCommand(tasks.AddReminderCommand)
_ = h.AddCommand(tags.AddTagCommand)
_ = h.AddCommand(tags.TagCommand)
_ = h.AddCommand(roles.MakeRoleSelfAssignableCommand)
_ = h.AddCommand(roles.RemoveSelfAssignableCommand)
_ = h.AddCommand(roles.SelfAssignRoleCommand)
_ = h.AddCommand(roles.UnAssignRoleCommand)
_ = h.AddCommand(roles.MakeAutoRoleCommand)
_ = h.AddCommand(roles.RemoveAutoRoleCommand)
_ = h.AddCommand(p_interpreter.PCommand)
_ = h.AddCommand(fun.InterleaveCommand)
_ = h.AddCommand(fun.DeinterleaveCommand)
_ = h.AddCommand(fun.GenerateRPNCommand)
_ = h.AddCommand(fun.ParseRPNCommand)
_ = h.AddCommand(fun.SolveCommand)
_ = h.AddCommand(user_management.KickUserCommand)
_ = h.AddCommand(user_management.BanUserCommand)
_ = h.AddCommand(user_management.UnbanUserCommand)
_ = h.AddCommand(guild_management.SetLoggingChannelCommand)
_ = h.AddCommand(guild_management.GetLoggingChannelCommand)
_ = h.AddCommand(guild_management.SetWelcomeChannelCommand)
_ = h.AddCommand(guild_management.GetWelcomeChannelCommand)
_ = h.AddCommand(guild_management.AddGuildCommand)
_ = h.AddCommand(guild_management.SetPuzzleChannelCommand)
_ = h.AddCommand(guild_management.GetPuzzleChannelCommand)
_ = h.AddCommand(guild_management.SetPuzzleRoleCommand)
_ = h.AddCommand(guild_management.GetPuzzleRoleCommand)
}

View File

@ -1,8 +1,10 @@
package utils
package logging
import (
"fmt"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/internal/postgres"
)
var LoggingChannel = make(chan *LogEvent, 10)
@ -19,7 +21,7 @@ type LogEvent struct {
func LoggingHandler(lc chan *LogEvent) {
for event := range lc {
var channelID string
row := Database.QueryRow("SELECT logging_channel FROM guilds where id=$1", event.GuildID)
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", event.GuildID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)

View File

@ -1,13 +1,24 @@
package exts
package p_interpreter
import (
"errors"
"fmt"
"github.com/dustinpianalto/disgoman"
"strings"
"github.com/dustinpianalto/disgoman"
)
func pCommand(ctx disgoman.Context, args []string) {
var PCommand = &disgoman.Command{
Name: "P",
Aliases: nil,
Description: "Interpret a P\" program and return the results",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: pCommandFunc,
}
func pCommandFunc(ctx disgoman.Context, args []string) {
input := strings.Join(args, "")
const LENGTH = 1999
var mem [LENGTH]byte
@ -57,7 +68,7 @@ func pCommand(ctx disgoman.Context, args []string) {
}
}
} else {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Invalid Character: %v", input[i]),
Error: errors.New("invalid character"),
@ -73,7 +84,7 @@ func pCommand(ctx disgoman.Context, args []string) {
}
_, err := ctx.Send(string(out))
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't send results",
Error: err,

View File

@ -0,0 +1,389 @@
package roles
import (
"fmt"
"strconv"
"strings"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff"
"github.com/dustinpianalto/goff/internal/postgres"
"github.com/dustinpianalto/goff/internal/services"
)
var MakeRoleSelfAssignableCommand = &disgoman.Command{
Name: "make-role-self-assignable",
Aliases: []string{"makesar"},
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) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var role *discordgo.Role
var err error
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("INSERT INTO roles (id, guild_id, self_assignable) VALUES ($1, $2, true) ON CONFLICT (id) DO UPDATE SET self_assignable=true", role.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("%s is now self assignable", role.Name))
}
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) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var err error
var role *discordgo.Role
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("INSERT INTO roles (id, guild_id, self_assignable) VALUES ($1, $2, false) ON CONFLICT (id) DO UPDATE SET self_assignable=false", role.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("%s's self assignability has been removed.", role.Name))
}
var SelfAssignRoleCommand = &disgoman.Command{
Name: "giverole",
Aliases: []string{"iwant", "givetome"},
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) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var role *discordgo.Role
var err error
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
if memberHasRole(ctx.Member, role.ID) {
_, _ = ctx.Send(fmt.Sprintf("You already have the %s role silly...", role.Name))
return
}
var selfAssignable bool
err = postgres.DB.QueryRow("SELECT self_assignable FROM roles where id=$1", role.ID).Scan(&selfAssignable)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
if !selfAssignable {
_, _ = ctx.Send(fmt.Sprintf("You aren't allowed to assign yourself the %s role", role.Name))
return
}
err = ctx.Session.GuildMemberRoleAdd(ctx.Guild.ID, ctx.User.ID, role.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "There was a problem adding that role to you.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("Congratulations! The %s role has been added to your... Ummm... Thing.", role.Name))
}
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) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var role *discordgo.Role
var err error
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: 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
}
var selfAssignable bool
err = postgres.DB.QueryRow("SELECT self_assignable FROM roles where id=$1", role.ID).Scan(&selfAssignable)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
if !selfAssignable {
_, _ = ctx.Send(fmt.Sprintf("You aren't allowed to remove the %s role from yourself", role.Name))
return
}
err = ctx.Session.GuildMemberRoleRemove(ctx.Guild.ID, ctx.User.ID, role.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "There was a problem removing that role from you.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("Sad to see you go... but the %s role has been removed.", role.Name))
}
func memberHasRole(m *discordgo.Member, id string) bool {
for _, r := range m.Roles {
if r == id {
return true
}
}
return false
}
var MakeAutoRoleCommand = &disgoman.Command{
Name: "make-auto-role",
Aliases: []string{"makear"},
Description: "Marks the passed in role to auto add to new members.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: makeAutoRoleCommandFunc,
}
func makeAutoRoleCommandFunc(ctx disgoman.Context, args []string) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var r *discordgo.Role
var err error
if r, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
role, err := services.RoleService.Role(r.ID)
if err != nil {
role = &goff.Role{
ID: r.ID,
IsModerator: false,
IsAdmin: false,
SelfAssignable: false,
AutoRole: true,
Guild: ctx.Guild.ID,
}
role, err = services.RoleService.AddRole(role)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error making an Auto Role",
Error: err,
}
return
}
} else {
err = services.RoleService.MakeAutoRole(role)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error making an Auto Role",
Error: err,
}
return
}
}
_, _ = ctx.Send(fmt.Sprintf("%s will be added to all new memebers.", r.Name))
}
var RemoveAutoRoleCommand = &disgoman.Command{
Name: "remove-auto-role",
Aliases: []string{"removear"},
Description: "Remove role from those added to new members.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: removeAutoRoleCommandFunc,
}
func removeAutoRoleCommandFunc(ctx disgoman.Context, args []string) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var r *discordgo.Role
var err error
if r, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
role, err := services.RoleService.Role(r.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Role was not configured as an Auto Role",
Error: err,
}
return
} else {
err = services.RoleService.RemoveAutoRole(role)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error removing Auto Role",
Error: err,
}
return
}
}
_, _ = ctx.Send(fmt.Sprintf("%s will no longer be added to all new memebers.", r.Name))
}

View File

@ -1,4 +1,4 @@
package exts
package tags
import (
"errors"
@ -7,62 +7,64 @@ import (
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
"github.com/kballard/go-shellquote"
"github.com/dustinpianalto/goff"
"github.com/dustinpianalto/goff/internal/postgres"
"github.com/dustinpianalto/goff/internal/services"
)
func addTagCommand(ctx disgoman.Context, input []string) {
var AddTagCommand = &disgoman.Command{
Name: "addtag",
Aliases: nil,
Description: "Add a tag",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
SanitizeEveryone: true,
Invoke: addTagCommandFunc,
}
func addTagCommandFunc(ctx disgoman.Context, input []string) {
if len(input) >= 1 {
args, err := shellquote.Split(strings.Join(input, " "))
if err != nil {
if strings.Contains(err.Error(), "Unterminated") {
args = strings.SplitN(strings.Join(args, " "), " ", 2)
} else {
ctx.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "",
Error: err,
}
return
}
}
queryString := `SELECT tags.id, tags.tag, tags.content from tags
WHERE tags.guild_id = $1
AND tags.tag = $2;`
row := utils.Database.QueryRow(queryString, ctx.Guild.ID, args[0])
row := postgres.DB.QueryRow(queryString, ctx.Guild.ID, input[0])
var dest string
if err := row.Scan(&dest); err != nil {
tag := args[0]
tag := input[0]
if tag == "" {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "That is not a valid tag name",
Error: err,
}
return
}
if len(args) <= 1 {
ctx.ErrorChannel <- disgoman.CommandError{
if len(input) <= 1 {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got a name but no value",
Error: err,
}
return
}
value := args[1]
value := strings.Join(input[1:], " ")
if value == "" {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You have to include a content for the tag",
Error: err,
}
return
}
queryString = `INSERT INTO tags (tag, content, creator, guild_id) VALUES ($1, $2, $3, $4);`
_, err := utils.Database.Exec(queryString, tag, value, ctx.Message.Author.ID, ctx.Guild.ID)
err = services.UserService.CreateUser(&goff.User{ID: ctx.User.ID}, ctx.Guild.ID)
if err != nil {
ctx.Send(err.Error())
ctx.ErrorChannel <- disgoman.CommandError{
log.Printf("Error creating user %s: %s", ctx.User.ID, err.Error())
}
queryString = `INSERT INTO tags (tag, content, creator, guild_id) VALUES ($1, $2, $3, $4);`
_, err := postgres.DB.Exec(queryString, tag, value, ctx.Message.Author.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "",
Error: err,
@ -72,7 +74,7 @@ func addTagCommand(ctx disgoman.Context, input []string) {
ctx.Send(fmt.Sprintf("Tag %v added successfully.", tag))
return
} else {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "That tag already exists",
Error: err,
@ -81,7 +83,7 @@ func addTagCommand(ctx disgoman.Context, input []string) {
}
} else {
ctx.Send("You need to tell me what tag you want to add...")
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You need to tell me what tag you want to add...",
Error: errors.New("nothing to do"),
@ -90,14 +92,24 @@ func addTagCommand(ctx disgoman.Context, input []string) {
}
}
func tagCommand(ctx disgoman.Context, args []string) {
var TagCommand = &disgoman.Command{
Name: "tag",
Aliases: nil,
Description: "Get a tag",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: tagCommandFunc,
}
func tagCommandFunc(ctx disgoman.Context, args []string) {
if len(args) >= 1 {
tagString := strings.Join(args, " ")
queryString := `SELECT tags.id, tags.tag, tags.content from tags
WHERE tags.guild_id = $1;`
rows, err := utils.Database.Query(queryString, ctx.Guild.ID)
rows, err := postgres.DB.Query(queryString, ctx.Guild.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "",
Error: err,
@ -111,14 +123,14 @@ func tagCommand(ctx disgoman.Context, args []string) {
content string
)
if err := rows.Scan(&id, &tag, &content); err != nil {
log.Fatal(err)
log.Println(err)
}
if tagString == tag {
ctx.Send(content)
return
}
}
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Tag %v not found", args[0]),
Error: err,
@ -127,7 +139,7 @@ func tagCommand(ctx disgoman.Context, args []string) {
}
} else {
ctx.Send("I need a tag to fetch...")
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I need a tag to fetch...",
Error: errors.New("nothing to do"),

View File

@ -1,10 +1,12 @@
package utils
package tasks
import (
"fmt"
"github.com/bwmarrin/discordgo"
"log"
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/internal/postgres"
)
type Task struct {
@ -20,7 +22,7 @@ type Task struct {
func processTask(task *Task, s *discordgo.Session) {
query := "SELECT completed, processing from tasks where id = $1"
res, err := Database.Query(query, task.ID)
res, err := postgres.DB.Query(query, task.ID)
if err != nil {
log.Println(err)
return
@ -38,8 +40,8 @@ func processTask(task *Task, s *discordgo.Session) {
}
closeQuery := "Update tasks set completed = true where id = $1"
processQuery := "UPDATE tasks SET processing = true WHERE id = $1"
defer Database.Exec(closeQuery, task.ID)
_, err = Database.Exec(processQuery, task.ID)
defer postgres.DB.Exec(closeQuery, task.ID)
_, err = postgres.DB.Exec(processQuery, task.ID)
if err != nil {
log.Println(err)
return
@ -85,7 +87,7 @@ func processTask(task *Task, s *discordgo.Session) {
}
}
processQuery = "UPDATE tasks SET processing = false WHERE id = $1"
_, err = Database.Exec(processQuery, task.ID)
_, err = postgres.DB.Exec(processQuery, task.ID)
if err != nil {
log.Println(err)
}
@ -95,9 +97,10 @@ func processTask(task *Task, s *discordgo.Session) {
func getTasksToRun() []Task {
query := "SELECT id, type, content, guild_id, channel_id, user_id, creation_time, trigger_time " +
"from tasks where completed is false and processing is false and trigger_time < $1"
res, err := Database.Query(query, time.Now())
res, err := postgres.DB.Query(query, time.Now())
if err != nil {
log.Println(err)
return nil
}
var tasks []Task
for res.Next() {

View File

@ -1,4 +1,4 @@
package exts
package tasks
import (
"errors"
@ -7,13 +7,23 @@ import (
"time"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
"github.com/dustinpianalto/goff/internal/postgres"
"github.com/olebedev/when"
"github.com/olebedev/when/rules/common"
"github.com/olebedev/when/rules/en"
)
func addReminderCommand(ctx disgoman.Context, args []string) {
var AddReminderCommand = &disgoman.Command{
Name: "remind",
Aliases: nil,
Description: "Remind me at a later time",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: addReminderFunc,
}
func addReminderFunc(ctx disgoman.Context, args []string) {
w := when.New(nil)
w.Add(en.All...)
w.Add(common.All...)
@ -21,7 +31,7 @@ func addReminderCommand(ctx disgoman.Context, args []string) {
text := strings.Join(args, " ")
r, err := w.Parse(text, time.Now())
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error parsing time",
Error: err,
@ -29,7 +39,7 @@ func addReminderCommand(ctx disgoman.Context, args []string) {
return
}
if r == nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You need to include a valid time",
Error: errors.New("no time found"),
@ -39,9 +49,9 @@ func addReminderCommand(ctx disgoman.Context, args []string) {
content := strings.Replace(text, r.Text+" ", "", 1)
query := "INSERT INTO tasks (type, content, guild_id, channel_id, user_id, trigger_time) " +
"VALUES ('Reminder', $1, $2, $3, $4, $5)"
_, err = utils.Database.Exec(query, content, ctx.Guild.ID, ctx.Channel.ID, ctx.User.ID, r.Time)
_, err = postgres.DB.Exec(query, content, ctx.Guild.ID, ctx.Channel.ID, ctx.User.ID, r.Time)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error adding task to database",
Error: err,

View File

@ -0,0 +1,119 @@
package user_management
import (
"log"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff"
"github.com/dustinpianalto/goff/internal/services"
)
func OnGuildMemberAdd(s *discordgo.Session, member *discordgo.GuildMemberAdd) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in OnGuildMemberAdd", r)
}
}()
user, err := services.UserService.User(member.User.ID)
if err != nil {
log.Println("Error getting user from database: ", err)
user = &goff.User{
ID: member.User.ID,
Banned: false,
Logging: true,
IsActive: true,
IsStaff: false,
IsAdmin: false,
}
err := services.UserService.CreateUser(user, member.GuildID)
if err != nil {
log.Println("Error adding user to database: ", err)
}
}
if !user.IsActive {
user.IsActive = true
err = services.UserService.UpdateUser(user)
if err != nil {
log.Println("Error marking user as active: ", err)
}
}
err = services.UserService.AddUserToGuild(user, &goff.Guild{ID: member.GuildID})
if err != nil {
log.Println("Error adding user to guild: ", err)
}
if !member.Member.Pending {
roles, err := services.RoleService.GetAutoRoles(member.GuildID)
if err != nil {
log.Println("Error getting Auto Join Roles: ", err)
}
log.Println(roles)
for _, r := range roles {
role, err := s.State.Role(member.GuildID, r.ID)
if err != nil {
log.Println("Error getting role: ", err)
continue
}
err = s.GuildMemberRoleAdd(member.GuildID, member.User.ID, role.ID)
if err != nil {
log.Println("Error adding Role to member: ", err)
continue
}
}
}
}
func OnGuildMemberRemove(s *discordgo.Session, member *discordgo.GuildMemberRemove) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in OnGuildMemberRemove: ", r)
}
}()
user, err := services.UserService.User(member.User.ID)
if err != nil {
log.Println("Error getting user from database: ", err)
return
}
err = services.UserService.RemoveUserFromGuild(user, &goff.Guild{ID: member.GuildID})
if err != nil {
log.Println("Error removing user from guild: ", err)
}
for i, g := range user.Guilds {
if g == member.GuildID {
user.Guilds[len(user.Guilds)-1], user.Guilds[i] = user.Guilds[i], user.Guilds[len(user.Guilds)-1]
user.Guilds = user.Guilds[:len(user.Guilds)-1]
}
}
if len(user.Guilds) == 0 {
err = services.UserService.MarkUserInactive(user)
if err != nil {
log.Println("Error marking user as inactive: ", err)
}
}
}
func OnGuildMemberUpdate(s *discordgo.Session, member *discordgo.GuildMemberUpdate) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in OnGuildMemberUpdate: ", r)
}
}()
if !member.Member.Pending {
roles, err := services.RoleService.GetAutoRoles(member.GuildID)
if err != nil {
log.Println("Error getting Auto Join Roles: ", err)
}
log.Println(roles)
for _, r := range roles {
role, err := s.State.Role(member.GuildID, r.ID)
if err != nil {
log.Println("Error getting role: ", err)
continue
}
err = s.GuildMemberRoleAdd(member.GuildID, member.User.ID, role.ID)
if err != nil {
log.Println("Error adding Role to member: ", err)
continue
}
}
}
}

View File

@ -1,4 +1,4 @@
package events
package user_management
import (
"fmt"
@ -7,7 +7,8 @@ import (
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/utils"
"github.com/dustinpianalto/goff/internal/discord_utils"
"github.com/dustinpianalto/goff/internal/postgres"
)
func OnGuildMemberAddLogging(s *discordgo.Session, member *discordgo.GuildMemberAdd) {
@ -17,7 +18,7 @@ func OnGuildMemberAddLogging(s *discordgo.Session, member *discordgo.GuildMember
}
}()
var channelID string
row := utils.Database.QueryRow("SELECT logging_channel FROM guilds where id=$1", member.GuildID)
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", member.GuildID)
err := row.Scan(&channelID)
if err != nil || channelID == "" {
return
@ -40,11 +41,11 @@ func OnGuildMemberAddLogging(s *discordgo.Session, member *discordgo.GuildMember
}
int64ID, _ := strconv.ParseInt(member.User.ID, 10, 64)
snow := utils.ParseSnowflake(int64ID)
snow := discord_utils.ParseSnowflake(int64ID)
field := &discordgo.MessageEmbedField{
Name: "User was created:",
Value: utils.ParseDateString(snow.CreationTime),
Value: discord_utils.ParseDateString(snow.CreationTime),
Inline: false,
}
@ -73,7 +74,7 @@ func OnGuildMemberRemoveLogging(s *discordgo.Session, member *discordgo.GuildMem
}()
timeNow := time.Now()
var channelID string
row := utils.Database.QueryRow("SELECT logging_channel FROM guilds where id=$1", member.GuildID)
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", member.GuildID)
err := row.Scan(&channelID)
if err != nil || channelID == "" {
return
@ -103,7 +104,7 @@ func OnGuildMemberRemoveLogging(s *discordgo.Session, member *discordgo.GuildMem
for _, log := range al.AuditLogEntries {
if log.TargetID == member.User.ID {
int64ID, _ := strconv.ParseInt(log.ID, 10, 64)
logSnow := utils.ParseSnowflake(int64ID)
logSnow := discord_utils.ParseSnowflake(int64ID)
if timeNow.Sub(logSnow.CreationTime).Seconds() <= 10 {
user, err := s.User(log.UserID)
if err == nil {
@ -133,3 +134,33 @@ func OnGuildMemberRemoveLogging(s *discordgo.Session, member *discordgo.GuildMem
}
s.ChannelMessageSendEmbed(channelID, embed)
}
func AddMemberToDatabase(s *discordgo.Session, m *discordgo.GuildMemberAdd) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in AddMemberToDatabase", r)
}
}()
queryString := `INSERT INTO users (id, banned, logging, is_active, is_staff, is_admin)
VALUES ($1, false, false, true, false, false)`
_, err := postgres.DB.Exec(queryString, m.User.ID)
if err != nil {
log.Println(fmt.Errorf("error inserting %s into database: %w", m.User.ID, err))
return
}
log.Printf("New User: %s\n", m.User.ID)
}
func MarkMemberInactive(s *discordgo.Session, m *discordgo.GuildMemberRemove) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in MarkMemberInactive")
}
}()
queryString := `UPDATE users SET is_active = false WHERE id = $1`
_, err := postgres.DB.Exec(queryString, m.User.ID)
if err != nil {
log.Println(fmt.Errorf("error marking %s as inactive: %w", m.User.ID, err))
return
}
}

View File

@ -1,4 +1,4 @@
package exts
package user_management
import (
"errors"
@ -8,10 +8,20 @@ import (
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
"github.com/dustinpianalto/goff/internal/exts/logging"
)
func kickUserCommand(ctx disgoman.Context, args []string) {
var KickUserCommand = &disgoman.Command{
Name: "kick",
Aliases: nil,
Description: "Kicks the given user with the given reason",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionKickMembers,
Invoke: kickUserFunc,
}
func kickUserFunc(ctx disgoman.Context, args []string) {
var member *discordgo.Member
var err error
if len(ctx.Message.Mentions) > 0 {
@ -26,7 +36,7 @@ func kickUserCommand(ctx disgoman.Context, args []string) {
err = errors.New("that is not a valid id")
}
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't get that member",
Error: err,
@ -35,7 +45,7 @@ func kickUserCommand(ctx disgoman.Context, args []string) {
}
if higher, _ := disgoman.HasHigherRole(ctx.Session, ctx.Guild.ID, ctx.Message.Author.ID, member.User.ID); !higher {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You must have a higher role than the person you are trying to kick",
Error: errors.New("need higher role"),
@ -44,7 +54,7 @@ func kickUserCommand(ctx disgoman.Context, args []string) {
}
if higher, _ := disgoman.HasHigherRole(ctx.Session, ctx.Guild.ID, ctx.Session.State.User.ID, member.User.ID); !higher {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I don't have a high enough role to kick that person",
Error: errors.New("need higher role"),
@ -62,7 +72,7 @@ func kickUserCommand(ctx disgoman.Context, args []string) {
err = ctx.Session.GuildMemberDeleteWithReason(ctx.Guild.ID, member.User.ID, auditReason)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Something went wrong kicking %v", member.User.Username),
Error: err,
@ -70,7 +80,7 @@ func kickUserCommand(ctx disgoman.Context, args []string) {
return
}
event := &utils.LogEvent{
event := &logging.LogEvent{
Embed: discordgo.MessageEmbed{
Title: "User Kicked",
Description: fmt.Sprintf(
@ -85,11 +95,21 @@ func kickUserCommand(ctx disgoman.Context, args []string) {
GuildID: ctx.Guild.ID,
Session: ctx.Session,
}
utils.LoggingChannel <- event
logging.LoggingChannel <- event
_, _ = ctx.Send(fmt.Sprintf("User %v#%v has been kicked.", member.User.Username, member.User.Discriminator))
}
func banUserCommand(ctx disgoman.Context, args []string) {
var BanUserCommand = &disgoman.Command{
Name: "ban",
Aliases: []string{"ban-no-delete"},
Description: "Bans the given user with the given reason",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionBanMembers,
Invoke: banUserFunc,
}
func banUserFunc(ctx disgoman.Context, args []string) {
var user *discordgo.User
var err error
if len(ctx.Message.Mentions) > 0 {
@ -104,7 +124,7 @@ func banUserCommand(ctx disgoman.Context, args []string) {
err = errors.New("that is not a valid id")
}
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't get that user",
Error: err,
@ -114,7 +134,7 @@ func banUserCommand(ctx disgoman.Context, args []string) {
if higher, err := disgoman.HasHigherRole(ctx.Session, ctx.Guild.ID, ctx.Message.Author.ID, user.ID); err != nil {
if err.Error() == "can't find caller member" {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Who are you?",
Error: err,
@ -122,7 +142,7 @@ func banUserCommand(ctx disgoman.Context, args []string) {
return
}
} else if !higher {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You must have a higher role than the person you are trying to ban",
Error: errors.New("need higher role"),
@ -132,7 +152,7 @@ func banUserCommand(ctx disgoman.Context, args []string) {
if higher, err := disgoman.HasHigherRole(ctx.Session, ctx.Guild.ID, ctx.Session.State.User.ID, user.ID); err != nil {
if err.Error() == "can't find caller member" {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Who am I?",
Error: err,
@ -140,7 +160,7 @@ func banUserCommand(ctx disgoman.Context, args []string) {
return
}
} else if !higher {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I don't have a high enough role to ban that person",
Error: errors.New("need higher role"),
@ -162,7 +182,7 @@ func banUserCommand(ctx disgoman.Context, args []string) {
err = ctx.Session.GuildBanCreateWithReason(ctx.Guild.ID, user.ID, auditReason, days)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Something went wrong banning %v", user.Username),
Error: err,
@ -170,7 +190,7 @@ func banUserCommand(ctx disgoman.Context, args []string) {
return
}
event := &utils.LogEvent{
event := &logging.LogEvent{
Embed: discordgo.MessageEmbed{
Title: "User Banned",
Description: fmt.Sprintf(
@ -185,11 +205,21 @@ func banUserCommand(ctx disgoman.Context, args []string) {
GuildID: ctx.Guild.ID,
Session: ctx.Session,
}
utils.LoggingChannel <- event
logging.LoggingChannel <- event
_, _ = ctx.Send(fmt.Sprintf("User %v#%v has been banned.", user.Username, user.Discriminator))
}
func unbanUserCommand(ctx disgoman.Context, args []string) {
var UnbanUserCommand = &disgoman.Command{
Name: "unban",
Aliases: nil,
Description: "Unbans the given user",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionBanMembers,
Invoke: unbanUserFunc,
}
func unbanUserFunc(ctx disgoman.Context, args []string) {
var user *discordgo.User
var err error
if len(ctx.Message.Mentions) > 0 {
@ -204,7 +234,7 @@ func unbanUserCommand(ctx disgoman.Context, args []string) {
err = errors.New("that is not a valid id")
}
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't get that user",
Error: err,
@ -214,7 +244,7 @@ func unbanUserCommand(ctx disgoman.Context, args []string) {
bans, err := ctx.Session.GuildBans(ctx.Guild.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error processing current bans",
Error: err,
@ -225,14 +255,14 @@ func unbanUserCommand(ctx disgoman.Context, args []string) {
if ban.User.ID == user.ID {
err = ctx.Session.GuildBanDelete(ctx.Guild.ID, user.ID)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Something went wrong unbanning %v", user.Username),
Error: err,
}
return
}
event := &utils.LogEvent{
event := &logging.LogEvent{
Embed: discordgo.MessageEmbed{
Title: "User Banned",
Description: fmt.Sprintf(
@ -247,7 +277,7 @@ func unbanUserCommand(ctx disgoman.Context, args []string) {
GuildID: ctx.Guild.ID,
Session: ctx.Session,
}
utils.LoggingChannel <- event
logging.LoggingChannel <- event
_, _ = ctx.Send(fmt.Sprintf("User %v#%v has been unbanned.", user.Username, user.Discriminator))
return
}

View File

@ -1,4 +1,4 @@
package exts
package utils
import (
"fmt"
@ -9,16 +9,26 @@ import (
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
"github.com/dustinpianalto/goff/internal/discord_utils"
)
func pingCommand(ctx disgoman.Context, _ []string) {
var PingCommand = &disgoman.Command{
Name: "ping",
Aliases: []string{" "},
Description: "Check the bot's ping",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: pingCommandFunc,
}
func pingCommandFunc(ctx disgoman.Context, _ []string) {
timeBefore := time.Now()
msg, _ := ctx.Send("Pong!")
took := time.Now().Sub(timeBefore)
_, err := ctx.Session.ChannelMessageEdit(ctx.Message.ChannelID, msg.ID, fmt.Sprintf("Pong!\nPing Took **%s**", took.String()))
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Ping Failed",
Error: err,
@ -26,7 +36,17 @@ func pingCommand(ctx disgoman.Context, _ []string) {
}
}
func inviteCommand(ctx disgoman.Context, args []string) {
var InviteCommand = &disgoman.Command{
Name: "invite",
Aliases: nil,
Description: "Get the invite link for this bot or others",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: inviteCommandFunc,
}
func inviteCommandFunc(ctx disgoman.Context, args []string) {
var ids []string
if len(args) == 0 {
ids = []string{ctx.Session.State.User.ID}
@ -39,7 +59,7 @@ func inviteCommand(ctx disgoman.Context, args []string) {
url := fmt.Sprintf("<https://discordapp.com/oauth2/authorize?client_id=%v&scope=bot>", id)
_, err := ctx.Send(url)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't send the invite link.",
Error: err,
@ -48,7 +68,17 @@ func inviteCommand(ctx disgoman.Context, args []string) {
}
}
func gitCommand(ctx disgoman.Context, _ []string) {
var GitCommand = &disgoman.Command{
Name: "git",
Aliases: nil,
Description: "Show my github link",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: gitCommandFunc,
}
func gitCommandFunc(ctx disgoman.Context, _ []string) {
embed := &discordgo.MessageEmbed{
Title: "Hi there, My code is on Github",
Color: 0,
@ -56,7 +86,7 @@ func gitCommand(ctx disgoman.Context, _ []string) {
}
_, err := ctx.Session.ChannelMessageSendEmbed(ctx.Channel.ID, embed)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Git failed",
Error: err,
@ -64,13 +94,24 @@ func gitCommand(ctx disgoman.Context, _ []string) {
}
}
func sayCommand(ctx disgoman.Context, args []string) {
var SayCommand = &disgoman.Command{
Name: "say",
Aliases: nil,
Description: "Repeat a message",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
SanitizeEveryone: true,
Invoke: sayCommandFunc,
}
func sayCommandFunc(ctx disgoman.Context, args []string) {
resp := strings.Join(args, " ")
resp = strings.ReplaceAll(resp, "@everyone", "@\ufff0everyone")
resp = strings.ReplaceAll(resp, "@here", "@\ufff0here")
_, err := ctx.Session.ChannelMessageSend(ctx.Message.ChannelID, resp)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Say Failed",
Error: err,
@ -78,7 +119,17 @@ func sayCommand(ctx disgoman.Context, args []string) {
}
}
func userCommand(ctx disgoman.Context, args []string) {
var UserCommand = &disgoman.Command{
Name: "user",
Aliases: nil,
Description: "Get user info",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: userCommandFunc,
}
func userCommandFunc(ctx disgoman.Context, args []string) {
var member *discordgo.Member
if len(args) == 0 {
member, _ = ctx.Session.GuildMember(ctx.Guild.ID, ctx.Message.Author.ID)
@ -90,7 +141,7 @@ func userCommand(ctx disgoman.Context, args []string) {
member, err = ctx.Session.GuildMember(ctx.Guild.ID, args[0])
}
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't get that member",
Error: err,
@ -135,15 +186,15 @@ func userCommand(ctx disgoman.Context, args []string) {
guildJoinTime, _ := member.JoinedAt.Parse()
guildJoinedField := &discordgo.MessageEmbedField{
Name: "Joined Guild:",
Value: utils.ParseDateString(guildJoinTime),
Value: discord_utils.ParseDateString(guildJoinTime),
Inline: false,
}
int64ID, _ := strconv.ParseInt(member.User.ID, 10, 64)
s := utils.ParseSnowflake(int64ID)
s := discord_utils.ParseSnowflake(int64ID)
discordJoinedField := &discordgo.MessageEmbedField{
Name: "Joined Discord:",
Value: utils.ParseDateString(s.CreationTime),
Value: discord_utils.ParseDateString(s.CreationTime),
Inline: false,
}
@ -160,10 +211,39 @@ func userCommand(ctx disgoman.Context, args []string) {
}
_, err := ctx.Session.ChannelMessageSendEmbed(ctx.Channel.ID, embed)
if err != nil {
ctx.ErrorChannel <- disgoman.CommandError{
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't send the user embed",
Error: err,
}
}
}
var SnowflakeCommand = &disgoman.Command{
Name: "s",
Aliases: nil,
Description: "Return the parts of a snowflake",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
SanitizeEveryone: true,
Invoke: snowflakeCommandFunc,
}
func snowflakeCommandFunc(ctx disgoman.Context, args []string) {
int64ID, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Not a valid ID",
Error: err,
}
return
}
s := discord_utils.ParseSnowflake(int64ID)
embed := &discordgo.MessageEmbed{
Title: args[0],
Description: fmt.Sprintf("Created: %s\nWorker: %d\nProcess: %d\nCounter: %d", discord_utils.ParseDateString(s.CreationTime), s.WorkerID, s.ProcessID, s.Increment),
}
_, _ = ctx.Session.ChannelMessageSendEmbed(ctx.Channel.ID, embed)
}

View File

@ -1,4 +1,4 @@
package utils
package postgres
import (
"database/sql"
@ -9,7 +9,7 @@ import (
)
var (
Database *sql.DB
DB *sql.DB
)
func ConnectDatabase(dbConnString string) {
@ -19,11 +19,14 @@ func ConnectDatabase(dbConnString string) {
} else {
fmt.Println("Database Connected.")
}
Database = db
db.SetMaxOpenConns(75) // The RDS instance has a max of 75 open connections
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(300)
DB = db
}
func InitializeDatabase() {
_, err := Database.Query("CREATE TABLE IF NOT EXISTS users(" +
_, err := DB.Query("CREATE TABLE IF NOT EXISTS users(" +
"id varchar(30) primary key," +
"banned bool not null default false," +
"logging bool not null default true," +
@ -35,7 +38,7 @@ func InitializeDatabase() {
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("CREATE TABLE IF NOT EXISTS guilds(" +
_, err = DB.Query("CREATE TABLE IF NOT EXISTS guilds(" +
"id varchar(30) primary key," +
"welcome_message varchar(1000) NOT NULL DEFAULT ''," +
"goodbye_message varchar(1000) NOT NULL DEFAULT ''," +
@ -45,14 +48,14 @@ func InitializeDatabase() {
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("CREATE TABLE IF NOT EXISTS prefixes(" +
_, err = DB.Query("CREATE TABLE IF NOT EXISTS prefixes(" +
"id serial primary key," +
"prefix varchar(10) not null unique default 'Go.'" +
")")
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("CREATE TABLE IF NOT EXISTS tags(" +
_, err = DB.Query("CREATE TABLE IF NOT EXISTS tags(" +
"id serial primary key," +
"tag varchar(100) not null unique," +
"content varchar(1000) not null," +
@ -63,21 +66,21 @@ func InitializeDatabase() {
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("CREATE TABLE IF NOT EXISTS x_users_guilds(" +
_, err = DB.Query("CREATE TABLE IF NOT EXISTS x_users_guilds(" +
"guild_id varchar(30) not null references guilds(id)," +
"user_id varchar(30) not null references users(id)" +
")")
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("CREATE TABLE IF NOT EXISTS x_guilds_prefixes(" +
_, err = DB.Query("CREATE TABLE IF NOT EXISTS x_guilds_prefixes(" +
"guild_id varchar(30) not null references guilds(id)," +
"prefix_id int not null references prefixes(id)" +
")")
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("CREATE TABLE IF NOT EXISTS tasks(" +
_, err = DB.Query("CREATE TABLE IF NOT EXISTS tasks(" +
"id serial primary key," +
"type varchar(10) not null," +
"content text not null," +
@ -91,14 +94,14 @@ func InitializeDatabase() {
if err != nil {
fmt.Println(err)
}
_, err = Database.Query(`CREATE TABLE IF NOT EXISTS postfixes(
_, err = DB.Query(`CREATE TABLE IF NOT EXISTS postfixes(
id serial primary key,
name varchar(100) not null,
time timestamp not null default NOW())`)
if err != nil {
log.Println(err)
}
_, err = Database.Exec(`CREATE TABLE IF NOT EXISTS puzzles(
_, err = DB.Exec(`CREATE TABLE IF NOT EXISTS puzzles(
id serial primary key,
text text not null,
time timestamp not null
@ -106,7 +109,7 @@ func InitializeDatabase() {
if err != nil {
log.Println(err)
}
_, err = Database.Exec(`CREATE TABLE IF NOT EXISTS x_guilds_puzzles(
_, err = DB.Exec(`CREATE TABLE IF NOT EXISTS x_guilds_puzzles(
id serial primary key,
guild_id varchar(30) not null references guilds(id),
puzzle_id int not null references puzzles(id),
@ -116,37 +119,37 @@ func InitializeDatabase() {
}
func LoadTestData() {
_, err := Database.Query("INSERT INTO users (id, banned, logging, steam_id, is_active, is_staff, is_admin) values " +
_, err := DB.Query("INSERT INTO users (id, banned, logging, steam_id, is_active, is_staff, is_admin) values " +
"('351794468870946827', false, true, '76561198024193239', true, true, true)," +
"('692908139506434065', false, true, '', true, false, false)," +
"('396588996706304010', false, true, '', true, true, false)")
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("INSERT INTO guilds (id, welcome_message, goodbye_message) VALUES " +
_, err = DB.Query("INSERT INTO guilds (id, welcome_message, goodbye_message) VALUES " +
"('265828729970753537', 'Hey there is someone new here.', 'Well fine then... Just leave without saying goodbye')")
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("INSERT INTO prefixes (prefix) VALUES ('Godev.'), ('godev.'), ('godev,')")
_, err = DB.Query("INSERT INTO prefixes (prefix) VALUES ('Godev.'), ('godev.'), ('godev,')")
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("INSERT INTO x_users_guilds (guild_id, user_id) VALUES " +
_, err = DB.Query("INSERT INTO x_users_guilds (guild_id, user_id) VALUES " +
"('265828729970753537', '351794468870946827')," +
"('265828729970753537', '692908139506434065')," +
"('265828729970753537', '396588996706304010')")
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("INSERT INTO x_guilds_prefixes (guild_id, prefix_id) VALUES " +
_, err = DB.Query("INSERT INTO x_guilds_prefixes (guild_id, prefix_id) VALUES " +
"('265828729970753537', 1)," +
"('265828729970753537', 2)," +
"('265828729970753537', 3)")
if err != nil {
fmt.Println(err)
}
_, err = Database.Query("INSERT INTO tags (tag, content, creator, guild_id) VALUES " +
_, err = DB.Query("INSERT INTO tags (tag, content, creator, guild_id) VALUES " +
"('test', 'This is a test of the tag system', '351794468870946827', '265828729970753537')")
if err != nil {
fmt.Println(err)

127
internal/postgres/guild.go Normal file
View File

@ -0,0 +1,127 @@
package postgres
import (
"database/sql"
"log"
"github.com/dustinpianalto/goff"
)
type GuildService struct {
DB *sql.DB
}
func (s *GuildService) Guild(id string) (*goff.Guild, error) {
var g goff.Guild
queryString := `SELECT id, welcome_message, goodbye_message,
logging_channel, welcome_channel, puzzle_channel, puzzle_role
FROM guilds
WHERE id = $1`
row := s.DB.QueryRow(queryString, id)
err := row.Scan(
&g.ID,
&g.WelcomeMessage,
&g.GoodbyeMessage,
&g.LoggingChannel,
&g.WelcomeChannel,
&g.PuzzleChannel,
&g.PuzzleRole,
)
if err != nil {
return nil, err
}
var prefixes []string
queryString = `SELECT p.prefix
FROM prefixes p, x_guilds_prefixes xgp
WHERE p.id = xgp.prefix_id AND xgp.guild_id = $1`
rows, err := s.DB.Query(queryString, id)
if err == nil {
for rows.Next() {
var prefix string
err = rows.Scan(&prefix)
if err != nil {
continue
}
prefixes = append(prefixes, prefix)
}
}
g.Prefixes = prefixes
return &g, nil
}
func (s *GuildService) CreateGuild(g *goff.Guild) error {
queryString := `INSERT INTO guilds (id,
welcome_message,
goodbye_message,
logging_channel,
welcome_channel,
puzzle_channel,
puzzle_role)
VALUES ($1, $2, $3, $4, $5, $6, $7)`
_, err := s.DB.Exec(queryString,
g.ID,
g.WelcomeMessage,
g.GoodbyeMessage,
g.LoggingChannel,
g.WelcomeChannel,
g.PuzzleChannel,
g.PuzzleRole,
)
return err
}
func (s *GuildService) DeleteGuild(g *goff.Guild) error {
queryString := `DELETE CASCADE FROM guilds WHERE id = $1`
_, err := s.DB.Exec(queryString, g.ID)
return err
}
func (s *GuildService) GuildUsers(g *goff.Guild) ([]*goff.User, error) {
var users []*goff.User
queryString := `SELECT u.id, u.banned, u.logging, u.steam_id, u.is_active, u.is_staff, u.is_admin
FROM users u, x_users_guilds xug
WHERE xug.guild_id = $1
AND xug.user_id = u.id`
rows, err := s.DB.Query(queryString, g.ID)
if err != nil {
return nil, err
}
for rows.Next() {
var user goff.User
err := rows.Scan(&user.ID,
&user.Banned,
&user.Logging,
&user.SteamID,
&user.IsActive,
&user.IsStaff,
&user.IsAdmin,
)
if err != nil {
log.Println(err)
continue
}
users = append(users, &user)
}
return users, nil
}
func (s *GuildService) UpdateGuild(g *goff.Guild) error {
queryString := `UPDATE guilds SET
welcome_message = $1,
goodbye_message = $2,
logging_channel = $3,
welcome_channel = $4,
puzzle_channel = $5,
puzzle_role = $6
WHERE id = $7`
_, err := s.DB.Exec(queryString,
g.WelcomeMessage,
g.GoodbyeMessage,
g.LoggingChannel,
g.WelcomeChannel,
g.PuzzleChannel,
g.PuzzleRole,
g.ID,
)
return err
}

View File

@ -0,0 +1,185 @@
package postgres
import "log"
type postfix struct {
Name string
Invoke func(bool) error
}
var postfixes = []postfix{
postfix{
Name: "1_Update_Guild_for_Puzzle",
Invoke: updateGuildForPuzzle,
},
postfix{
Name: "1_Update_X_Guild_Prefixes_to_add_ID",
Invoke: updateXGuildPrefixesToAddID,
},
postfix{
Name: "1_Update_Tags_Content_Length",
Invoke: updateTagsContentLength,
},
postfix{
Name: "2_Add_Table_Roles",
Invoke: addTableRoles,
},
postfix{
Name: "3_Update_Guild_Add_Puzzle_Role",
Invoke: updateGuildsAddPuzzleRole,
},
postfix{
Name: "4_Add_Multi_Column_Unique_XUsersGuilds",
Invoke: addMultiColumnUniqueXUsersGuilds,
},
postfix{
Name: "5_Add_Auto_Role_To_Roles_Table",
Invoke: addAutoRoleToRoles,
},
}
func RunPostfixes() {
for _, postfix := range postfixes {
queryString := "SELECT * from postfixes where name = $1"
rows, err := DB.Query(queryString, postfix.Name)
if err != nil {
log.Println(err)
continue
}
if rows.Next() {
continue
} else {
err := postfix.Invoke(false)
if err != nil {
continue
}
_, err = DB.Exec("INSERT INTO postfixes (name) VALUES ($1)", postfix.Name)
if err != nil {
log.Println(err)
continue
}
}
}
}
func updateGuildForPuzzle(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE guilds
ADD COLUMN puzzle_channel varchar(30) not null default ''`
} else {
queryString = `ALTER TABLE guilds
DROP COLUMN puzzleChat`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func updateXGuildPrefixesToAddID(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE x_guilds_prefixes
ADD COLUMN id serial primary key`
} else {
queryString = `ALTER TABLE x_guilds_prefixes
DROP COLUMN id`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func updateTagsContentLength(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE tags
ALTER COLUMN content TYPE varchar(2000)`
} else {
queryString = `ALTER TABLE tags
ALTER COLUMN content TYPE varchar(1000)`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func addTableRoles(revert bool) error {
var queryString string
if !revert {
queryString = `CREATE TABLE roles(
id varchar(30) primary key,
guild_id varchar(30) not null references guilds(id),
self_assignable bool not null default false,
admin bool not null default false,
moderator bool not null default false
)`
} else {
queryString = `DROP TABLE roles`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func updateGuildsAddPuzzleRole(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE guilds
ADD COLUMN puzzle_role varchar(30) references roles(id)`
} else {
queryString = `ALTER TABLE guilds
DROP COLUMN puzzle_role`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func addMultiColumnUniqueXUsersGuilds(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE x_users_guilds
ADD CONSTRAINT u_user_guild UNIQUE(user_id, guild_id)`
} else {
queryString = `ALTER TABLE DROP CONSTRAINT u_user_guild IF EXISTS`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func addAutoRoleToRoles(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE roles
ADD COLUMN auto_role bool DEFAULT false`
} else {
queryString = `ALTER TABLE roles
DROP COLUMN auto_role`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}

View File

@ -0,0 +1,86 @@
package postgres
import (
"database/sql"
"log"
"github.com/dustinpianalto/goff"
)
type RoleService struct {
DB *sql.DB
}
func (s *RoleService) Role(id string) (*goff.Role, error) {
var r goff.Role
queryString := `SELECT id, moderator, admin, self_assignable, guild_id FROM roles WHERE id = $1`
row := s.DB.QueryRow(queryString, id)
if err := row.Scan(&r.ID, &r.IsModerator, &r.IsAdmin, &r.SelfAssignable, &r.Guild); err != nil {
return nil, err
}
return &r, nil
}
func (s *RoleService) AddRole(r *goff.Role) (*goff.Role, error) {
queryString := `INSERT INTO roles (id, moderator, admin, self_assignable, auto_role, guild_id)
VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT DO NOTHING`
_, err := s.DB.Exec(queryString, r.ID, r.IsModerator, r.IsAdmin, r.SelfAssignable, r.AutoRole, r.Guild)
if err != nil {
return nil, err
}
return r, nil
}
func (s *RoleService) DeleteRole(r *goff.Role) error {
queryString := `DELETE FROM roles WHERE id = $1`
_, err := s.DB.Exec(queryString, r.ID)
return err
}
func (s *RoleService) MakeSelfAssignable(r *goff.Role) error {
queryString := `UPDATE roles SET self_assignable = true WHERE id = $1`
_, err := s.DB.Exec(queryString, r.ID)
return err
}
func (s *RoleService) RemoveSelfAssignable(r *goff.Role) error {
queryString := `UPDATE roles SET self_assignable = false WHERE id = $1`
_, err := s.DB.Exec(queryString, r.ID)
return err
}
func (s *RoleService) MakeAutoRole(r *goff.Role) error {
queryString := `UPDATE roles SET auto_role = true WHERE id = $1`
_, err := s.DB.Exec(queryString, r.ID)
return err
}
func (s *RoleService) RemoveAutoRole(r *goff.Role) error {
queryString := `UPDATE roles SET auto_role = false WHERE id = $1`
_, err := s.DB.Exec(queryString, r.ID)
return err
}
func (s *RoleService) GetAutoRoles(gID string) ([]*goff.Role, error) {
var roles []*goff.Role
queryString := `SELECT id FROM roles WHERE guild_id = $1 AND auto_role = true`
rows, err := s.DB.Query(queryString, gID)
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
}

87
internal/postgres/user.go Normal file
View File

@ -0,0 +1,87 @@
package postgres
import (
"database/sql"
"github.com/dustinpianalto/goff"
)
type UserService struct {
DB *sql.DB
}
func (s *UserService) User(id string) (*goff.User, error) {
var u goff.User
queryString := `SELECT id, banned, logging, steam_id, is_active, is_staff, is_admin
FROM users WHERE id=$1`
row := s.DB.QueryRow(queryString, id)
if err := row.Scan(&u.ID, &u.Banned, &u.Logging, &u.SteamID, &u.IsActive, &u.IsStaff, &u.IsAdmin); err != nil {
return nil, err
}
var guilds []string
queryString = `SELECT guild_id from x_users_guilds WHERE user_id=$1`
rows, err := s.DB.Query(queryString, id)
if err != nil {
return nil, err
}
for rows.Next() {
var guildID string
err = rows.Scan(&guildID)
if err != nil {
return nil, err
}
guilds = append(guilds, guildID)
}
u.Guilds = guilds
return &u, nil
}
func (s *UserService) CreateUser(u *goff.User, gid string) error {
queryString := `INSERT INTO users (id, banned, logging, steam_id, is_active, is_staff, is_admin)
VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT DO NOTHING`
_, err := s.DB.Exec(queryString, u.ID, u.Banned, u.Logging, u.SteamID, u.IsActive, u.IsStaff, u.IsAdmin)
if err == nil {
err = s.AddUserToGuild(u, &goff.Guild{ID: gid})
}
return err
}
func (s *UserService) DeleteUser(u *goff.User) error {
queryString := `DELETE CASCADE FROM x_users_guilds WHERE user_id = $1; DELETE FROM users WHERE id = $1`
_, err := s.DB.Exec(queryString, u.ID)
return err
}
func (s *UserService) MarkUserInactive(u *goff.User) error {
queryString := `UPDATE users SET is_active = false WHERE id = $1`
_, err := s.DB.Exec(queryString, u.ID)
if err == nil {
u.IsActive = false
}
return err
}
func (s *UserService) AddUserToGuild(u *goff.User, g *goff.Guild) error {
queryString := `INSERT INTO x_users_guilds (user_id, guild_id) VALUES ($1, $2) ON CONFLICT DO NOTHING`
_, err := s.DB.Exec(queryString, u.ID, g.ID)
return err
}
func (s *UserService) RemoveUserFromGuild(u *goff.User, g *goff.Guild) error {
queryString := `DELETE FROM x_users_guilds WHERE user_id = $1 AND guild_id = $2`
_, err := s.DB.Exec(queryString, u.ID, g.ID)
return err
}
func (s *UserService) UpdateUser(u *goff.User) error {
queryString := `UPDATE users SET
banned = $1,
logging = $2,
steam_id = $3,
is_active = $4,
is_staff = $5,
is_admin = $6
WHERE id = $7`
_, err := s.DB.Exec(queryString, u.Banned, u.Logging, u.SteamID, u.IsActive, u.IsStaff, u.IsAdmin)
return err
}

View File

@ -0,0 +1,13 @@
package services
import "github.com/dustinpianalto/goff"
var UserService goff.UserService
var GuildService goff.GuildService
var RoleService goff.RoleService
func InitalizeServices(us goff.UserService, gs goff.GuildService, rs goff.RoleService) {
UserService = us
GuildService = gs
RoleService = rs
}

View File

@ -1,4 +1,4 @@
package utils
package email
import (
"io"
@ -9,6 +9,7 @@ import (
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/pkg/puzzles"
imap "github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-message/mail"
@ -117,7 +118,7 @@ func processEmail(r io.Reader, dg *discordgo.Session, wg *sync.WaitGroup) {
if addressIn(from, puzzleAddress) &&
strings.Contains(subject, "Daily Coding Problem:") {
log.Println("Processing Puzzle")
ProcessPuzzleEmail(mr, dg)
puzzles.ProcessPuzzleEmail(mr, dg)
}
}

View File

@ -1,4 +1,4 @@
package utils
package puzzles
import (
"io"
@ -8,6 +8,8 @@ import (
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff"
"github.com/dustinpianalto/goff/internal/postgres"
"github.com/emersion/go-message/mail"
)
@ -48,15 +50,15 @@ func ProcessPuzzleEmail(mr *mail.Reader, dg *discordgo.Session) {
Text: "Daily Coding Problem",
},
}
var guilds []Guild
queryString := `SELECT id, puzzle_channel from guilds`
rows, err := Database.Query(queryString)
var guilds []goff.Guild
queryString := `SELECT id, puzzle_channel, puzzle_role from guilds`
rows, err := postgres.DB.Query(queryString)
if err != nil {
log.Println(err)
}
for rows.Next() {
var guild Guild
err := rows.Scan(&guild.ID, &guild.PuzzleChannel)
var guild goff.Guild
err := rows.Scan(&guild.ID, &guild.PuzzleChannel, &guild.PuzzleRole)
if err != nil {
log.Println(err)
continue
@ -65,7 +67,7 @@ func ProcessPuzzleEmail(mr *mail.Reader, dg *discordgo.Session) {
}
var puzzleID int64
queryString = "INSERT INTO puzzles (text, time) VALUES ($1, $2) RETURNING id"
err = Database.QueryRow(queryString, puzzle, date).Scan(&puzzleID)
err = postgres.DB.QueryRow(queryString, puzzle, date).Scan(&puzzleID)
if err != nil {
log.Println(err)
return
@ -74,15 +76,24 @@ func ProcessPuzzleEmail(mr *mail.Reader, dg *discordgo.Session) {
if g.PuzzleChannel == "" {
continue
}
msg := discordgo.MessageSend{
Embed: &e,
var msg discordgo.MessageSend
role, err := dg.State.Role(g.ID, g.PuzzleRole.String)
if err != nil {
msg = discordgo.MessageSend{
Embed: &e,
}
} else {
msg = discordgo.MessageSend{
Content: role.Mention(),
Embed: &e,
}
}
m, err := dg.ChannelMessageSendComplex(g.PuzzleChannel, &msg)
if err != nil {
log.Println(err)
}
queryString = "INSERT INTO x_guilds_puzzles (guild_id, puzzle_id, message_id) VALUES ($1, $2, $3)"
_, err = Database.Exec(queryString, g.ID, puzzleID, m.ID)
_, err = postgres.DB.Exec(queryString, g.ID, puzzleID, m.ID)
if err != nil {
log.Println(err)
continue

21
role.go Normal file
View File

@ -0,0 +1,21 @@
package goff
type Role struct {
ID string
IsModerator bool
IsAdmin bool
SelfAssignable bool
AutoRole bool
Guild string
}
type RoleService interface {
Role(id string) (*Role, error)
AddRole(r *Role) (*Role, error)
DeleteRole(r *Role) error
MakeSelfAssignable(r *Role) error
RemoveSelfAssignable(r *Role) error
MakeAutoRole(r *Role) error
RemoveAutoRole(r *Role) error
GetAutoRoles(gID string) ([]*Role, error)
}

134
task-definition.json Normal file
View File

@ -0,0 +1,134 @@
{
"ipcMode": null,
"executionRoleArn": "arn:aws:iam::005692590034:role/goff_ecs_rds+cw+ecr",
"containerDefinitions": [
{
"dnsSearchDomains": null,
"environmentFiles": null,
"logConfiguration": {
"logDriver": "awslogs",
"secretOptions": null,
"options": {
"awslogs-group": "/ecs/goff",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
},
"entryPoint": null,
"portMappings": [],
"command": null,
"linuxParameters": null,
"cpu": 0,
"environment": [],
"resourceRequirements": null,
"ulimits": null,
"dnsServers": null,
"mountPoints": [],
"workingDirectory": null,
"secrets": [
{
"valueFrom": "goff_database_uri",
"name": "DATABASE_URL"
},
{
"valueFrom": "goff_discord_token",
"name": "DISCORDGO_TOKEN"
},
{
"valueFrom": "goff_email_password",
"name": "GOFF_EMAIL_PASSWORD"
},
{
"valueFrom": "goff_email_username",
"name": "GOFF_EMAIL_USERNAME"
}
],
"dockerSecurityOptions": null,
"memory": 512,
"memoryReservation": null,
"volumesFrom": [],
"stopTimeout": null,
"image": "005692590034.dkr.ecr.us-east-1.amazonaws.com/goff:latest",
"startTimeout": null,
"firelensConfiguration": null,
"dependsOn": null,
"disableNetworking": null,
"interactive": null,
"healthCheck": null,
"essential": true,
"links": null,
"hostname": null,
"extraHosts": null,
"pseudoTerminal": null,
"user": null,
"readonlyRootFilesystem": null,
"dockerLabels": null,
"systemControls": null,
"privileged": null,
"name": "goff"
}
],
"placementConstraints": [],
"memory": "512",
"taskRoleArn": "arn:aws:iam::005692590034:role/goff_ecs_rds+cw+ecr",
"compatibilities": [
"EC2"
],
"taskDefinitionArn": "arn:aws:ecs:us-east-1:005692590034:task-definition/goff:2",
"family": "goff",
"requiresAttributes": [
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "ecs.capability.execution-role-awslogs"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.ecr-auth"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.task-iam-role"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "ecs.capability.execution-role-ecr-pull"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "ecs.capability.secrets.ssm.environment-variables"
}
],
"pidMode": null,
"requiresCompatibilities": [
"EC2"
],
"networkMode": null,
"cpu": "1024",
"revision": 2,
"status": "ACTIVE",
"inferenceAccelerators": null,
"proxyConfiguration": null,
"volumes": []
}

View File

@ -1,4 +0,0 @@
#!/bin/bash
/usr/local/bin/docker-compose build || exit
/usr/local/bin/docker-compose up -d

22
user.go Normal file
View File

@ -0,0 +1,22 @@
package goff
type User struct {
ID string
Banned bool
Logging bool
SteamID string
IsActive bool
IsStaff bool
IsAdmin bool
Guilds []string
}
type UserService interface {
User(id string) (*User, error)
CreateUser(u *User, gid string) error
DeleteUser(u *User) error
MarkUserInactive(u *User) error
AddUserToGuild(u *User, g *Guild) error
RemoveUserFromGuild(u *User, g *Guild) error
UpdateUser(u *User) error
}

View File

@ -1,77 +0,0 @@
package utils
import "log"
type postfix struct {
Name string
Invoke func(bool) error
}
var postfixes = []postfix{
postfix{
Name: "1_Update_Guild_for_Puzzle",
Invoke: updateGuildForPuzzle,
},
postfix{
Name: "1_Update_X_Guild_Prefixes_to_add_ID",
Invoke: updateXGuildPrefixesToAddID,
},
}
func RunPostfixes() {
for _, postfix := range postfixes {
queryString := "SELECT * from postfixes where name = $1"
rows, err := Database.Query(queryString, postfix.Name)
if err != nil {
log.Println(err)
continue
}
if rows.Next() {
continue
} else {
err := postfix.Invoke(false)
if err != nil {
continue
}
_, err = Database.Exec("INSERT INTO postfixes (name) VALUES ($1)", postfix.Name)
if err != nil {
log.Println(err)
continue
}
}
}
}
func updateGuildForPuzzle(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE guilds
ADD COLUMN puzzle_channel varchar(30) not null default ''`
} else {
queryString = `ALTER TABLE guilds
DROP COLUMN puzzleChat`
}
_, err := Database.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func updateXGuildPrefixesToAddID(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE x_guilds_prefixes
ADD COLUMN id serial primary key`
} else {
queryString = `ALTER TABLE x_guilds_prefixes
DROP COLUMN id`
}
_, err := Database.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}

View File

@ -1,156 +0,0 @@
package utils
import (
"fmt"
"strconv"
"strings"
)
type Operator struct {
Token string
Precedence int
Association string
}
func (o Operator) HasHigherPrecedence(t Operator) bool {
return o.Precedence < t.Precedence // lower number is higher precedence
}
func (o Operator) HasEqualPrecedence(t Operator) bool {
return o.Precedence == t.Precedence
}
func (o Operator) IsLeftAssociative() bool {
return o.Association == "left"
}
var operators = map[string]Operator{
"+": Operator{
Token: "+",
Precedence: 4,
Association: "left",
},
"-": Operator{
Token: "-",
Precedence: 4,
Association: "left",
},
"*": Operator{
Token: "*",
Precedence: 3,
Association: "left",
},
"/": Operator{
Token: "/",
Precedence: 3,
Association: "left",
},
"%": Operator{
Token: "%",
Precedence: 3,
Association: "left",
},
"(": Operator{
Token: "(",
Precedence: 1,
Association: "left",
},
")": Operator{
Token: ")",
Precedence: 1,
Association: "left",
},
}
type Stack []Operator
func (s *Stack) IsEmpty() bool {
return len(*s) == 0
}
func (s *Stack) Push(op Operator) {
*s = append(*s, op)
}
func (s *Stack) Pop() (Operator, bool) {
if s.IsEmpty() {
return Operator{}, false
}
index := len(*s) - 1
element := (*s)[index]
*s = (*s)[:index]
return element, true
}
func (s *Stack) Top() Operator {
if s.IsEmpty() {
return Operator{}
}
return (*s)[len(*s)-1]
}
func GenerateRPN(tokens []string) (string, error) {
output := ""
s := Stack{}
for _, token := range tokens {
err := processToken(token, &s, &output)
if err != nil {
return "", err
}
}
for !s.IsEmpty() {
ele, _ := s.Pop()
output += " " + ele.Token
}
return strings.TrimSpace(output), nil
}
func processToken(t string, s *Stack, o *string) error {
if _, err := strconv.Atoi(t); err == nil {
*o += " " + t
return nil
} else if op, ok := operators[t]; ok {
if op.Token == "(" {
s.Push(op)
} else if op.Token == ")" {
if s.IsEmpty() {
return fmt.Errorf("mismatched parentheses")
}
for s.Top().Token != "(" {
if ele, ok := s.Pop(); ok {
*o += " " + ele.Token
} else {
return fmt.Errorf("mismatched parentheses")
}
if s.IsEmpty() {
break
}
}
s.Pop() // Pop and discard the (
} else if !s.IsEmpty() {
for {
if (s.Top().HasHigherPrecedence(op) ||
(s.Top().HasEqualPrecedence(op) &&
op.IsLeftAssociative())) &&
s.Top().Token != "(" {
if ele, ok := s.Pop(); ok {
*o += " " + ele.Token
if s.IsEmpty() {
break
}
continue
} else {
break
}
}
break
}
s.Push(op)
} else {
s.Push(op)
}
return nil
}
return fmt.Errorf("invalid character %s", t)
}

View File

@ -1,95 +0,0 @@
package utils
import (
"errors"
"fmt"
"math"
"strconv"
)
type FStack []float64
func (s *FStack) IsEmpty() bool {
return len(*s) == 0
}
func (s *FStack) Push(op float64) {
*s = append(*s, op)
}
func (s *FStack) Pop() (float64, bool) {
if s.IsEmpty() {
return 0, false
}
index := len(*s) - 1
element := (*s)[index]
*s = (*s)[:index]
return element, true
}
func (s *FStack) PopTwo() (float64, float64, bool) {
if s.IsEmpty() || len(*s) < 2 {
return 0, 0, false
}
index := len(*s) - 1
b := (*s)[index]
a := (*s)[index-1]
*s = (*s)[:index-1]
return a, b, true
}
func (s *FStack) Top() float64 {
if s.IsEmpty() {
return 0
}
return (*s)[len(*s)-1]
}
func ParseRPN(args []string) (float64, error) {
s := FStack{}
for _, token := range args {
switch token {
case "+":
if a, b, ok := s.PopTwo(); ok {
s.Push(a + b)
} else {
return 0, fmt.Errorf("not enough operands on stack for +: %v", s)
}
case "-":
if a, b, ok := s.PopTwo(); ok {
s.Push(a - b)
} else {
return 0, fmt.Errorf("not enough operands on stack for -: %v", s)
}
case "*":
if a, b, ok := s.PopTwo(); ok {
s.Push(a * b)
} else {
return 0, fmt.Errorf("not enough operands on stack for *: %v", s)
}
case "/":
if a, b, ok := s.PopTwo(); ok {
s.Push(a / b)
} else {
return 0, fmt.Errorf("not enough operands on stack for /: %v", s)
}
case "%":
if a, b, ok := s.PopTwo(); ok {
s.Push(math.Mod(a, b))
} else {
return 0, fmt.Errorf("not enough operands on stack for %: %v", s)
}
default:
f, err := strconv.ParseFloat(token, 64)
if err != nil {
return 0, err
}
s.Push(f)
}
}
if res, ok := s.Pop(); ok {
return res, nil
}
return 0, errors.New("no result")
}

View File

@ -1,10 +0,0 @@
package utils
type Guild struct {
ID string
WelcomeMessage string
GoodbyeMessage string
LoggingChannel string
WelcomeChannel string
PuzzleChannel string
}