From 03260f8892c76a92b36747e378082cc2eb2dbf93 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Tue, 8 Sep 2020 05:57:03 +0200 Subject: [PATCH 01/12] Set up main release (#15) Fix setting Signed-off-by: Etzelia Set up main release Signed-off-by: Etzelia Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/15 --- .drone.yml | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/.drone.yml b/.drone.yml index d9435fb..c81b376 100644 --- a/.drone.yml +++ b/.drone.yml @@ -22,7 +22,9 @@ kind: pipeline name: release trigger: event: - - tag + - push + branch: + - master steps: - name: build pull: always @@ -31,18 +33,10 @@ steps: - make build-all - name: gitea-release pull: always - image: plugins/gitea-release:1 + image: jolheiser/drone-gitea-main:latest settings: - api_key: + token: from_secret: gitea_token base_url: https://git.etztech.xyz files: - - "sedbot" - - name: gitea-prune - pull: always - image: jolheiser/dgrp:latest - settings: - base: https://git.etztech.xyz - token: - from_secret: gitea_token - keep: 2 \ No newline at end of file + - "sedbot" \ No newline at end of file From 8769b33bca78648a29d00414cb06e4499728f581 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Tue, 8 Sep 2020 06:01:09 +0200 Subject: [PATCH 02/12] Fix Drone Release (#16) Fix Drone Release Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/16 --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index c81b376..069fa23 100644 --- a/.drone.yml +++ b/.drone.yml @@ -37,6 +37,6 @@ steps: settings: token: from_secret: gitea_token - base_url: https://git.etztech.xyz + base: https://git.etztech.xyz files: - "sedbot" \ No newline at end of file From a581094959b3b019b8ddaf65442116df9ea45f0f Mon Sep 17 00:00:00 2001 From: Etzelia Date: Sat, 17 Oct 2020 06:32:16 +0200 Subject: [PATCH 03/12] Update go-mcm and change Eq to Exact (#18) Update go-mcm and change Eq to Exact Signed-off-by: Etzelia Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/18 --- discord/register.go | 2 +- go.mod | 2 +- go.sum | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/discord/register.go b/discord/register.go index f5b3289..a2cc9b6 100644 --- a/discord/register.go +++ b/discord/register.go @@ -58,7 +58,7 @@ func init() { nickname = player.Username if len(apps) == 0 { - apps, err = models.Application(models.NewDjangoBuilder().Eq(django.ApplicationID, player.ApplicationID)) + apps, err = models.Application(models.NewDjangoBuilder().Exact(django.ApplicationID, player.ApplicationID)) if err != nil { return "Something went wrong, please contact staff", nil } diff --git a/go.mod b/go.mod index 69cbd96..65542c2 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/bwmarrin/discordgo v0.21.1 github.com/gorilla/websocket v1.4.2 // indirect go.etcd.io/bbolt v1.3.4 - go.etztech.xyz/go-mcm v1.3.0 + go.etztech.xyz/go-mcm v1.3.1 go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 go.jolheiser.com/beaver v1.0.2 go.jolheiser.com/gojang v0.0.2 diff --git a/go.sum b/go.sum index 2e1439d..573fed0 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etztech.xyz/go-mcm v1.3.0 h1:ULhLEHRJZYh+hIgHfp7IuqpOn6H7kkrVxnnfzyZLQM0= go.etztech.xyz/go-mcm v1.3.0/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc= +go.etztech.xyz/go-mcm v1.3.1 h1:RLdOQrMgw0eP7bsfRRbXLW8c5/RaJ5Mg7i/ESFaUwvY= +go.etztech.xyz/go-mcm v1.3.1/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc= go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 h1:j/ZeoAj185wHfCSYD52Kt/69i3Bzk1MXN4Qh1yP6+P4= go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359/go.mod h1:+fC1WzJm/oS4UEgqr1jPouWerxBys52lTTDA94/5bf8= go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= From d1600be5d1182e6c654fc7a8c0fb3a36b995736d Mon Sep 17 00:00:00 2001 From: Etzelia Date: Sun, 25 Oct 2020 22:17:40 +0100 Subject: [PATCH 04/12] Add leave messages (#19) Add leave messages Signed-off-by: Etzelia Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/19 --- config/config.go | 14 ++++++++++---- discord/discord.go | 11 +++++++++++ go.mod | 8 ++++---- go.sum | 14 ++++++++++---- sedbot.example.toml | 3 +++ 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/config/config.go b/config/config.go index 1198b1a..5d58dd1 100644 --- a/config/config.go +++ b/config/config.go @@ -4,7 +4,7 @@ import ( "io/ioutil" "os" - "github.com/BurntSushi/toml" + "github.com/pelletier/go-toml" ) var defaultConfig = []byte("") @@ -28,6 +28,7 @@ type Config struct { MessageRoles []MessageRole `toml:"message_roles"` RegisterRole string `toml:"register_role"` RegisteredChannel string `toml:"registered_channel"` + LeaveChannel string `toml:"leave_channel"` FiredRole string `toml:"fired_role"` MemeRate string `toml:"meme_rate"` Insult struct { @@ -76,10 +77,15 @@ func Load(configPath string) (*Config, error) { } } - var cfg *Config - if err = toml.Unmarshal(configContent, &cfg); err != nil { + var cfg Config + tree, err := toml.LoadBytes(configContent) + if err != nil { return nil, err } - return cfg, nil + if err := tree.Unmarshal(&cfg); err != nil { + return nil, err + } + + return &cfg, nil } diff --git a/discord/discord.go b/discord/discord.go index 3a3e5ea..c8eeec2 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -1,6 +1,7 @@ package discord import ( + "fmt" "strings" "time" @@ -48,6 +49,7 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) Echo(cfg) bot.AddHandler(readyHandler()) + bot.AddHandler(leaveHandler(cfg)) bot.AddHandler(commandHandler(cfg, db)) bot.AddHandler(messageHandler(cfg, db)) bot.AddHandler(reactionAddHandler()) @@ -60,6 +62,9 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) } memeRateLimit = NewRateLimit(d) + // Intents + bot.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAll) + return bot, nil } @@ -204,3 +209,9 @@ func reactionHandler(add bool, s *discordgo.Session, m *discordgo.MessageReactio } } } + +func leaveHandler(cfg *config.Config) func(s *discordgo.Session, m *discordgo.GuildMemberRemove) { + return func(s *discordgo.Session, m *discordgo.GuildMemberRemove) { + sendMessage(s, cfg.LeaveChannel, fmt.Sprintf("%s left the server. :sob:", m.Mention()), true) + } +} diff --git a/go.mod b/go.mod index 65542c2..8ac31bc 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,14 @@ module go.etztech.xyz/sedbot go 1.14 require ( - github.com/BurntSushi/toml v0.3.1 - github.com/bwmarrin/discordgo v0.21.1 + github.com/bwmarrin/discordgo v0.22.0 github.com/gorilla/websocket v1.4.2 // indirect + github.com/pelletier/go-toml v1.8.1 go.etcd.io/bbolt v1.3.4 go.etztech.xyz/go-mcm v1.3.1 go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 go.jolheiser.com/beaver v1.0.2 go.jolheiser.com/gojang v0.0.2 - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect - golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect + golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect + golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 // indirect ) diff --git a/go.sum b/go.sum index 573fed0..04db0dd 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,17 @@ -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/bwmarrin/discordgo v0.21.1 h1:UI2PWwzvn5IFuscYcDc6QB/duhs9MUIjQ4HclcIZisc= github.com/bwmarrin/discordgo v0.21.1/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/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/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/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etztech.xyz/go-mcm v1.3.0 h1:ULhLEHRJZYh+hIgHfp7IuqpOn6H7kkrVxnnfzyZLQM0= -go.etztech.xyz/go-mcm v1.3.0/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc= go.etztech.xyz/go-mcm v1.3.1 h1:RLdOQrMgw0eP7bsfRRbXLW8c5/RaJ5Mg7i/ESFaUwvY= go.etztech.xyz/go-mcm v1.3.1/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc= go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 h1:j/ZeoAj185wHfCSYD52Kt/69i3Bzk1MXN4Qh1yP6+P4= @@ -23,6 +25,8 @@ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -32,4 +36,6 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfru golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 h1:iCaAy5bMeEvwANu3YnJfWwI0kWAGkEa2RXPdweI/ysk= +golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/sedbot.example.toml b/sedbot.example.toml index 8297124..242bd19 100644 --- a/sedbot.example.toml +++ b/sedbot.example.toml @@ -19,6 +19,9 @@ register_role = "0" # registered_channel is the channel to message to welcome the newly registered user registered_channel = "0" +# leave_channel is the channel to post leave messages to +leave_channel = "0" + # staff_roles are for staff commands staff_roles = [] From 1a6b6c174abc14059aaea792768483d0cf38a854 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Fri, 30 Oct 2020 21:34:11 +0100 Subject: [PATCH 05/12] Include username#discriminator in leave message (#21) user#discriminator Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/21 --- discord/discord.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/discord.go b/discord/discord.go index c8eeec2..e42bbb2 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -212,6 +212,6 @@ func reactionHandler(add bool, s *discordgo.Session, m *discordgo.MessageReactio func leaveHandler(cfg *config.Config) func(s *discordgo.Session, m *discordgo.GuildMemberRemove) { return func(s *discordgo.Session, m *discordgo.GuildMemberRemove) { - sendMessage(s, cfg.LeaveChannel, fmt.Sprintf("%s left the server. :sob:", m.Mention()), true) + sendMessage(s, cfg.LeaveChannel, fmt.Sprintf("%s (%s) left the server. :sob:", m.Mention(), m.User.String()), true) } } From 6a891d1ed13b588c973d8180ed8aac0adf4c832c Mon Sep 17 00:00:00 2001 From: Etzelia Date: Sat, 9 Jan 2021 03:53:01 +0100 Subject: [PATCH 06/12] Change default branch to main --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 069fa23..91eafe9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -24,7 +24,7 @@ trigger: event: - push branch: - - master + - main steps: - name: build pull: always From bed25234bba2a9b1f4d9204164338ce3e4e77301 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Sat, 9 Jan 2021 04:00:28 +0100 Subject: [PATCH 07/12] Add XKCD and FK (#22) CI restart Merge branch 'main' of git.etztech.xyz:Etzelia/sedbot into memes Add XKCD and FK Signed-off-by: Etzelia Co-authored-by: Etzelia Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/22 Co-Authored-By: Etzelia Co-Committed-By: Etzelia --- discord/birb.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ discord/clear.go | 2 +- discord/xkcd.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ go.mod | 2 ++ go.sum | 4 ++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 discord/birb.go create mode 100644 discord/xkcd.go diff --git a/discord/birb.go b/discord/birb.go new file mode 100644 index 0000000..4f11bb3 --- /dev/null +++ b/discord/birb.go @@ -0,0 +1,46 @@ +package discord + +import ( + "context" + "fmt" + "strconv" + "strings" + + "go.etztech.xyz/falseknees" +) + +func init() { + commands["birb"] = command{ + validate: func(cmd commandInit) bool { + return true + }, + run: func(cmd commandInit) (string, error) { + if !memeRateLimit.Try() { + return "", nil + } + + client := falseknees.New() + + var comic *falseknees.Comic + var err error + args := strings.Fields(cmd.message.Content) + if len(args) < 2 { + comic, err = client.Random(context.Background()) + } else if strings.EqualFold(args[1], "new") { + comic, err = client.Current(context.Background()) + } else { + comicNum, err := strconv.Atoi(args[1]) + if err != nil { + return "", err + } + comic, err = client.Comic(context.Background(), comicNum) + } + if err != nil { + return "", err + } + + return fmt.Sprintf("%d: %s\n%s", comic.Num, comic.Title, comic.Img), nil + }, + help: "Get a FalseKnees comic", + } +} diff --git a/discord/clear.go b/discord/clear.go index d549868..5a3f0e9 100644 --- a/discord/clear.go +++ b/discord/clear.go @@ -24,7 +24,7 @@ func init() { if userID != "" { limitArg = 2 if len(args) < 2 { - return "This command takes needs two arguments with a mention", nil + return "This command takes two arguments with a mention", nil } } else if len(args) < 1 { return "This command takes one argument without a mention", nil diff --git a/discord/xkcd.go b/discord/xkcd.go new file mode 100644 index 0000000..9491239 --- /dev/null +++ b/discord/xkcd.go @@ -0,0 +1,44 @@ +package discord + +import ( + "context" + "fmt" + "strconv" + "strings" + + "go.jolheiser.com/xkcd" +) + +func init() { + commands["xkcd"] = command{ + validate: func(cmd commandInit) bool { + return true + }, + run: func(cmd commandInit) (string, error) { + if !memeRateLimit.Try() { + return "", nil + } + + client := xkcd.New() + + var comic *xkcd.Comic + var err error + args := strings.Fields(cmd.message.Content) + if len(args) < 2 { + comic, err = client.Current(context.Background()) + } else { + comicNum, err := strconv.Atoi(args[1]) + if err != nil { + return "", err + } + comic, err = client.Comic(context.Background(), comicNum) + } + if err != nil { + return "", err + } + + return fmt.Sprintf("%d: %s\n%s\n%s", comic.Num, comic.SafeTitle, comic.Alt, comic.Img), nil + }, + help: "Get an xkcd comic", + } +} diff --git a/go.mod b/go.mod index 8ac31bc..162309c 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,12 @@ require ( github.com/gorilla/websocket v1.4.2 // indirect github.com/pelletier/go-toml v1.8.1 go.etcd.io/bbolt v1.3.4 + go.etztech.xyz/falseknees v0.0.1 go.etztech.xyz/go-mcm v1.3.1 go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 go.jolheiser.com/beaver v1.0.2 go.jolheiser.com/gojang v0.0.2 + go.jolheiser.com/xkcd v0.0.1 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 // indirect ) diff --git a/go.sum b/go.sum index 04db0dd..851a02a 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etztech.xyz/falseknees v0.0.1 h1:XjlBqMyBUH5b7e/9oedEwZ9pnz3sqMhXQv6vnQocxeM= +go.etztech.xyz/falseknees v0.0.1/go.mod h1:Acn1AwrvAArQEqhMBDlak5BvCZ3jgV8vdL8Pe5ZldRE= go.etztech.xyz/go-mcm v1.3.1 h1:RLdOQrMgw0eP7bsfRRbXLW8c5/RaJ5Mg7i/ESFaUwvY= go.etztech.xyz/go-mcm v1.3.1/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc= go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 h1:j/ZeoAj185wHfCSYD52Kt/69i3Bzk1MXN4Qh1yP6+P4= @@ -20,6 +22,8 @@ go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= go.jolheiser.com/gojang v0.0.2 h1:CvQETKT9sFfvuDeYVUkiR0Jh7xIs7Cayi0rZuDrXoZg= go.jolheiser.com/gojang v0.0.2/go.mod h1:hUBULFDoampNM97E1IaYUhkLBJ30sb7iGsoFOdDU76I= +go.jolheiser.com/xkcd v0.0.1 h1:pRNY2BXxUS+NMtKlm/ENumOr7g3k4VWY/QoDri9YSNU= +go.jolheiser.com/xkcd v0.0.1/go.mod h1:AzWPrZToCLfpazsZBkeu/nPuIvurMqfCOptiydz7Dvk= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= From d86a1f86b04c8a6d5b61456d4515659f2f4842f9 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Sun, 17 Jan 2021 03:45:06 +0100 Subject: [PATCH 08/12] Jupiter (#23) Jupiter Signed-off-by: Etzelia Co-authored-by: Etzelia Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/23 Co-Authored-By: Etzelia Co-Committed-By: Etzelia --- config/config.go | 5 +++-- discord/discord.go | 7 ++++++ discord/jupiter.go | 23 +++++++++++++++++++ imgur/imgur.go | 55 +++++++++++++++++++++++++++++++++++++++++++++ sedbot.example.toml | 3 +++ 5 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 discord/jupiter.go create mode 100644 imgur/imgur.go diff --git a/config/config.go b/config/config.go index 5d58dd1..ce83a62 100644 --- a/config/config.go +++ b/config/config.go @@ -20,8 +20,9 @@ type Config struct { Address string `toml:"address"` Port int `toml:"port"` } `toml:"server"` - DBPath string `toml:"db_path"` - MCPath string `toml:"mc_path"` + DBPath string `toml:"db_path"` + MCPath string `toml:"mc_path"` + ImgurClientID string `toml:"imgur_client_id"` StaffRoles []string `toml:"staff_roles"` Echoes []Echo `toml:"echoes"` diff --git a/discord/discord.go b/discord/discord.go index e42bbb2..07c413e 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -7,6 +7,7 @@ import ( "go.etztech.xyz/sedbot/config" "go.etztech.xyz/sedbot/database" + "go.etztech.xyz/sedbot/imgur" "github.com/bwmarrin/discordgo" "go.jolheiser.com/beaver" @@ -39,6 +40,12 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) return nil, err } + // Init Jupiter images + rand.Seed(time.Now().UnixNano()) + if err := imgur.Init(cfg.ImgurClientID); err != nil { + return nil, err + } + for _, messageRole := range cfg.MessageRoles { if messageRoleMap[messageRole.MessageID] == nil { messageRoleMap[messageRole.MessageID] = make(map[string]string) diff --git a/discord/jupiter.go b/discord/jupiter.go new file mode 100644 index 0000000..46e7ebb --- /dev/null +++ b/discord/jupiter.go @@ -0,0 +1,23 @@ +package discord + +import "go.etztech.xyz/sedbot/imgur" + +func init() { + cmd := command{ + validate: func(cmd commandInit) bool { + return true + }, + run: func(cmd commandInit) (string, error) { + if !memeRateLimit.Try() { + return "", nil + } + img := imgur.Images[rand.Intn(len(imgur.Images))-1] + return img.Link, nil + }, + help: "Get a Jupiter image", + } + + commands["jupiter"] = cmd + commands["jup"] = cmd + commands["jupjup"] = cmd +} diff --git a/imgur/imgur.go b/imgur/imgur.go new file mode 100644 index 0000000..b7b6378 --- /dev/null +++ b/imgur/imgur.go @@ -0,0 +1,55 @@ +package imgur + +import ( + "encoding/json" + "fmt" + "net/http" +) + +// TODO Make a client for this in a separate module + +var Images []*Image + +type Response struct { + Images []*Image `json:"data"` + Success bool `json:"success"` + Status int `json:"status"` +} + +type Image struct { + ID string `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + Datetime int `json:"datetime"` + Type string `json:"type"` + Animated bool `json:"animated"` + Width int `json:"width"` + Height int `json:"height"` + Size int `json:"size"` + Views int `json:"views"` + Bandwidth int `json:"bandwidth"` + Deletehash string `json:"deletehash"` + Section string `json:"section"` + Link string `json:"link"` +} + +func Init(clientID string) error { + + req, err := http.NewRequest(http.MethodGet, "https://api.imgur.com/3/album/TaJVIdQ/images", nil) + if err != nil { + return err + } + req.Header.Set("Authorization", fmt.Sprintf("Client-ID %s", clientID)) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + + var imgurResp Response + if err := json.NewDecoder(resp.Body).Decode(&imgurResp); err != nil { + return err + } + Images = imgurResp.Images + return resp.Body.Close() +} diff --git a/sedbot.example.toml b/sedbot.example.toml index 242bd19..f6d4d2b 100644 --- a/sedbot.example.toml +++ b/sedbot.example.toml @@ -28,6 +28,9 @@ staff_roles = [] # meme_rate is the rate limit for memes meme_rate = "0" +# Imgur Client ID +imgur_client_id = "" + # Server options [server] # connection address From cf674102b1004198ab725a6a8fd01c121703dfdf Mon Sep 17 00:00:00 2001 From: Etzelia Date: Wed, 20 Jan 2021 22:26:11 +0100 Subject: [PATCH 09/12] Update gojang (#24) Update gojang Signed-off-by: Etzelia Co-authored-by: Etzelia Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/24 Co-Authored-By: Etzelia Co-Committed-By: Etzelia --- go.mod | 2 +- go.sum | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 162309c..3ee8ad2 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( go.etztech.xyz/go-mcm v1.3.1 go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 go.jolheiser.com/beaver v1.0.2 - go.jolheiser.com/gojang v0.0.2 + go.jolheiser.com/gojang v0.0.3 go.jolheiser.com/xkcd v0.0.1 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 // indirect diff --git a/go.sum b/go.sum index 851a02a..4f5c3cb 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/bwmarrin/discordgo v0.21.1 h1:UI2PWwzvn5IFuscYcDc6QB/duhs9MUIjQ4HclcIZisc= -github.com/bwmarrin/discordgo v0.21.1/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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -20,15 +18,13 @@ go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 h1:j/ZeoAj185wHfCSYD52 go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359/go.mod h1:+fC1WzJm/oS4UEgqr1jPouWerxBys52lTTDA94/5bf8= go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= -go.jolheiser.com/gojang v0.0.2 h1:CvQETKT9sFfvuDeYVUkiR0Jh7xIs7Cayi0rZuDrXoZg= -go.jolheiser.com/gojang v0.0.2/go.mod h1:hUBULFDoampNM97E1IaYUhkLBJ30sb7iGsoFOdDU76I= +go.jolheiser.com/gojang v0.0.3 h1:EWDLMo6X3f67DK2p/mSB680H43t8SDrDYNZnXvY7PLg= +go.jolheiser.com/gojang v0.0.3/go.mod h1:hUBULFDoampNM97E1IaYUhkLBJ30sb7iGsoFOdDU76I= go.jolheiser.com/xkcd v0.0.1 h1:pRNY2BXxUS+NMtKlm/ENumOr7g3k4VWY/QoDri9YSNU= go.jolheiser.com/xkcd v0.0.1/go.mod h1:AzWPrZToCLfpazsZBkeu/nPuIvurMqfCOptiydz7Dvk= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -38,8 +34,6 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 h1:iCaAy5bMeEvwANu3YnJfWwI0kWAGkEa2RXPdweI/ysk= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 2dc22baa282e271ea6fd08c006b4c87c52548d2f Mon Sep 17 00:00:00 2001 From: Etzelia Date: Wed, 20 Jan 2021 23:13:30 +0100 Subject: [PATCH 10/12] Birbs (#25) Update 'discord/status.go' Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/25 Co-Authored-By: Etzelia Co-Committed-By: Etzelia --- discord/status.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discord/status.go b/discord/status.go index d7d3e73..4b786c6 100644 --- a/discord/status.go +++ b/discord/status.go @@ -32,12 +32,12 @@ func init() { Inline: true, }, { - Name: "Player's Online", + Name: "~~Players~~ Birbs Online", Value: fmt.Sprintf("%d / %d", q.CurrentPlayers, q.MaxPlayers), Inline: true, }, { - Name: "Players", + Name: "~~Players~~ Birbs", Value: strings.Join(q.Players, ", "), }, }, From beb2b4a6aa751bcdfbd39544ab1a6e1bd0788616 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Mon, 22 Feb 2021 19:27:49 +0100 Subject: [PATCH 11/12] Add ServerAPI, clean up help, Twitter (#31) Update make commands Remove unnecessary generate step Update Drone to Go 1.16 Add ServerAPI, clean up help, Twitter Signed-off-by: Etzelia Co-authored-by: Etzelia Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/31 Co-Authored-By: Etzelia Co-Committed-By: Etzelia --- .drone.yml | 10 +-- .gitignore | 6 +- Makefile | 7 -- config/config.go | 14 +++- .../sedbot.example.toml | 18 ++++++ database/database.go | 27 +------- database/ping.go | 30 +++++++++ database/unban.go | 49 ++++++++++++++ discord/ban.go | 53 +++++++++++++++ discord/broadcast.go | 41 ++++++++++++ discord/discord.go | 49 +++++++++++--- discord/help.go | 64 +++++++++++++++---- discord/tweet.go | 34 ++++++++++ discord/unban.go | 40 ++++++++++++ discord/unbans.go | 35 ++++++++++ discord/utils.go | 43 +++++++++++++ go.mod | 5 +- go.sum | 24 +++++-- main.go | 2 - sedbot.example.go | 35 ---------- 20 files changed, 478 insertions(+), 108 deletions(-) rename sedbot.example.toml => config/sedbot.example.toml (85%) create mode 100644 database/ping.go create mode 100644 database/unban.go create mode 100644 discord/ban.go create mode 100644 discord/broadcast.go create mode 100644 discord/tweet.go create mode 100644 discord/unban.go create mode 100644 discord/unbans.go delete mode 100644 sedbot.example.go diff --git a/.drone.yml b/.drone.yml index 91eafe9..401caf9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,13 +7,13 @@ trigger: steps: - name: build pull: always - image: golang:1.15 + image: golang:1.16 commands: - make test - - make build-all + - make build - name: check pull: always - image: golang:1.15 + image: golang:1.16 commands: - make vet @@ -28,9 +28,9 @@ trigger: steps: - name: build pull: always - image: golang:1.15 + image: golang:1.16 commands: - - make build-all + - make build - name: gitea-release pull: always image: jolheiser/drone-gitea-main:latest diff --git a/.gitignore b/.gitignore index 0e03ca1..e1c8229 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ # GoLand .idea/ -# Generated -config/config_default.go - # sedbot -sedbot* \ No newline at end of file +sedbot* +!config/sedbot.example.toml \ No newline at end of file diff --git a/Makefile b/Makefile index 970187d..339839a 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,6 @@ fmt: imp: imp -w -.PHONY: generate -generate: - $(GO) generate ./... - .PHONY: test test: $(GO) test -race ./... @@ -24,8 +20,5 @@ vet: build: $(GO) build -.PHONY: build-all -build-all: generate build - .PHONY: check check: generate imp fmt test vet build \ No newline at end of file diff --git a/config/config.go b/config/config.go index ce83a62..a1bd19e 100644 --- a/config/config.go +++ b/config/config.go @@ -1,13 +1,15 @@ package config import ( + _ "embed" "io/ioutil" "os" "github.com/pelletier/go-toml" ) -var defaultConfig = []byte("") +//go:embed sedbot.example.toml +var defaultConfig []byte type Config struct { Token string `toml:"token"` @@ -23,6 +25,16 @@ type Config struct { DBPath string `toml:"db_path"` MCPath string `toml:"mc_path"` ImgurClientID string `toml:"imgur_client_id"` + ServerAPI struct { + Endpoint string `toml:"endpoint"` + Token string `toml:"token"` + } `toml:"serverapi"` + Twitter struct { + ConsumerKey string `toml:"consumer_key"` + ConsumerSecret string `toml:"consumer_secret"` + AccessToken string `toml:"access_token"` + AccessSecret string `toml:"access_secret"` + } `toml:"twitter"` StaffRoles []string `toml:"staff_roles"` Echoes []Echo `toml:"echoes"` diff --git a/sedbot.example.toml b/config/sedbot.example.toml similarity index 85% rename from sedbot.example.toml rename to config/sedbot.example.toml index f6d4d2b..4af6fcc 100644 --- a/sedbot.example.toml +++ b/config/sedbot.example.toml @@ -31,6 +31,24 @@ meme_rate = "0" # Imgur Client ID imgur_client_id = "" +# ServerAPI options +[serverapi] +# API endpoint +endpoint = "" +# Auth token +token = "" + +# Twitter options +[twitter] +# Consumer Key +consumer_key = "" +# Consumer Secret +consumer_secret = "" +# Access Token +access_token = "" +# Access Secret +access_secret = "" + # Server options [server] # connection address diff --git a/database/database.go b/database/database.go index 8f3c9ac..663312e 100644 --- a/database/database.go +++ b/database/database.go @@ -1,16 +1,16 @@ package database import ( - "strconv" - "go.etcd.io/bbolt" ) var ( firedBucket = []byte("fired") + unbanBucket = []byte("unban") buckets = [][]byte{ firedBucket, + unbanBucket, } ) @@ -35,26 +35,3 @@ func Load(dbPath string) (*Database, error) { db: db, }, nil } - -func (db *Database) CheckPing(roleID string) int { - roleIDByte := []byte(roleID) - var idx int - _ = db.db.View(func(tx *bbolt.Tx) error { - num := tx.Bucket(firedBucket).Get(roleIDByte) - if num != nil { - if i, err := strconv.Atoi(string(num)); err == nil { - idx = i - } - } - return nil - }) - return idx -} - -func (db *Database) IncrementPing(roleID string) error { - roleIDByte := []byte(roleID) - return db.db.Update(func(tx *bbolt.Tx) error { - idx := db.CheckPing(roleID) - return tx.Bucket(firedBucket).Put(roleIDByte, []byte(strconv.Itoa(idx+1))) - }) -} diff --git a/database/ping.go b/database/ping.go new file mode 100644 index 0000000..7f0738d --- /dev/null +++ b/database/ping.go @@ -0,0 +1,30 @@ +package database + +import ( + "strconv" + + "go.etcd.io/bbolt" +) + +func (db *Database) CheckPing(roleID string) int { + roleIDByte := []byte(roleID) + var idx int + _ = db.db.View(func(tx *bbolt.Tx) error { + num := tx.Bucket(firedBucket).Get(roleIDByte) + if num != nil { + if i, err := strconv.Atoi(string(num)); err == nil { + idx = i + } + } + return nil + }) + return idx +} + +func (db *Database) IncrementPing(roleID string) error { + roleIDByte := []byte(roleID) + return db.db.Update(func(tx *bbolt.Tx) error { + idx := db.CheckPing(roleID) + return tx.Bucket(firedBucket).Put(roleIDByte, []byte(strconv.Itoa(idx+1))) + }) +} diff --git a/database/unban.go b/database/unban.go new file mode 100644 index 0000000..ce7c205 --- /dev/null +++ b/database/unban.go @@ -0,0 +1,49 @@ +package database + +import ( + "strconv" + "time" + + "go.etcd.io/bbolt" +) + +type UnbanRecord struct { + Username string + Expiration time.Time +} + +func (u UnbanRecord) ExpirationString() string { + return u.Expiration.Format("01/02/2006 at 03:04:05 pm MST") +} + +func (db *Database) ListUnbans() []UnbanRecord { + unbans := make([]UnbanRecord, 0) + _ = db.db.View(func(tx *bbolt.Tx) error { + return tx.Bucket(unbanBucket).ForEach(func(username, unix []byte) error { + unixNum, err := strconv.ParseInt(string(unix), 10, 64) + if err != nil { + return err + } + unbans = append(unbans, UnbanRecord{ + Username: string(username), + Expiration: time.Unix(unixNum, 0), + }) + return nil + }) + }) + return unbans +} + +func (db *Database) AddUnban(record UnbanRecord) error { + usernameByte := []byte(record.Username) + return db.db.Update(func(tx *bbolt.Tx) error { + return tx.Bucket(unbanBucket).Put(usernameByte, []byte(strconv.FormatInt(record.Expiration.Unix(), 10))) + }) +} + +func (db *Database) RemoveUnban(username string) error { + usernameByte := []byte(username) + return db.db.Update(func(tx *bbolt.Tx) error { + return tx.Bucket(unbanBucket).Delete(usernameByte) + }) +} diff --git a/discord/ban.go b/discord/ban.go new file mode 100644 index 0000000..de427ac --- /dev/null +++ b/discord/ban.go @@ -0,0 +1,53 @@ +package discord + +import ( + "fmt" + "net/http" + "strings" + "time" + + "go.etztech.xyz/go-serverapi" +) + +func init() { + commands["ban"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + args := strings.Fields(cmd.message.Content) + + if len(args) < 2 { + return "This command requires an in-game username.", nil + } + target := args[1] + reason := "You have been banned. Appeal at https://birbmc.com/appeal" + if len(args) >= 3 { + reason = fmt.Sprintf("%s. Appeal at https://birbmc.com/appeal", strings.Join(args[2:], " ")) + } + + ban := serverapi.Ban{ + Kick: serverapi.Kick{ + Unban: serverapi.Unban{ + Target: target, + }, + Reason: reason, + }, + Source: "Discord", + Created: time.Now().Unix(), + } + + status, err := cmd.sapiClient.Ban(ban) + if err != nil { + return "", err + } + if status != http.StatusOK { + return fmt.Sprintf("ServerAPI returned status %d when trying to ban %s", status, target), nil + } + + return fmt.Sprintf("%s was banned by %s", target, cmd.message.Author.Username), nil + }, + help: "Ban a player", + } +} diff --git a/discord/broadcast.go b/discord/broadcast.go new file mode 100644 index 0000000..6b69c17 --- /dev/null +++ b/discord/broadcast.go @@ -0,0 +1,41 @@ +package discord + +import ( + "fmt" + "net/http" + "strings" + + "go.etztech.xyz/go-serverapi" +) + +func init() { + commands["broadcast"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + args := strings.Fields(cmd.message.Content) + + if len(args) < 2 { + return "This command requires a message to broadcast", nil + } + + message := strings.Join(args[1:], " ") + broadcast := serverapi.Broadcast{ + From: cmd.message.Author.Username, + Message: message, + } + status, err := cmd.sapiClient.Broadcast(broadcast) + if err != nil { + return "", err + } + if status != http.StatusOK { + return fmt.Sprintf("ServerAPI returned status %d when trying to broadcast.", status), nil + } + + return "Broadcast sent!", nil + }, + help: "Send an in-game broadcast", + } +} diff --git a/discord/discord.go b/discord/discord.go index 07c413e..33c96b8 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -10,6 +10,9 @@ import ( "go.etztech.xyz/sedbot/imgur" "github.com/bwmarrin/discordgo" + "github.com/dghubble/go-twitter/twitter" + "github.com/dghubble/oauth1" + "go.etztech.xyz/go-serverapi" "go.jolheiser.com/beaver" ) @@ -22,13 +25,17 @@ var ( ) type commandInit struct { - session *discordgo.Session - message *discordgo.Message - config *config.Config - database *database.Database + session *discordgo.Session + message *discordgo.Message + config *config.Config + database *database.Database + sapiClient *serverapi.Client + twitterClient *twitter.Client } type command struct { + staffOnly bool + // TODO Does this really need to exist separately? validate func(cmd commandInit) bool run func(cmd commandInit) (string, error) help string @@ -46,6 +53,22 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) return nil, err } + // Init ServerAPI + sapi := serverapi.NewClient(cfg.ServerAPI.Endpoint, serverapi.WithToken(cfg.ServerAPI.Token)) + + // Init Twitter + twitterConfig := oauth1.NewConfig(cfg.Twitter.ConsumerKey, cfg.Twitter.ConsumerSecret) + twitterToken := oauth1.NewToken(cfg.Twitter.AccessToken, cfg.Twitter.AccessSecret) + twitterHttpClient := twitterConfig.Client(oauth1.NoContext, twitterToken) + twitterClient := twitter.NewClient(twitterHttpClient) + + // Init Unban Schedule + sched := &unbanSchedule{ + db: db, + sapi: sapi, + } + go sched.Run() + for _, messageRole := range cfg.MessageRoles { if messageRoleMap[messageRole.MessageID] == nil { messageRoleMap[messageRole.MessageID] = make(map[string]string) @@ -57,7 +80,7 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) Echo(cfg) bot.AddHandler(readyHandler()) bot.AddHandler(leaveHandler(cfg)) - bot.AddHandler(commandHandler(cfg, db)) + bot.AddHandler(commandHandler(cfg, db, sapi, twitterClient)) bot.AddHandler(messageHandler(cfg, db)) bot.AddHandler(reactionAddHandler()) bot.AddHandler(reactionRemoveHandler()) @@ -125,7 +148,7 @@ func readyHandler() func(s *discordgo.Session, m *discordgo.Ready) { } } -func commandHandler(cfg *config.Config, db *database.Database) func(s *discordgo.Session, m *discordgo.MessageCreate) { +func commandHandler(cfg *config.Config, db *database.Database, sapi *serverapi.Client, twitterClient *twitter.Client) func(s *discordgo.Session, m *discordgo.MessageCreate) { return func(s *discordgo.Session, m *discordgo.MessageCreate) { // Ignore bots if m.Author.Bot { @@ -150,11 +173,17 @@ func commandHandler(cfg *config.Config, db *database.Database) func(s *discordgo return } + if cmd.staffOnly && !isStaff(m.Member.Roles, cfg.StaffRoles) { + return + } + cmdInit := commandInit{ - session: s, - message: m.Message, - config: cfg, - database: db, + session: s, + message: m.Message, + config: cfg, + database: db, + sapiClient: sapi, + twitterClient: twitterClient, } if !cmd.validate(cmdInit) { sendMessage(s, m.ChannelID, "You cannot run this command.", false) diff --git a/discord/help.go b/discord/help.go index cc7170a..3d80eb8 100644 --- a/discord/help.go +++ b/discord/help.go @@ -1,8 +1,9 @@ package discord import ( - "fmt" "strings" + + "github.com/bwmarrin/discordgo" ) func init() { @@ -13,29 +14,64 @@ func init() { run: func(cmd commandInit) (string, error) { args := strings.Fields(cmd.message.Content)[1:] - var resp string + var resp *discordgo.MessageEmbed if len(args) == 1 { - resp = singleHelp(args[0]) + resp = singleHelp(cmd, args[0]) } else { - resp = allHelp() + resp = allHelp(cmd) } - return resp, nil + + channel, err := cmd.session.UserChannelCreate(cmd.message.Author.ID) + if err != nil { + return "", err + } + + sendEmbed(cmd.session, channel.ID, resp) + return "", nil }, help: "HELP! HEEEEEEEEEELP!", } } -func singleHelp(cmd string) string { - if c, ok := commands[cmd]; ok { - return fmt.Sprintf("%s: %s", cmd, c.help) +func singleHelp(cmd commandInit, arg string) *discordgo.MessageEmbed { + embed := &discordgo.MessageEmbed{ + Title: "Unkown Command", } - return "Unknown command" + c, ok := commands[arg] + if !ok { + return embed + } + + if c.staffOnly && !isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) { + return embed + } + + embed.Title = arg + embed.Description = c.help + return embed } -func allHelp() string { - helps := make([]string, 0) - for n, c := range commands { - helps = append(helps, fmt.Sprintf("%s: %s", n, c.help)) +func allHelp(cmd commandInit) *discordgo.MessageEmbed { + staff := isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + embed := &discordgo.MessageEmbed{ + Title: "SedBot Help", + Fields: make([]*discordgo.MessageEmbedField, 0), } - return strings.Join(helps, "\n") + if staff { + embed.Description = "Commands with an asterisk (*) are staff-only" + } + for n, c := range commands { + cmdName := n + if c.staffOnly { + cmdName += "*" + } + if !c.staffOnly || staff { + embed.Fields = append(embed.Fields, &discordgo.MessageEmbedField{ + Name: cmdName, + Value: c.help, + Inline: true, + }) + } + } + return embed } diff --git a/discord/tweet.go b/discord/tweet.go new file mode 100644 index 0000000..32b9269 --- /dev/null +++ b/discord/tweet.go @@ -0,0 +1,34 @@ +package discord + +import ( + "fmt" + "strings" +) + +func init() { + commands["tweet"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + args := strings.Fields(cmd.message.Content) + + if len(args) < 2 { + return "This command requires a message to tweet", nil + } + + message := strings.Join(args[1:], " ") + tweet, resp, err := cmd.twitterClient.Statuses.Update(message, nil) + if err != nil { + return "", err + } + if resp.StatusCode%100 != 2 { + + } + + return fmt.Sprintf("https://twitter.com/%d/status/%d", tweet.User.ID, tweet.ID), nil + }, + help: "Send a tweet from the BirbMC Twitter", + } +} diff --git a/discord/unban.go b/discord/unban.go new file mode 100644 index 0000000..324b90c --- /dev/null +++ b/discord/unban.go @@ -0,0 +1,40 @@ +package discord + +import ( + "fmt" + "strconv" + "strings" + "time" + + "go.etztech.xyz/sedbot/database" +) + +func init() { + commands["unban"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + args := strings.Fields(cmd.message.Content) + + if len(args) < 3 { + return "This command requires an in-game username and number of days (use 0 days to unban on next schedule).", nil + } + days, err := strconv.Atoi(args[2]) + if err != nil { + return "number of days must be an integer", nil + } + target := args[1] + expiration := time.Now().Add(time.Hour * 24 * time.Duration(days)) + record := database.UnbanRecord{ + Username: target, + Expiration: expiration, + } + + return fmt.Sprintf("%s will be unbanned on %s", target, record.ExpirationString()), + cmd.database.AddUnban(record) + }, + help: "Unban a player", + } +} diff --git a/discord/unbans.go b/discord/unbans.go new file mode 100644 index 0000000..698ab60 --- /dev/null +++ b/discord/unbans.go @@ -0,0 +1,35 @@ +package discord + +import ( + "github.com/bwmarrin/discordgo" +) + +func init() { + commands["unbans"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + unbans := cmd.database.ListUnbans() + if len(unbans) == 0 { + return "There are no pending unbans", nil + } + + embed := &discordgo.MessageEmbed{ + Fields: make([]*discordgo.MessageEmbedField, len(unbans)), + } + for i, record := range cmd.database.ListUnbans() { + embed.Fields[i] = &discordgo.MessageEmbedField{ + Name: record.Username, + Value: record.ExpirationString(), + Inline: true, + } + } + + sendEmbed(cmd.session, cmd.message.ChannelID, embed) + return "", nil + }, + help: "Unban a player", + } +} diff --git a/discord/utils.go b/discord/utils.go index 7406bbb..22b60cc 100644 --- a/discord/utils.go +++ b/discord/utils.go @@ -2,7 +2,13 @@ package discord import ( r "math/rand" + "net/http" "time" + + "go.etztech.xyz/sedbot/database" + + "go.etztech.xyz/go-serverapi" + "go.jolheiser.com/beaver" ) type rateLimit struct { @@ -38,3 +44,40 @@ func random(list []string) string { idx := rand.Intn(size) return list[idx] } + +type unbanSchedule struct { + db *database.Database + sapi *serverapi.Client +} + +func (u *unbanSchedule) Run() { + u.check() + ticker := time.NewTicker(time.Minute * 5) + for { + <-ticker.C + u.check() + } +} + +func (u *unbanSchedule) check() { + beaver.Debug("Running unban schedule") + now := time.Now() + for _, record := range u.db.ListUnbans() { + if now.After(record.Expiration) { + beaver.Infof("Unbanning %s", record.Username) + unban := serverapi.Unban{ + Target: record.Username, + } + status, err := u.sapi.Unban(unban) + if err != nil { + beaver.Error(err) + } + if status != http.StatusOK { + beaver.Errorf("ServerAPI returned status %d when trying to ban %s", status, record.Username) + } + if err := u.db.RemoveUnban(record.Username); err != nil { + beaver.Errorf("could not remove unban for %s in database", record.Username) + } + } + } +} diff --git a/go.mod b/go.mod index 3ee8ad2..f90ef43 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,17 @@ module go.etztech.xyz/sedbot -go 1.14 +go 1.16 require ( github.com/bwmarrin/discordgo v0.22.0 + github.com/dghubble/go-twitter v0.0.0-20201011215211-4b180d0cc78d + github.com/dghubble/oauth1 v0.7.0 github.com/gorilla/websocket v1.4.2 // indirect github.com/pelletier/go-toml v1.8.1 go.etcd.io/bbolt v1.3.4 go.etztech.xyz/falseknees v0.0.1 go.etztech.xyz/go-mcm v1.3.1 + go.etztech.xyz/go-serverapi v0.0.3 go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 go.jolheiser.com/beaver v1.0.2 go.jolheiser.com/gojang v0.0.3 diff --git a/go.sum b/go.sum index 4f5c3cb..7ba0f54 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,46 @@ 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/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= +github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +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/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/dghubble/go-twitter v0.0.0-20201011215211-4b180d0cc78d h1:sBKr0A8iQ1qAOozedZ8Aox+Jpv+TeP1Qv7dcQyW8V+M= +github.com/dghubble/go-twitter v0.0.0-20201011215211-4b180d0cc78d/go.mod h1:xfg4uS5LEzOj8PgZV7SQYRHbG7jPUnelEiaAVJxmhJE= +github.com/dghubble/oauth1 v0.7.0 h1:AlpZdbRiJM4XGHIlQ8BuJ/wlpGwFEJNnB4Mc+78tA/w= +github.com/dghubble/oauth1 v0.7.0/go.mod h1:8pFdfPkv/jr8mkChVbNVuJ0suiHe278BtWI4Tk1ujxk= +github.com/dghubble/sling v1.3.0 h1:pZHjCJq4zJvc6qVQ5wN1jo5oNZlNE0+8T/h0XeXBUKU= +github.com/dghubble/sling v1.3.0/go.mod h1:XXShWaBWKzNLhu2OxikSNFrlsvowtz4kyRuXUG7oQKY= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/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/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +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= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etztech.xyz/falseknees v0.0.1 h1:XjlBqMyBUH5b7e/9oedEwZ9pnz3sqMhXQv6vnQocxeM= go.etztech.xyz/falseknees v0.0.1/go.mod h1:Acn1AwrvAArQEqhMBDlak5BvCZ3jgV8vdL8Pe5ZldRE= go.etztech.xyz/go-mcm v1.3.1 h1:RLdOQrMgw0eP7bsfRRbXLW8c5/RaJ5Mg7i/ESFaUwvY= go.etztech.xyz/go-mcm v1.3.1/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc= +go.etztech.xyz/go-serverapi v0.0.3 h1:h2Zww0x5E61cH4jXB97x3oUnbryEuLkuq+RTgIi5/U4= +go.etztech.xyz/go-serverapi v0.0.3/go.mod h1:tq4J5zxVnAwzOiv79iLUzpfNAd7IoNirOfb0gt3/IEY= go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 h1:j/ZeoAj185wHfCSYD52Kt/69i3Bzk1MXN4Qh1yP6+P4= go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359/go.mod h1:+fC1WzJm/oS4UEgqr1jPouWerxBys52lTTDA94/5bf8= go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= go.jolheiser.com/gojang v0.0.3 h1:EWDLMo6X3f67DK2p/mSB680H43t8SDrDYNZnXvY7PLg= go.jolheiser.com/gojang v0.0.3/go.mod h1:hUBULFDoampNM97E1IaYUhkLBJ30sb7iGsoFOdDU76I= +go.jolheiser.com/gql v0.0.1 h1:y3LGHcJUZI9otTCcMn8TVdF3aEzNX0FW6m0YUamlLto= +go.jolheiser.com/gql v0.0.1/go.mod h1:74eYqVRIxsOFxtVl0RYGKNyYQgJYQaxOCgar7LP71Hw= go.jolheiser.com/xkcd v0.0.1 h1:pRNY2BXxUS+NMtKlm/ENumOr7g3k4VWY/QoDri9YSNU= go.jolheiser.com/xkcd v0.0.1/go.mod h1:AzWPrZToCLfpazsZBkeu/nPuIvurMqfCOptiydz7Dvk= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= @@ -30,9 +48,7 @@ golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 h1:iCaAy5bMeEvwANu3YnJfWwI0kWAGkEa2RXPdweI/ysk= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/main.go b/main.go index 442ec31..9be634f 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,3 @@ -//go:generate go run sedbot.example.go - package main import ( diff --git a/sedbot.example.go b/sedbot.example.go deleted file mode 100644 index 10abce6..0000000 --- a/sedbot.example.go +++ /dev/null @@ -1,35 +0,0 @@ -// +build ignore - -package main - -import ( - "fmt" - "io/ioutil" - "os" -) - -const ( - exampleFile = "sedbot.example.toml" - writeFile = "config/config_default.go" - tmpl = `package config - -func init() { - defaultConfig = []byte(` + "`" + `%s` + "`" + `) -} -` -) - -func main() { - bytes, err := ioutil.ReadFile(exampleFile) - if err != nil { - fmt.Printf("Could not read from %s. Are you in the root directory of the project?", exampleFile) - os.Exit(1) - } - - data := fmt.Sprintf(tmpl, string(bytes)) - - if err := ioutil.WriteFile(writeFile, []byte(data), os.ModePerm); err != nil { - fmt.Printf("Could not write to %s.", writeFile) - os.Exit(1) - } -} From dec436805c9d0fe4a0b465c4a9a5b534fac85ae1 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Mon, 22 Feb 2021 23:53:55 -0600 Subject: [PATCH 12/12] Clean up Signed-off-by: Etzelia --- discord/ban.go | 5 ++-- discord/birb.go | 5 ++-- discord/broadcast.go | 5 ++-- discord/clear.go | 5 ++-- discord/compliment.go | 5 ++-- discord/dad.go | 5 ++-- discord/discord.go | 30 +++++++++++++++++++--- discord/echo.go | 59 ++++++++++++++++++++++++++----------------- discord/fired.go | 5 ++-- discord/help.go | 25 +++++++++++++----- discord/history.go | 9 +++---- discord/inspire.go | 5 ++-- discord/insult.go | 5 ++-- discord/jupiter.go | 10 +++----- discord/register.go | 5 ++-- discord/status.go | 11 +++----- discord/tweet.go | 5 ++-- discord/unban.go | 5 ++-- discord/unbans.go | 7 ++--- discord/welcome.go | 10 +++----- discord/xkcd.go | 5 ++-- 21 files changed, 140 insertions(+), 86 deletions(-) diff --git a/discord/ban.go b/discord/ban.go index de427ac..1180784 100644 --- a/discord/ban.go +++ b/discord/ban.go @@ -10,8 +10,9 @@ import ( ) func init() { - commands["ban"] = command{ + commands = append(commands, &command{ staffOnly: true, + name: "ban", validate: func(cmd commandInit) bool { return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) }, @@ -49,5 +50,5 @@ func init() { return fmt.Sprintf("%s was banned by %s", target, cmd.message.Author.Username), nil }, help: "Ban a player", - } + }) } diff --git a/discord/birb.go b/discord/birb.go index 4f11bb3..91642c3 100644 --- a/discord/birb.go +++ b/discord/birb.go @@ -10,7 +10,8 @@ import ( ) func init() { - commands["birb"] = command{ + commands = append(commands, &command{ + name: "birb", validate: func(cmd commandInit) bool { return true }, @@ -42,5 +43,5 @@ func init() { return fmt.Sprintf("%d: %s\n%s", comic.Num, comic.Title, comic.Img), nil }, help: "Get a FalseKnees comic", - } + }) } diff --git a/discord/broadcast.go b/discord/broadcast.go index 6b69c17..18de5d1 100644 --- a/discord/broadcast.go +++ b/discord/broadcast.go @@ -9,8 +9,9 @@ import ( ) func init() { - commands["broadcast"] = command{ + commands = append(commands, &command{ staffOnly: true, + name: "broadcast", validate: func(cmd commandInit) bool { return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) }, @@ -37,5 +38,5 @@ func init() { return "Broadcast sent!", nil }, help: "Send an in-game broadcast", - } + }) } diff --git a/discord/clear.go b/discord/clear.go index 5a3f0e9..f75c676 100644 --- a/discord/clear.go +++ b/discord/clear.go @@ -8,7 +8,8 @@ import ( const clearMax = 20 func init() { - commands["clear"] = command{ + commands = append(commands, &command{ + name: "clear", validate: func(cmd commandInit) bool { return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) }, @@ -64,5 +65,5 @@ func init() { return "", cmd.session.ChannelMessagesBulkDelete(cmd.message.ChannelID, batch) }, help: "Clear messages", - } + }) } diff --git a/discord/compliment.go b/discord/compliment.go index 3df9afa..f26066d 100644 --- a/discord/compliment.go +++ b/discord/compliment.go @@ -6,7 +6,8 @@ import ( ) func init() { - commands["compliment"] = command{ + commands = append(commands, &command{ + name: "compliment", validate: func(cmd commandInit) bool { return true }, @@ -38,5 +39,5 @@ func init() { return "", nil }, help: "Compliment someone!", - } + }) } diff --git a/discord/dad.go b/discord/dad.go index 7744e99..a9fb940 100644 --- a/discord/dad.go +++ b/discord/dad.go @@ -18,7 +18,8 @@ type dadJoke struct { } func init() { - commands["dad"] = command{ + commands = append(commands, &command{ + name: "dad", validate: func(cmd commandInit) bool { return true }, @@ -60,5 +61,5 @@ func init() { return dj.Joke, nil }, help: "Get a random Dad joke", - } + }) } diff --git a/discord/discord.go b/discord/discord.go index 33c96b8..5b0c533 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -18,10 +18,12 @@ import ( // Register commands to this map var ( - commands = make(map[string]command) + commands = make([]*command, 0) + commandMap = make(map[string]*command) messageRoleMap = make(map[string]map[string]string) memeRateLimit *rateLimit + embedColor = 0x007D96 ) type commandInit struct { @@ -34,10 +36,14 @@ type commandInit struct { } type command struct { - staffOnly bool + staffOnly bool + deleteInvocation bool + echo bool // TODO Does this really need to exist separately? validate func(cmd commandInit) bool run func(cmd commandInit) (string, error) + name string + aliases []string help string } @@ -77,7 +83,19 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) messageRoleMap[messageRole.MessageID][messageRole.Emoji] = messageRole.RoleID } + // Init commandMap Echo(cfg) + for _, c := range commands { + if c.name == "" { + beaver.Errorf("command is missing a name: %s", c.help) + continue + } + commandMap[c.name] = c + for _, a := range c.aliases { + commandMap[a] = c + } + } + bot.AddHandler(readyHandler()) bot.AddHandler(leaveHandler(cfg)) bot.AddHandler(commandHandler(cfg, db, sapi, twitterClient)) @@ -123,6 +141,7 @@ func sendMessage(s *discordgo.Session, channelID, content string, scrub bool) *d } func sendEmbed(s *discordgo.Session, channelID string, embed *discordgo.MessageEmbed) *discordgo.Message { + embed.Color = embedColor msg, err := s.ChannelMessageSendEmbed(channelID, embed) if err != nil { beaver.Errorf("could not send embed: %v", err) @@ -168,7 +187,7 @@ func commandHandler(cfg *config.Config, db *database.Database, sapi *serverapi.C cmdArg := strings.ToLower(args[0]) - cmd, ok := commands[cmdArg] + cmd, ok := commandMap[cmdArg] if !ok { return } @@ -189,6 +208,11 @@ func commandHandler(cfg *config.Config, db *database.Database, sapi *serverapi.C sendMessage(s, m.ChannelID, "You cannot run this command.", false) return } + if cmd.deleteInvocation { + if err := s.ChannelMessageDelete(m.Message.ChannelID, m.Message.ID); err != nil { + beaver.Warnf("could not remove invocation for %s: %v", m.Content, err) + } + } feedback, err := cmd.run(cmdInit) if err != nil { feedback = "Internal error" diff --git a/discord/echo.go b/discord/echo.go index b450a02..9ba244b 100644 --- a/discord/echo.go +++ b/discord/echo.go @@ -5,44 +5,57 @@ import ( "strings" "go.etztech.xyz/sedbot/config" + + "github.com/bwmarrin/discordgo" ) func Echo(cfg *config.Config) { - echoes := make([]string, 0) for _, e := range cfg.Echoes { - echo := e - commands[echo.Name] = command{ + commands = append(commands, &command{ + name: e.Name, + aliases: e.Aliases, + echo: true, validate: func(cmd commandInit) bool { return true }, run: func(cmd commandInit) (string, error) { - return echo.Message, nil + return e.Message, nil }, - help: echo.Help, - } - for _, a := range echo.Aliases { - alias := a - commands[alias] = command{ - validate: func(cmd commandInit) bool { - return true - }, - run: func(cmd commandInit) (string, error) { - return echo.Message, nil - }, - help: echo.Help, - } - } - combined := append([]string{echo.Name}, echo.Aliases...) - echoes = append(echoes, fmt.Sprintf("**%s**: %s", strings.Join(combined, ", "), echo.Help)) + help: e.Help, + }) } - commands["echoes"] = command{ + commands = append(commands, &command{ + deleteInvocation: true, + name: "echoes", validate: func(cmd commandInit) bool { return true }, run: func(cmd commandInit) (string, error) { - return strings.Join(echoes, "\n"), nil + embed := &discordgo.MessageEmbed{ + Title: "Echo Commands", + Fields: make([]*discordgo.MessageEmbedField, len(cfg.Echoes)), + } + for i, echo := range cfg.Echoes { + name := echo.Name + if len(echo.Aliases) > 0 { + name += fmt.Sprintf(" (%s)", strings.Join(echo.Aliases, ", ")) + } + embed.Fields[i] = &discordgo.MessageEmbedField{ + Name: name, + Value: echo.Help, + Inline: true, + } + } + + channel, err := cmd.session.UserChannelCreate(cmd.message.Author.ID) + if err != nil { + return "", err + } + + sendEmbed(cmd.session, channel.ID, embed) + return "", nil }, help: "Get all dynamic messages", - } + }) } diff --git a/discord/fired.go b/discord/fired.go index 7247018..6c5c5b8 100644 --- a/discord/fired.go +++ b/discord/fired.go @@ -5,7 +5,8 @@ import ( ) func init() { - commands["fired"] = command{ + commands = append(commands, &command{ + name: "fired", validate: func(cmd commandInit) bool { return true }, @@ -14,5 +15,5 @@ func init() { cmd.database.CheckPing(cmd.config.FiredRole)), nil }, help: "Check how many times Carolyn has been fired.", - } + }) } diff --git a/discord/help.go b/discord/help.go index 3d80eb8..2587ef6 100644 --- a/discord/help.go +++ b/discord/help.go @@ -1,13 +1,16 @@ package discord import ( + "fmt" "strings" "github.com/bwmarrin/discordgo" ) func init() { - commands["help"] = command{ + commands = append(commands, &command{ + deleteInvocation: true, + name: "help", validate: func(cmd commandInit) bool { return true }, @@ -30,14 +33,15 @@ func init() { return "", nil }, help: "HELP! HEEEEEEEEEELP!", - } + }) } func singleHelp(cmd commandInit, arg string) *discordgo.MessageEmbed { embed := &discordgo.MessageEmbed{ Title: "Unkown Command", + Color: 0x007D96, } - c, ok := commands[arg] + c, ok := commandMap[arg] if !ok { return embed } @@ -46,7 +50,7 @@ func singleHelp(cmd commandInit, arg string) *discordgo.MessageEmbed { return embed } - embed.Title = arg + embed.Title = c.name embed.Description = c.help return embed } @@ -60,10 +64,17 @@ func allHelp(cmd commandInit) *discordgo.MessageEmbed { if staff { embed.Description = "Commands with an asterisk (*) are staff-only" } - for n, c := range commands { - cmdName := n + for _, c := range commands { + if c.echo { + continue + } + + cmdName := c.name + if len(c.aliases) > 0 { + cmdName += fmt.Sprintf(" (%s)", strings.Join(c.aliases, ", ")) + } if c.staffOnly { - cmdName += "*" + cmdName = fmt.Sprintf("*%s", cmdName) } if !c.staffOnly || staff { embed.Fields = append(embed.Fields, &discordgo.MessageEmbedField{ diff --git a/discord/history.go b/discord/history.go index 3b5c26f..baa609a 100644 --- a/discord/history.go +++ b/discord/history.go @@ -12,7 +12,9 @@ import ( ) func init() { - cmd := command{ + commands = append(commands, &command{ + name: "history", + aliases: []string{"names"}, validate: func(cmd commandInit) bool { return true }, @@ -79,8 +81,5 @@ func init() { return "", nil }, help: "Minecraft name history", - } - - commands["history"] = cmd - commands["names"] = cmd + }) } diff --git a/discord/inspire.go b/discord/inspire.go index 2e89db9..e4238ae 100644 --- a/discord/inspire.go +++ b/discord/inspire.go @@ -3,7 +3,8 @@ package discord import "go.etztech.xyz/inspiro" func init() { - commands["inspire"] = command{ + commands = append(commands, &command{ + name: "inspire", validate: func(cmd commandInit) bool { return true }, @@ -22,5 +23,5 @@ func init() { return img, nil }, help: "Get inspired!", - } + }) } diff --git a/discord/insult.go b/discord/insult.go index ad85472..09ddce1 100644 --- a/discord/insult.go +++ b/discord/insult.go @@ -6,7 +6,8 @@ import ( ) func init() { - commands["insult"] = command{ + commands = append(commands, &command{ + name: "insult", validate: func(cmd commandInit) bool { return true }, @@ -39,5 +40,5 @@ func init() { return "", nil }, help: "Insult someone!", - } + }) } diff --git a/discord/jupiter.go b/discord/jupiter.go index 46e7ebb..1fecc3e 100644 --- a/discord/jupiter.go +++ b/discord/jupiter.go @@ -3,7 +3,9 @@ package discord import "go.etztech.xyz/sedbot/imgur" func init() { - cmd := command{ + commands = append(commands, &command{ + name: "jupiter", + aliases: []string{"jup", "jupjup"}, validate: func(cmd commandInit) bool { return true }, @@ -15,9 +17,5 @@ func init() { return img.Link, nil }, help: "Get a Jupiter image", - } - - commands["jupiter"] = cmd - commands["jup"] = cmd - commands["jupjup"] = cmd + }) } diff --git a/discord/register.go b/discord/register.go index a2cc9b6..9901d3a 100644 --- a/discord/register.go +++ b/discord/register.go @@ -16,7 +16,8 @@ import ( const bannedPlayersFile = "banned-players.json" func init() { - commands["register"] = command{ + commands = append(commands, &command{ + name: "register", validate: func(cmd commandInit) bool { return len(cmd.message.Member.Roles) == 0 }, @@ -94,7 +95,7 @@ func init() { return "", nil }, help: "Register yourself with the Discord", - } + }) } type Ban struct { diff --git a/discord/status.go b/discord/status.go index 4b786c6..e2afe3a 100644 --- a/discord/status.go +++ b/discord/status.go @@ -9,7 +9,9 @@ import ( ) func init() { - cmd := command{ + commands = append(commands, &command{ + name: "status", + aliases: []string{"version", "online"}, validate: func(cmd commandInit) bool { return true }, @@ -22,7 +24,6 @@ func init() { } embed := &discordgo.MessageEmbed{ - Color: 0x007D96, Title: fmt.Sprintf("Server Status for `%s`", cmd.config.Server.Address), Description: q.MOTD, Fields: []*discordgo.MessageEmbedField{ @@ -46,9 +47,5 @@ func init() { return "", nil }, help: "Get the server status", - } - - commands["status"] = cmd - commands["version"] = cmd - commands["online"] = cmd + }) } diff --git a/discord/tweet.go b/discord/tweet.go index 32b9269..756fedd 100644 --- a/discord/tweet.go +++ b/discord/tweet.go @@ -6,8 +6,9 @@ import ( ) func init() { - commands["tweet"] = command{ + commands = append(commands, &command{ staffOnly: true, + name: "tweet", validate: func(cmd commandInit) bool { return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) }, @@ -30,5 +31,5 @@ func init() { return fmt.Sprintf("https://twitter.com/%d/status/%d", tweet.User.ID, tweet.ID), nil }, help: "Send a tweet from the BirbMC Twitter", - } + }) } diff --git a/discord/unban.go b/discord/unban.go index 324b90c..b699acd 100644 --- a/discord/unban.go +++ b/discord/unban.go @@ -10,8 +10,9 @@ import ( ) func init() { - commands["unban"] = command{ + commands = append(commands, &command{ staffOnly: true, + name: "unban", validate: func(cmd commandInit) bool { return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) }, @@ -36,5 +37,5 @@ func init() { cmd.database.AddUnban(record) }, help: "Unban a player", - } + }) } diff --git a/discord/unbans.go b/discord/unbans.go index 698ab60..d2d8742 100644 --- a/discord/unbans.go +++ b/discord/unbans.go @@ -5,8 +5,9 @@ import ( ) func init() { - commands["unbans"] = command{ + commands = append(commands, &command{ staffOnly: true, + name: "unbans", validate: func(cmd commandInit) bool { return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) }, @@ -30,6 +31,6 @@ func init() { sendEmbed(cmd.session, cmd.message.ChannelID, embed) return "", nil }, - help: "Unban a player", - } + help: "Check the unban scheduler", + }) } diff --git a/discord/welcome.go b/discord/welcome.go index e4380b2..785aa5c 100644 --- a/discord/welcome.go +++ b/discord/welcome.go @@ -7,15 +7,13 @@ import ( ) func init() { - commands["welcome"] = command{ + commands = append(commands, &command{ + deleteInvocation: true, + name: "welcome", validate: func(cmd commandInit) bool { return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) }, run: func(cmd commandInit) (string, error) { - if err := cmd.session.ChannelMessageDelete(cmd.message.ChannelID, cmd.message.ID); err != nil { - return "", err - } - orphans := make([]*discordgo.Member, 0) members, err := cmd.session.GuildMembers(cmd.message.GuildID, "", 1000) @@ -49,5 +47,5 @@ func init() { return "", nil }, help: "Get a list of people with no roles", - } + }) } diff --git a/discord/xkcd.go b/discord/xkcd.go index 9491239..b498a76 100644 --- a/discord/xkcd.go +++ b/discord/xkcd.go @@ -10,7 +10,8 @@ import ( ) func init() { - commands["xkcd"] = command{ + commands = append(commands, &command{ + name: "xkcd", validate: func(cmd commandInit) bool { return true }, @@ -40,5 +41,5 @@ func init() { return fmt.Sprintf("%d: %s\n%s\n%s", comic.Num, comic.SafeTitle, comic.Alt, comic.Img), nil }, help: "Get an xkcd comic", - } + }) }