From 6cbe4df36c66ca4fd548136e57cbfe954231ede8 Mon Sep 17 00:00:00 2001 From: Layla Date: Mon, 19 Jun 2023 03:08:24 -0400 Subject: [PATCH] Remove Common, Rework External Chat Support, & Bugfixes (!5) Co-authored-by: Layla Reviewed-on: https://gitea.sumulayla.synology.me/layla/birdbot/pulls/5 --- .github/workflows/publish_release.yaml | 2 +- .github/workflows/validate.yaml | 2 +- Makefile | 2 +- app/bot.go | 51 +++++++++++++++++++------- app/component_loader.go | 24 ++++++------ app/external_chat_manager.go | 2 +- app/plugins.go | 5 ++- common/chat_commands.go | 24 ------------ common/event.go | 19 ---------- common/external_chat.go | 11 ------ common/module.go | 29 --------------- common/user.go | 19 ---------- core/channel.go | 2 +- core/configuration.go | 2 + discord/command.go | 2 +- discord/component_button.go | 2 +- discord/discord.go | 4 +- discord/event.go | 2 +- discord/user.go | 2 +- go.mod | 1 + go.sum | 6 +++ main.go | 2 +- modules/announce_events.go | 2 +- modules/feedback_webhook.go | 2 +- modules/manage_event_channels.go | 2 +- modules/recurring_events.go | 2 +- modules/role_selection.go | 2 +- persistence/sqlite3.go | 2 +- 28 files changed, 81 insertions(+), 146 deletions(-) delete mode 100644 common/chat_commands.go delete mode 100644 common/event.go delete mode 100644 common/external_chat.go delete mode 100644 common/module.go delete mode 100644 common/user.go diff --git a/.github/workflows/publish_release.yaml b/.github/workflows/publish_release.yaml index 117060a..ee8c886 100644 --- a/.github/workflows/publish_release.yaml +++ b/.github/workflows/publish_release.yaml @@ -20,7 +20,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '>=1.19.0' + go-version: '1.20' - name: Version run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - name: Test diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index aebdfae..f92fee2 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -14,7 +14,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '>=1.19.0' + go-version: '1.20' - name: Test run: | make test diff --git a/Makefile b/Makefile index e10ec75..b6c2539 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ go-full-build: go-clean go-get go-build go-build: @echo " > Building binary..." @mkdir -p $(GOBIN) - @CGO_ENABLED=1 go build -ldflags "-X github.com/yeslayla/birdbot/app.Version=$(VERSION) -X github.com/yeslayla/birdbot/app.Build=$(BUILD_NUMBER)" -o $(GOBIN)/$(PROJECT_BIN) $(GOFILES) + @GOOS=linux CGO_ENABLED=1 go build -ldflags "-X github.com/yeslayla/birdbot/app.Version=$(VERSION) -X github.com/yeslayla/birdbot/app.Build=$(BUILD_NUMBER)" -o $(GOBIN)/$(PROJECT_BIN) $(GOFILES) @chmod 755 $(GOBIN)/$(PROJECT_BIN) go-generate: diff --git a/app/bot.go b/app/bot.go index 069aeb5..b8acccb 100644 --- a/app/bot.go +++ b/app/bot.go @@ -4,7 +4,7 @@ import ( "fmt" "log" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" "github.com/yeslayla/birdbot/core" "github.com/yeslayla/birdbot/discord" "github.com/yeslayla/birdbot/mastodon" @@ -34,6 +34,8 @@ type Bot struct { onEventUpdatedHandlers [](func(common.Event) error) onEventCompletedHandlers [](func(common.Event) error) + chatLinks map[string][]string + chatHandlers map[string]common.ExternalChatModule channelChats map[string][]common.ExternalChatModule } @@ -45,6 +47,7 @@ func (app *Bot) Initialize(cfg *core.Config) error { app.eventCategoryID = cfg.Discord.EventCategory app.archiveCategoryID = cfg.Discord.ArchiveCategory app.notificationChannelID = cfg.Discord.NotificationChannel + app.chatLinks = cfg.Discord.ChatLinks if app.guildID == "" { return fmt.Errorf("discord Guild ID is not set") @@ -62,29 +65,21 @@ func (app *Bot) Initialize(cfg *core.Config) error { app.Session = discord.New(cfg.Discord.ApplicationID, app.guildID, cfg.Discord.Token, app.Database) - // Intialize submodules - for channelID, chats := range app.channelChats { - channel := app.Session.NewChannelFromID(channelID) - for _, chat := range chats { - app.InitalizeExternalChat(channel, chat) - } - } - // Register Event Handlers app.Session.OnReady(app.onReady) app.Session.OnEventCreate(app.onEventCreate) app.Session.OnEventDelete(app.onEventDelete) app.Session.OnEventUpdate(app.onEventUpdate) - if len(app.channelChats) > 0 { - app.Session.OnMessageRecieved(app.onMessageRecieved) - } - return nil } // Run opens the session with Discord until exit func (app *Bot) Run() error { + + // Intialize submodules + app.prepareChat() + return app.Session.Run() } @@ -186,10 +181,40 @@ func (app *Bot) onMessageRecieved(d *discord.Discord, channelID string, user com } } +func (app *Bot) prepareChat() { + + // Associate channels with chat modules + for channelID, chatHandelerIDs := range app.chatLinks { + if _, ok := app.channelChats[channelID]; !ok { + app.channelChats[channelID] = []common.ExternalChatModule{} + } + + for _, chatHandlerID := range chatHandelerIDs { + if handler, ok := app.chatHandlers[chatHandlerID]; ok { + app.channelChats[channelID] = append(app.channelChats[channelID], handler) + } + } + } + + // Initialize chat modules + for channelID, chats := range app.channelChats { + channel := app.Session.NewChannelFromID(channelID) + for _, chat := range chats { + app.InitalizeExternalChat(channel, chat) + } + } + + // Register listener if needed + if len(app.channelChats) > 0 { + app.Session.OnMessageRecieved(app.onMessageRecieved) + } +} + // NewBot creates a new bot instance func NewBot(db persistence.Database) *Bot { return &Bot{ Database: db, channelChats: make(map[string][]common.ExternalChatModule), + chatHandlers: make(map[string]common.ExternalChatModule), } } diff --git a/app/component_loader.go b/app/component_loader.go index c458026..d1af008 100644 --- a/app/component_loader.go +++ b/app/component_loader.go @@ -2,17 +2,20 @@ package app import ( "log" + "path/filepath" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" ) type ComponentLoader struct { - bot *Bot + bot *Bot + configDir string } -func NewComponentLoader(bot *Bot) *ComponentLoader { +func NewComponentLoader(bot *Bot, configDir string) *ComponentLoader { return &ComponentLoader{ - bot: bot, + bot: bot, + configDir: configDir, } } @@ -49,13 +52,8 @@ func (loader *ComponentLoader) OnEventComplete(handler func(common.Event) error) return nil } -func (loader *ComponentLoader) RegisterExternalChat(channelID string, chat common.ExternalChatModule) error { - if _, ok := loader.bot.channelChats[channelID]; !ok { - loader.bot.channelChats[channelID] = []common.ExternalChatModule{} - } - - loader.bot.channelChats[channelID] = append(loader.bot.channelChats[channelID], chat) - +func (loader *ComponentLoader) RegisterExternalChat(ID string, chat common.ExternalChatModule) error { + loader.bot.chatHandlers[ID] = chat return nil } @@ -71,3 +69,7 @@ func (loader *ComponentLoader) Notify(message string) error { func (loader *ComponentLoader) RegisterCommand(name string, config common.ChatCommandConfiguration, handler func(common.User, map[string]any) string) { loader.bot.Session.RegisterCommand(name, config, handler) } + +func (loader *ComponentLoader) GetConfigPath(fileName string) string { + return filepath.Join(loader.configDir, "birdbot", fileName) +} diff --git a/app/external_chat_manager.go b/app/external_chat_manager.go index e2f79fd..1c381a0 100644 --- a/app/external_chat_manager.go +++ b/app/external_chat_manager.go @@ -1,7 +1,7 @@ package app import ( - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" "github.com/yeslayla/birdbot/core" ) diff --git a/app/plugins.go b/app/plugins.go index e728962..7f84fd1 100644 --- a/app/plugins.go +++ b/app/plugins.go @@ -3,9 +3,10 @@ package app import ( "log" "os" + "path/filepath" "plugin" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" ) // LoadPlugin loads a plugin and returns its component if successful @@ -49,7 +50,7 @@ func LoadPlugins(directory string) []common.Module { continue } - if comp := LoadPlugin(path.Name()); comp != nil { + if comp := LoadPlugin(filepath.Join(directory, path.Name())); comp != nil { components = append(components, comp) } } diff --git a/common/chat_commands.go b/common/chat_commands.go deleted file mode 100644 index 1911396..0000000 --- a/common/chat_commands.go +++ /dev/null @@ -1,24 +0,0 @@ -package common - -import "github.com/bwmarrin/discordgo" - -type CommandOptionType uint64 - -const ( - CommandTypeString CommandOptionType = CommandOptionType(discordgo.ApplicationCommandOptionString) - CommandTypeInt CommandOptionType = CommandOptionType(discordgo.ApplicationCommandOptionInteger) - CommandTypeBool CommandOptionType = CommandOptionType(discordgo.ApplicationCommandOptionBoolean) - CommandTypeFloat CommandOptionType = CommandOptionType(discordgo.ApplicationCommandOptionNumber) -) - -type ChatCommandConfiguration struct { - Description string - EphemeralResponse bool - Options map[string]ChatCommandOption -} - -type ChatCommandOption struct { - Description string - Type CommandOptionType - Required bool -} diff --git a/common/event.go b/common/event.go deleted file mode 100644 index 6424ab4..0000000 --- a/common/event.go +++ /dev/null @@ -1,19 +0,0 @@ -package common - -import ( - "time" -) - -// Event represents a calendar event -type Event struct { - Name string - ID string - Location string - Completed bool - DateTime time.Time - CompleteDateTime time.Time - Description string - ImageURL string - - Organizer User -} diff --git a/common/external_chat.go b/common/external_chat.go deleted file mode 100644 index e191107..0000000 --- a/common/external_chat.go +++ /dev/null @@ -1,11 +0,0 @@ -package common - -type ExternalChatManager interface { - SendMessage(user string, message string) -} - -type ExternalChatModule interface { - Initialize(ExternalChatManager) - - RecieveMessage(user User, message string) -} diff --git a/common/module.go b/common/module.go deleted file mode 100644 index 2672a4c..0000000 --- a/common/module.go +++ /dev/null @@ -1,29 +0,0 @@ -package common - -type Module interface { - Initialize(birdbot ModuleManager) error -} - -// ModuleManager is the primary way for a module to interact with BirdBot -// by listening to events and committing actions -type ModuleManager interface { - OnReady(func() error) error - - OnNotify(func(string) error) error - - // Event events - OnEventCreate(func(Event) error) error - OnEventDelete(func(Event) error) error - OnEventUpdate(func(Event) error) error - OnEventComplete(func(Event) error) error - - // Actions - CreateEvent(event Event) error - Notify(message string) error - - // Commands - RegisterCommand(string, ChatCommandConfiguration, func(User, map[string]any) string) - - // Submodules - RegisterExternalChat(channelID string, chat ExternalChatModule) error -} diff --git a/common/user.go b/common/user.go deleted file mode 100644 index 498dfd7..0000000 --- a/common/user.go +++ /dev/null @@ -1,19 +0,0 @@ -package common - -import "fmt" - -// User represents a user within BirdBot -type User struct { - ID string - AvatarURL string - DisplayName string -} - -// DiscordMention generated a Discord mention string for the user -func (user *User) DiscordMention() string { - if user == nil { - return "" - } - - return fmt.Sprintf("<@%s>", user.ID) -} diff --git a/core/channel.go b/core/channel.go index ec4dc61..5c7e163 100644 --- a/core/channel.go +++ b/core/channel.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" ) type Channel struct { diff --git a/core/configuration.go b/core/configuration.go index 50e32bc..b368d45 100644 --- a/core/configuration.go +++ b/core/configuration.go @@ -21,6 +21,8 @@ type DiscordConfig struct { NotificationChannel string `yaml:"notification_channel" env:"DISCORD_NOTIFICATION_CHANNEL"` RoleSelections []RoleSelectionConfig `yaml:"role_selection"` + + ChatLinks map[string][]string `yaml:"chat_links"` } type Feedback struct { diff --git a/discord/command.go b/discord/command.go index e415264..9fc7605 100644 --- a/discord/command.go +++ b/discord/command.go @@ -4,7 +4,7 @@ import ( "log" "github.com/bwmarrin/discordgo" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" ) // RegisterCommand creates an new command that can be used to interact with bird bot diff --git a/discord/component_button.go b/discord/component_button.go index ef3db59..3e18948 100644 --- a/discord/component_button.go +++ b/discord/component_button.go @@ -2,7 +2,7 @@ package discord import ( "github.com/bwmarrin/discordgo" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" ) type Button struct { diff --git a/discord/discord.go b/discord/discord.go index 3b292a3..f80f9a9 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -8,7 +8,7 @@ import ( "github.com/bwmarrin/discordgo" "github.com/stretchr/testify/mock" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" "github.com/yeslayla/birdbot/persistence" ) @@ -125,7 +125,7 @@ func (discord *Discord) OnEventUpdate(handler func(*Discord, common.Event)) { // OnMessageRecieved registers a handler when a message is recieved func (discord *Discord) OnMessageRecieved(handler func(*Discord, string, common.User, string)) { discord.session.AddHandler(func(s *discordgo.Session, r *discordgo.MessageCreate) { - if r.GuildID != discord.guildID { + if r.GuildID != discord.guildID || r.Author.Bot { return } diff --git a/discord/event.go b/discord/event.go index 45d6169..059e150 100644 --- a/discord/event.go +++ b/discord/event.go @@ -4,7 +4,7 @@ import ( "time" "github.com/bwmarrin/discordgo" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" "github.com/yeslayla/birdbot/core" ) diff --git a/discord/user.go b/discord/user.go index 72cdb63..8520971 100644 --- a/discord/user.go +++ b/discord/user.go @@ -4,7 +4,7 @@ import ( "log" "github.com/bwmarrin/discordgo" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" ) // NewUser creates a new user object from a discordgo.User object diff --git a/go.mod b/go.mod index e7558ec..280e6b2 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect + github.com/yeslayla/birdbot-common v0.1.0 // indirect golang.org/x/crypto v0.10.0 // indirect golang.org/x/sys v0.9.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index ef9f4fa..48209bd 100644 --- a/go.sum +++ b/go.sum @@ -394,6 +394,12 @@ github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFy github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yeslayla/birdbot-common v0.0.0-20230619031144-7238d1b18f76 h1:lfZb/m0Ckc6FiAiCSAlJ/6coyx3CkEnnHZXhPLWqQa4= +github.com/yeslayla/birdbot-common v0.0.0-20230619031144-7238d1b18f76/go.mod h1:zyvQi9lqnd8tKudJW75FRyBONnAa2JwYk43vLECJqO0= +github.com/yeslayla/birdbot-common v0.0.0-20230619053929-5d690affa770 h1:tKCGApCuP7j8VrkZkq8XnN2nFFN/o/IuiRojTCaqpRo= +github.com/yeslayla/birdbot-common v0.0.0-20230619053929-5d690affa770/go.mod h1:zyvQi9lqnd8tKudJW75FRyBONnAa2JwYk43vLECJqO0= +github.com/yeslayla/birdbot-common v0.1.0 h1:Ozj9E8CP50iBqMviEpHxpKwdyCr7jkBMQonncHRvnqM= +github.com/yeslayla/birdbot-common v0.1.0/go.mod h1:zyvQi9lqnd8tKudJW75FRyBONnAa2JwYk43vLECJqO0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/main.go b/main.go index 1794121..d9d5270 100644 --- a/main.go +++ b/main.go @@ -65,7 +65,7 @@ func main() { log.Fatal("Failed to initialize: ", err) } - loader := app.NewComponentLoader(bot) + loader := app.NewComponentLoader(bot, configDir) if cfg.Features.AnnounceEvents.IsEnabledByDefault() { loader.LoadComponent(modules.NewAnnounceEventsComponent(bot.Mastodon, cfg.Discord.NotificationChannel)) diff --git a/modules/announce_events.go b/modules/announce_events.go index 83c2397..9263010 100644 --- a/modules/announce_events.go +++ b/modules/announce_events.go @@ -3,7 +3,7 @@ package modules import ( "fmt" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" "github.com/yeslayla/birdbot/mastodon" ) diff --git a/modules/feedback_webhook.go b/modules/feedback_webhook.go index 31198e8..9bcaf84 100644 --- a/modules/feedback_webhook.go +++ b/modules/feedback_webhook.go @@ -8,7 +8,7 @@ import ( "log" "net/http" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" ) type feedbackWebhookModule struct { diff --git a/modules/manage_event_channels.go b/modules/manage_event_channels.go index 9884895..16fecf2 100644 --- a/modules/manage_event_channels.go +++ b/modules/manage_event_channels.go @@ -3,7 +3,7 @@ package modules import ( "log" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" "github.com/yeslayla/birdbot/core" "github.com/yeslayla/birdbot/discord" ) diff --git a/modules/recurring_events.go b/modules/recurring_events.go index e3cce36..9bad07f 100644 --- a/modules/recurring_events.go +++ b/modules/recurring_events.go @@ -4,7 +4,7 @@ import ( "log" "strings" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" "github.com/yeslayla/birdbot/discord" ) diff --git a/modules/role_selection.go b/modules/role_selection.go index 9d04719..f534382 100644 --- a/modules/role_selection.go +++ b/modules/role_selection.go @@ -4,7 +4,7 @@ import ( "fmt" "log" - "github.com/yeslayla/birdbot/common" + "github.com/yeslayla/birdbot-common/common" "github.com/yeslayla/birdbot/core" "github.com/yeslayla/birdbot/discord" "github.com/yeslayla/birdbot/persistence" diff --git a/persistence/sqlite3.go b/persistence/sqlite3.go index de70444..7f11423 100644 --- a/persistence/sqlite3.go +++ b/persistence/sqlite3.go @@ -140,7 +140,7 @@ func (db *Sqlite3Database) GetDiscordWebhook(id string) (*DBDiscordWebhook, erro // SetDiscordWebhook stores a discord webhook based on a given local id func (db *Sqlite3Database) SetDiscordWebhook(id string, data *DBDiscordWebhook) error { - statement, err := db.db.Prepare("INSERT OR IGNORE INTO discord_webhooks (id, webhook_id, webhook_token) VALUES (?, ?)") + statement, err := db.db.Prepare("INSERT OR IGNORE INTO discord_webhooks (id, webhook_id, webhook_token) VALUES (?, ?, ?)") if err != nil { return err }