Remove Common, Rework External Chat Support, & Bugfixes (!5)

Co-authored-by: Layla <layla@layla.gg>
Reviewed-on: https://gitea.sumulayla.synology.me/layla/birdbot/pulls/5
This commit is contained in:
Layla 2023-06-19 03:08:24 -04:00
parent 5e4698495c
commit 6cbe4df36c
28 changed files with 81 additions and 146 deletions

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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),
}
}

View File

@ -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)
}

View File

@ -1,7 +1,7 @@
package app
import (
"github.com/yeslayla/birdbot/common"
"github.com/yeslayla/birdbot-common/common"
"github.com/yeslayla/birdbot/core"
)

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -1,11 +0,0 @@
package common
type ExternalChatManager interface {
SendMessage(user string, message string)
}
type ExternalChatModule interface {
Initialize(ExternalChatManager)
RecieveMessage(user User, message string)
}

View File

@ -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
}

View File

@ -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 "<NULL>"
}
return fmt.Sprintf("<@%s>", user.ID)
}

View File

@ -6,7 +6,7 @@ import (
"strings"
"time"
"github.com/yeslayla/birdbot/common"
"github.com/yeslayla/birdbot-common/common"
)
type Channel struct {

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -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"
)

View File

@ -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

1
go.mod
View File

@ -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

6
go.sum
View File

@ -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=

View File

@ -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))

View File

@ -3,7 +3,7 @@ package modules
import (
"fmt"
"github.com/yeslayla/birdbot/common"
"github.com/yeslayla/birdbot-common/common"
"github.com/yeslayla/birdbot/mastodon"
)

View File

@ -8,7 +8,7 @@ import (
"log"
"net/http"
"github.com/yeslayla/birdbot/common"
"github.com/yeslayla/birdbot-common/common"
)
type feedbackWebhookModule struct {

View File

@ -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"
)

View File

@ -4,7 +4,7 @@ import (
"log"
"strings"
"github.com/yeslayla/birdbot/common"
"github.com/yeslayla/birdbot-common/common"
"github.com/yeslayla/birdbot/discord"
)

View File

@ -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"

View File

@ -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
}