mirror of
https://github.com/roleypoly/roleypoly.git
synced 2025-06-16 17:49:09 +00:00
feat: add discord-bot service
This commit is contained in:
parent
c40961b1b2
commit
5e3ceb4181
13 changed files with 184 additions and 66 deletions
|
@ -3,11 +3,15 @@ load("@io_bazel_rules_docker//go:image.bzl", "go_image")
|
|||
|
||||
go_library(
|
||||
name = "discord-bot_lib",
|
||||
srcs = ["discordbot.go"],
|
||||
srcs = [
|
||||
"discordbot.go",
|
||||
"listener.go",
|
||||
],
|
||||
importpath = "github.com/roleypoly/roleypoly/src/discord-bot",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//src/common/version",
|
||||
"//src/discord-bot/internal/strings",
|
||||
"@com_github_bwmarrin_discordgo//:discordgo",
|
||||
"@com_github_joho_godotenv//autoload",
|
||||
"@com_github_lampjaw_discordclient//:discordclient",
|
||||
|
@ -16,13 +20,13 @@ go_library(
|
|||
)
|
||||
|
||||
go_binary(
|
||||
name = "discord-bot_bin",
|
||||
name = "discord-bot",
|
||||
embed = [":discord-bot_lib"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
go_image(
|
||||
name = "discord-bot",
|
||||
name = "image",
|
||||
embed = [":discord-bot_lib"],
|
||||
visibility = ["//visibility:public"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
|
@ -13,15 +14,21 @@ import (
|
|||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
var (
|
||||
botToken = os.Getenv("DISCORD_BOT_TOKEN")
|
||||
botClientID = os.Getenv("DISCORD_CLIENT_ID")
|
||||
rootUsers = strings.Split(os.Getenv("ROOT_USERS"), ",")
|
||||
allowedBots = strings.Split(os.Getenv("ALLOWED_BOTS"), ",")
|
||||
appURL = os.Getenv("PUBLIC_URL")
|
||||
|
||||
selfMention = regexp.MustCompile("<@!?" + botClientID + ">")
|
||||
)
|
||||
|
||||
func main() {
|
||||
klog.Info(version.StartupInfo("discord-bot"))
|
||||
|
||||
botToken := os.Getenv("DISCORD_BOT_TOKEN")
|
||||
botClientID := os.Getenv("DISCORD_CLIENT_ID")
|
||||
rootUsers := strings.Split(os.Getenv("ROOT_USERS"), ",")
|
||||
|
||||
discordClient := discordclient.NewDiscordClient(botToken, rootUsers[0], botClientID)
|
||||
discordClient.GatewayIntents = discordgo.IntentsNone
|
||||
discordClient.GatewayIntents = discordgo.IntentsGuildMessages
|
||||
|
||||
messageChannel, err := discordClient.Listen(-1)
|
||||
if err != nil {
|
||||
|
@ -30,14 +37,21 @@ func main() {
|
|||
|
||||
defer awaitExit()
|
||||
|
||||
go processMessages(messageChannel)
|
||||
l := listener{
|
||||
client: discordClient,
|
||||
}
|
||||
|
||||
go l.processMessages(messageChannel)
|
||||
}
|
||||
|
||||
func processMessages(messageChannel <-chan discordclient.Message) {
|
||||
for {
|
||||
message := <-messageChannel
|
||||
klog.Infoln("message: ", message.Message())
|
||||
func isBotAllowlisted(userID string) bool {
|
||||
for _, id := range allowedBots {
|
||||
if id == userID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func awaitExit() {
|
||||
|
|
11
src/discord-bot/internal/strings/BUILD.bazel
Normal file
11
src/discord-bot/internal/strings/BUILD.bazel
Normal file
|
@ -0,0 +1,11 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "strings",
|
||||
srcs = [
|
||||
"renderer.go",
|
||||
"strings.go",
|
||||
],
|
||||
importpath = "github.com/roleypoly/roleypoly/src/discord-bot/internal/strings",
|
||||
visibility = ["//src/discord-bot:__subpackages__"],
|
||||
)
|
13
src/discord-bot/internal/strings/renderer.go
Normal file
13
src/discord-bot/internal/strings/renderer.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package strings
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// Render a template to string
|
||||
func Render(tmpl *template.Template, data interface{}) string {
|
||||
buffer := &bytes.Buffer{}
|
||||
tmpl.Execute(buffer, data)
|
||||
return buffer.String()
|
||||
}
|
44
src/discord-bot/internal/strings/strings.go
Normal file
44
src/discord-bot/internal/strings/strings.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package strings
|
||||
|
||||
import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
// MentionResponse is a template that requires strings AppURL and GuildID.
|
||||
MentionResponse = template.Must(
|
||||
template.New("MentionResponse").Parse(
|
||||
`:beginner: Assign your roles here! {{ .AppURL }}/s/{{ .GuildID }}`,
|
||||
),
|
||||
)
|
||||
|
||||
RootStats = template.Must(
|
||||
template.New("RootStats").Parse(`🐈
|
||||
**People Stats**
|
||||
<:blank:676216695375003650>🙎♀️ **Total Users:** {{ .Users }}
|
||||
<:blank:676216695375003650>👨👩👦👦 **Total Guilds:** {{ .Guilds }}
|
||||
<:blank:676216695375003650>🦺 **Total Roles:** {{ .Roles }}
|
||||
|
||||
**Bot Stats**
|
||||
<:blank:676216695375003650>🔩 **Total Shards:** {{ .Shards }}
|
||||
<:blank:676216695375003650>⚙️ **Revision:** {{ .GitCommit }} ({{ .GitBranch }})
|
||||
<:blank:676216695375003650>⏰ **Built at** {{ .BuildDate }}
|
||||
`,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
type MentionResponseData struct {
|
||||
AppURL string
|
||||
GuildID string
|
||||
}
|
||||
|
||||
type RootStatsData struct {
|
||||
Users int
|
||||
Guilds int
|
||||
Roles int
|
||||
Shards int
|
||||
GitCommit string
|
||||
GitBranch string
|
||||
BuildDate string
|
||||
}
|
53
src/discord-bot/listener.go
Normal file
53
src/discord-bot/listener.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/lampjaw/discordclient"
|
||||
"k8s.io/klog"
|
||||
|
||||
"github.com/roleypoly/roleypoly/src/discord-bot/internal/strings"
|
||||
)
|
||||
|
||||
type listener struct {
|
||||
client *discordclient.DiscordClient
|
||||
}
|
||||
|
||||
func (l *listener) processMessages(messageChannel <-chan discordclient.Message) {
|
||||
for {
|
||||
go l.handle(<-messageChannel)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *listener) handle(message discordclient.Message) {
|
||||
// Only if it's a message create
|
||||
if message.Type() != discordclient.MessageTypeCreate {
|
||||
return
|
||||
}
|
||||
|
||||
// Only if it's an allowed bot
|
||||
if message.IsBot() && !isBotAllowlisted(message.UserID()) {
|
||||
return
|
||||
}
|
||||
|
||||
// Only if it has the right mention
|
||||
if !selfMention.MatchString(message.RawMessage()) {
|
||||
return
|
||||
}
|
||||
|
||||
l.defaultResponse(message)
|
||||
}
|
||||
|
||||
func (l *listener) defaultResponse(message discordclient.Message) {
|
||||
channel := message.Channel()
|
||||
guild, err := message.ResolveGuildID()
|
||||
if err != nil {
|
||||
klog.Warning("failed to fetch guild, ", err)
|
||||
}
|
||||
|
||||
l.client.SendMessage(
|
||||
channel,
|
||||
strings.Render(
|
||||
strings.MentionResponse,
|
||||
strings.MentionResponseData{GuildID: guild, AppURL: appURL},
|
||||
),
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue