From 696ab7201cd80334391492d43b3ff55addc6232d Mon Sep 17 00:00:00 2001 From: Layla Manley Date: Fri, 28 Oct 2022 23:08:17 -0400 Subject: [PATCH] Major Refactor (#2) * Major reworks * More refactoring * Refactor feature complete! * Comments * Add versioning --- .github/workflows/publish_release.yaml | 2 +- .github/workflows/validate.yaml | 2 +- Makefile | 4 +- app/bot.go | 150 ++++++++----------------- app/channel.go | 68 ----------- core/channel.go | 7 ++ {app => core}/configuration.go | 2 +- {app => core}/event.go | 25 +++-- {app => core}/event_test.go | 6 +- core/organizer.go | 16 +++ core/pointers.go | 6 + discord/channel.go | 146 ++++++++++++++++++++++++ discord/discord.go | 97 ++++++++++++++++ discord/event.go | 28 +++++ discord/user.go | 20 ++++ go.mod | 1 + go.sum | 1 + main.go | 8 ++ 18 files changed, 403 insertions(+), 186 deletions(-) delete mode 100644 app/channel.go create mode 100644 core/channel.go rename {app => core}/configuration.go (97%) rename {app => core}/event.go (77%) rename {app => core}/event_test.go (76%) create mode 100644 core/organizer.go create mode 100644 core/pointers.go create mode 100644 discord/channel.go create mode 100644 discord/discord.go create mode 100644 discord/event.go create mode 100644 discord/user.go diff --git a/.github/workflows/publish_release.yaml b/.github/workflows/publish_release.yaml index ef29e3c..112556b 100644 --- a/.github/workflows/publish_release.yaml +++ b/.github/workflows/publish_release.yaml @@ -28,7 +28,7 @@ jobs: make test - name: Build run: | - make build + make build VERSION="${{ env.RELEASE_VERSION }}" - name: Login to Docker Hub uses: docker/login-action@v2 with: diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index 675f8cf..aebdfae 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -20,4 +20,4 @@ jobs: make test - name: Build run: | - make build \ No newline at end of file + make build VERSION="test" \ No newline at end of file diff --git a/Makefile b/Makefile index 49747d8..37550b9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ PROJECTNAME="Bird Bot" PROJECT_BIN="birdbot" +VERSION="DEV" +BUILD_NUMBER:=$(shell date "+%s%N" | cut -b1-13) # Go related variables. GOBASE=$(shell pwd) @@ -14,7 +16,7 @@ go-full-build: go-clean go-get go-build go-build: @echo " > Building binary..." @mkdir -p $(GOBIN) - @GOOS=linux CGO_ENABLED=0 go build -o $(GOBIN)/$(PROJECT_BIN) $(GOFILES) + @GOOS=linux CGO_ENABLED=0 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 d8e6023..9572947 100644 --- a/app/bot.go +++ b/app/bot.go @@ -6,27 +6,28 @@ import ( "log" "os" - "github.com/bwmarrin/discordgo" "github.com/ilyakaznacheev/cleanenv" + "github.com/yeslayla/birdbot/core" + "github.com/yeslayla/birdbot/discord" ) +var Version string +var Build string + type Bot struct { - discord *discordgo.Session + session *discord.Discord // Discord Objects guildID string eventCategoryID string archiveCategoryID string notificationChannelID string - - // Signal for shutdown - stop chan os.Signal } // Initalize creates the discord session and registers handlers func (app *Bot) Initialize(config_path string) error { log.Printf("Using config: %s", config_path) - cfg := &Config{} + cfg := &core.Config{} _, err := os.Stat(config_path) if errors.Is(err, os.ErrNotExist) { @@ -51,171 +52,114 @@ func (app *Bot) Initialize(config_path string) error { return fmt.Errorf("discord Guild ID is not set") } - // Create Discord Session - app.discord, err = discordgo.New(fmt.Sprint("Bot ", cfg.Discord.Token)) - if err != nil { - return fmt.Errorf("failed to create Discord session: %v", err) - } + app.session = discord.New(app.guildID, cfg.Discord.Token) // Register Event Handlers - app.discord.AddHandler(app.onReady) - app.discord.AddHandler(app.onEventCreate) - app.discord.AddHandler(app.onEventDelete) - app.discord.AddHandler(app.onEventUpdate) + app.session.OnReady(app.onReady) + app.session.OnEventCreate(app.onEventCreate) + app.session.OnEventDelete(app.onEventDelete) + app.session.OnEventUpdate(app.onEventUpdate) return nil } // Run opens the session with Discord until exit func (app *Bot) Run() error { - - if err := app.discord.Open(); err != nil { - return fmt.Errorf("failed to open Discord session: %v", err) - } - defer app.discord.Close() - - // Keep alive - app.stop = make(chan os.Signal, 1) - <-app.stop - return nil + return app.session.Run() } // Stop triggers a graceful shutdown of the app func (app *Bot) Stop() { log.Print("Shuting down...") - app.stop <- os.Kill + app.session.Stop() } // Notify sends a message to the notification channe; func (app *Bot) Notify(message string) { if app.notificationChannelID == "" { + log.Println(message) return } - _, err := app.discord.ChannelMessageSend(app.notificationChannelID, message) + log.Print("Notification: ", message) - log.Println("Notification: ", message) + channel := app.session.NewChannelFromID(app.notificationChannelID) + if channel == nil { + log.Printf("Failed notification: channel was not found with ID '%v'", app.notificationChannelID) + } + + err := app.session.SendMessage(channel, message) if err != nil { - log.Println("Failed notification: ", err) + log.Print("Failed notification: ", err) } } -func (app *Bot) onReady(s *discordgo.Session, r *discordgo.Ready) { - app.Notify("BirdBot is ready!") - log.Print("BirdBot is ready!") +func (app *Bot) onReady(d *discord.Discord) { + app.Notify(fmt.Sprintf("BirdBot %s is ready!", Version)) } -func (app *Bot) onEventCreate(s *discordgo.Session, r *discordgo.GuildScheduledEventCreate) { - if r.GuildID != app.guildID { - return - } +func (app *Bot) onEventCreate(d *discord.Discord, event *core.Event) { - event := &Event{} - event.Name = r.Name - event.OrganizerID = r.CreatorID - event.DateTime = r.ScheduledStartTime - if r.EntityType != discordgo.GuildScheduledEventEntityTypeExternal { - event.Location = REMOTE_LOCATION - } else { - event.Location = r.EntityMetadata.Location - } log.Print("Event Created: '", event.Name, "':'", event.Location, "'") - channel, err := CreateChannelIfNotExists(s, app.guildID, event.GetChannelName()) + channel, err := app.session.NewChannelFromName(event.Channel().Name) if err != nil { log.Print("Failed to create channel for event: ", err) } if app.eventCategoryID != "" { - if _, err = s.ChannelEdit(channel.ID, &discordgo.ChannelEdit{ - ParentID: app.eventCategoryID, - }); err != nil { + err = app.session.MoveChannelToCategory(channel, app.eventCategoryID) + if err != nil { log.Printf("Failed to move channel to events category '%s': %v", channel.Name, err) } } - eventURL := fmt.Sprintf("https://discordapp.com/events/%s/%s", app.guildID, r.ID) - app.Notify(fmt.Sprintf("<@%s> is organizing an event '%s': %s", event.OrganizerID, event.Name, eventURL)) + eventURL := fmt.Sprintf("https://discordapp.com/events/%s/%s", app.guildID, event.ID) + app.Notify(fmt.Sprintf("%s is organizing an event '%s': %s", event.Organizer.Mention(), event.Name, eventURL)) } -func (app *Bot) onEventDelete(s *discordgo.Session, r *discordgo.GuildScheduledEventDelete) { - if r.GuildID != app.guildID { - return - } +func (app *Bot) onEventDelete(d *discord.Discord, event *core.Event) { - // Create Event Object - event := &Event{} - event.Name = r.Name - event.OrganizerID = r.CreatorID - event.DateTime = r.ScheduledStartTime - if r.EntityType != discordgo.GuildScheduledEventEntityTypeExternal { - event.Location = REMOTE_LOCATION - } else { - event.Location = r.EntityMetadata.Location - } - - _, err := DeleteChannel(app.discord, app.guildID, event.GetChannelName()) + _, err := app.session.DeleteChannel(event.Channel()) if err != nil { log.Print("Failed to create channel for event: ", err) } - app.Notify(fmt.Sprintf("<@%s> cancelled '%s' on %s, %d!", event.OrganizerID, event.Name, event.DateTime.Month().String(), event.DateTime.Day())) + app.Notify(fmt.Sprintf("%s cancelled '%s' on %s, %d!", event.Organizer.Mention(), event.Name, event.DateTime.Month().String(), event.DateTime.Day())) } -func (app *Bot) onEventUpdate(s *discordgo.Session, r *discordgo.GuildScheduledEventUpdate) { - if r.GuildID != app.guildID { - return - } - - // Create Event Object - event := &Event{} - event.Name = r.Name - event.OrganizerID = r.CreatorID - event.DateTime = r.ScheduledStartTime - if r.EntityType != discordgo.GuildScheduledEventEntityTypeExternal { - event.Location = REMOTE_LOCATION - } else { - event.Location = r.EntityMetadata.Location - } - +func (app *Bot) onEventUpdate(d *discord.Discord, event *core.Event) { // Pass event onwards - switch r.Status { - case discordgo.GuildScheduledEventStatusCompleted: - app.onEventComplete(s, event) + if event.Completed { + app.onEventComplete(d, event) } } -func (app *Bot) onEventComplete(s *discordgo.Session, event *Event) { +func (app *Bot) onEventComplete(d *discord.Discord, event *core.Event) { - channel_name := event.GetChannelName() + channel := event.Channel() if app.archiveCategoryID != "" { - // Get Channel ID - id, err := GetChannelID(s, app.guildID, channel_name) - if err != nil { - log.Printf("Failed to archive channel: %v", err) - return + if err := app.session.MoveChannelToCategory(channel, app.archiveCategoryID); err != nil { + log.Print("Failed to move channel to archive category: ", err) } - // Move to archive category - if _, err := s.ChannelEdit(id, &discordgo.ChannelEdit{ - ParentID: app.archiveCategoryID, - }); err != nil { - log.Printf("Failed to move channel to archive category: %v", err) - return + if err := app.session.ArchiveChannel(channel); err != nil { + log.Print("Failed to archive channel: ", err) } - log.Printf("Archived channel: '%s'", channel_name) + log.Printf("Archived channel: '%s'", channel.Name) + } else { // Delete Channel - _, err := DeleteChannel(s, app.guildID, channel_name) + _, err := app.session.DeleteChannel(channel) if err != nil { log.Print("Failed to delete channel: ", err) } - log.Printf("Deleted channel: '%s'", channel_name) + log.Printf("Deleted channel: '%s'", channel.Name) } } diff --git a/app/channel.go b/app/channel.go deleted file mode 100644 index 328f074..0000000 --- a/app/channel.go +++ /dev/null @@ -1,68 +0,0 @@ -package app - -import ( - "fmt" - "log" - - "github.com/bwmarrin/discordgo" -) - -func CreateChannelIfNotExists(discord *discordgo.Session, guildID string, channel_name string) (*discordgo.Channel, error) { - - // Grab channels to query - channels, err := discord.GuildChannels(guildID) - if err != nil { - return nil, fmt.Errorf("failed to list channels when creating new channel: '%s': %v", channel_name, err) - } - for _, channel := range channels { - - // Found channel! - if channel.Name == channel_name { - log.Printf("Tried to create channel, but it already exists '%s'", channel_name) - return channel, nil - } - } - - // Since a channel was not found, create one - channel, err := discord.GuildChannelCreate(guildID, channel_name, discordgo.ChannelTypeGuildText) - if err != nil { - return nil, fmt.Errorf("failed to created channel '%s': %v", channel_name, err) - } - - log.Printf("Created channel: '%s'", channel_name) - return channel, nil -} - -func DeleteChannel(discord *discordgo.Session, guildID string, channel_name string) (bool, error) { - - channels, err := discord.GuildChannels(guildID) - if err != nil { - return false, fmt.Errorf("failed to list channels when deleting channel: '%s': %v", channel_name, err) - } - for _, channel := range channels { - if channel.Name == channel_name { - _, err = discord.ChannelDelete(channel.ID) - if err != nil { - return false, fmt.Errorf("failed to delete channel: %v", err) - } - return true, nil - } - } - - log.Printf("Tried to delete channel, but it didn't exist '%s'", channel_name) - return false, nil -} - -func GetChannelID(discord *discordgo.Session, guildID string, channel_name string) (string, error) { - channels, err := discord.GuildChannels(guildID) - if err != nil { - return "", fmt.Errorf("failed to list channels when getting channel id: '%s': %v", channel_name, err) - } - for _, channel := range channels { - if channel.Name == channel_name { - return channel.ID, nil - } - } - - return "", fmt.Errorf("failed to get channel id for '%s': channel not found", channel_name) -} diff --git a/core/channel.go b/core/channel.go new file mode 100644 index 0000000..447e346 --- /dev/null +++ b/core/channel.go @@ -0,0 +1,7 @@ +package core + +type Channel struct { + Name string + ID string + Verified bool +} diff --git a/app/configuration.go b/core/configuration.go similarity index 97% rename from app/configuration.go rename to core/configuration.go index 29bb108..4dd0f25 100644 --- a/app/configuration.go +++ b/core/configuration.go @@ -1,4 +1,4 @@ -package app +package core type Config struct { Discord DiscordConfig `yaml:"discord"` diff --git a/app/event.go b/core/event.go similarity index 77% rename from app/event.go rename to core/event.go index 87caa3a..82746e0 100644 --- a/app/event.go +++ b/core/event.go @@ -1,4 +1,4 @@ -package app +package core import ( "fmt" @@ -10,14 +10,18 @@ import ( const REMOTE_LOCATION string = "online" type Event struct { - Name string - Location string - DateTime time.Time + Name string + ID string + Location string + Completed bool + DateTime time.Time - OrganizerID string + Organizer *User } -func (event *Event) GetChannelName() string { +// Channel returns a channel object associated with an event +func (event *Event) Channel() *Channel { + month := event.GetMonthPrefix() day := event.DateTime.Day() city := event.GetCityFromLocation() @@ -29,13 +33,17 @@ func (event *Event) GetChannelName() string { re, _ := regexp.Compile(`[^\w\-]`) channel = re.ReplaceAllString(channel, "") - return channel + return &Channel{ + Name: channel, + Verified: false, + } } +// GetCityFromLocation returns the city name of an event's location func (event *Event) GetCityFromLocation() string { if event.Location == REMOTE_LOCATION { - return REMOTE_LOCATION + return fmt.Sprint("-", REMOTE_LOCATION) } parts := strings.Split(event.Location, " ") index := -1 @@ -65,6 +73,7 @@ func (event *Event) GetCityFromLocation() string { return fmt.Sprint("-", loc) } +// GetMonthPrefix returns a month in short form func (event *Event) GetMonthPrefix() string { month := event.DateTime.Month() data := map[time.Month]string{ diff --git a/app/event_test.go b/core/event_test.go similarity index 76% rename from app/event_test.go rename to core/event_test.go index 1e1448e..17afe4c 100644 --- a/app/event_test.go +++ b/core/event_test.go @@ -1,4 +1,4 @@ -package app +package core import ( "testing" @@ -15,13 +15,13 @@ func TestGetChannelName(t *testing.T) { Location: "1234 Place Rd, Ann Arbor, MI 00000", DateTime: time.Date(2022, time.January, 5, 0, 0, 0, 0, time.UTC), } - assert.Equal("jan-5-ann-arbor-hello-world", event.GetChannelName()) + assert.Equal("jan-5-ann-arbor-hello-world", event.Channel().Name) event = Event{ Name: "Hello World", Location: "Michigan Theater, Ann Arbor", DateTime: time.Date(2022, time.January, 5, 0, 0, 0, 0, time.UTC), } - assert.Equal("jan-5-hello-world", event.GetChannelName()) + assert.Equal("jan-5-hello-world", event.Channel().Name) } diff --git a/core/organizer.go b/core/organizer.go new file mode 100644 index 0000000..29a98b0 --- /dev/null +++ b/core/organizer.go @@ -0,0 +1,16 @@ +package core + +import "fmt" + +type User struct { + ID string +} + +// Mention generated a Discord mention string for the user +func (user *User) Mention() string { + if user == nil { + return "" + } + + return fmt.Sprintf("<@%s>", user.ID) +} diff --git a/core/pointers.go b/core/pointers.go new file mode 100644 index 0000000..e27fdd1 --- /dev/null +++ b/core/pointers.go @@ -0,0 +1,6 @@ +package core + +// Bool returns a pointer to a bool +func Bool(v bool) *bool { + return &v +} diff --git a/discord/channel.go b/discord/channel.go new file mode 100644 index 0000000..086898c --- /dev/null +++ b/discord/channel.go @@ -0,0 +1,146 @@ +package discord + +import ( + "fmt" + "log" + + "github.com/bwmarrin/discordgo" + "github.com/yeslayla/birdbot/core" +) + +// NewChannelFromID creates a channel from a given ID +func (discord *Discord) NewChannelFromID(ID string) *core.Channel { + channel, err := discord.session.Channel(ID) + if err != nil { + return nil + } + + return &core.Channel{ + ID: ID, + Name: channel.Name, + Verified: true, + } +} + +// NewChannelFromName creates a channel object with its name +func (discord *Discord) NewChannelFromName(channel_name string) (*core.Channel, error) { + + // Grab channels to query + channels, err := discord.session.GuildChannels(discord.guildID) + if err != nil { + return nil, fmt.Errorf("failed to list channels when creating new channel: '%s': %v", channel_name, err) + } + for _, channel := range channels { + + // Found channel! + if channel.Name == channel_name { + + // Channel already exists! + return &core.Channel{ + Name: channel.Name, + ID: channel.ID, + Verified: true, + }, nil + } + } + + // Since a channel was not found, create one + channel, err := discord.session.GuildChannelCreate(discord.guildID, channel_name, discordgo.ChannelTypeGuildText) + if err != nil { + return nil, fmt.Errorf("failed to created channel '%s': %v", channel_name, err) + } + + log.Printf("Created channel: '%s'", channel_name) + return &core.Channel{ + Name: channel.Name, + ID: channel.ID, + }, nil +} + +// GetVerifiedChannel looks up channel data and returns a verified objec +func (discord *Discord) GetVerifiedChannel(channel *core.Channel) *core.Channel { + if channel.ID != "" { + return discord.NewChannelFromID(channel.ID) + } + if channel.Name != "" { + channel, err := discord.NewChannelFromName(channel.Name) + if err != nil { + log.Println("Failed to verify channel by name: ", err) + } + return channel + } + return nil +} + +// DeleteChannel deletes a channel +func (discord *Discord) DeleteChannel(channel *core.Channel) (bool, error) { + if channel.Verified == false { + channel = discord.GetVerifiedChannel(channel) + } + + _, err := discord.session.ChannelDelete(channel.ID) + if err != nil { + return false, fmt.Errorf("failed to delete channel: %v", err) + } + return true, nil +} + +// getChannelID returns a channel ID from its name +func (discord *Discord) getChannelID(channel_name string) (string, error) { + + // Get list of all channels + channels, err := discord.session.GuildChannels(discord.guildID) + if err != nil { + return "", fmt.Errorf("failed to list channels when getting channel id: '%s': %v", channel_name, err) + } + + // Loop through to find channel + for _, ch := range channels { + + // Find and return ID! + if ch.Name == channel_name { + return ch.ID, nil + } + } + + return "", fmt.Errorf("failed to get channel id for '%s': channel not found", channel_name) +} + +// SendMessage sends a message to a given channel +func (discord *Discord) SendMessage(channel *core.Channel, message string) error { + if channel.Verified == false { + channel = discord.GetVerifiedChannel(channel) + } + + _, err := discord.session.ChannelMessageSend(channel.ID, message) + return err +} + +// MoveChannelToCategory places a channel in a given category +func (discord *Discord) MoveChannelToCategory(channel *core.Channel, categoryID string) error { + if channel.Verified == false { + channel = discord.GetVerifiedChannel(channel) + } + + // Move to archive category + if _, err := discord.session.ChannelEdit(channel.ID, &discordgo.ChannelEdit{ + ParentID: categoryID, + }); err != nil { + return fmt.Errorf("failed to move channel to archive category: %v", err) + } + + return nil +} + +// ArchiveChannel archives a channel +func (discord *Discord) ArchiveChannel(channel *core.Channel) error { + if channel.Verified == false { + channel = discord.GetVerifiedChannel(channel) + } + + _, err := discord.session.ChannelEdit(channel.ID, &discordgo.ChannelEdit{ + Archived: core.Bool(true), + }) + + return err +} diff --git a/discord/discord.go b/discord/discord.go new file mode 100644 index 0000000..05c6dc8 --- /dev/null +++ b/discord/discord.go @@ -0,0 +1,97 @@ +package discord + +import ( + "fmt" + "log" + "os" + "os/signal" + + "github.com/bwmarrin/discordgo" + "github.com/stretchr/testify/mock" + "github.com/yeslayla/birdbot/core" +) + +type Discord struct { + mock.Mock + + guildID string + session *discordgo.Session + + // Signal for shutdown + stop chan os.Signal +} + +// New creates a new Discord session +func New(guildID string, token string) *Discord { + + // Create Discord Session + session, err := discordgo.New(fmt.Sprint("Bot ", token)) + if err != nil { + log.Fatalf("Failed to create Discord session: %v", err) + } + + return &Discord{ + session: session, + guildID: guildID, + } +} + +// Run opens the Discod session until exit +func (discord *Discord) Run() error { + + if err := discord.session.Open(); err != nil { + return fmt.Errorf("failed to open Discord session: %v", err) + } + defer discord.session.Close() + + // Keep alive + discord.stop = make(chan os.Signal, 1) + signal.Notify(discord.stop, os.Interrupt) + <-discord.stop + return nil +} + +// Stop tells the Discord session to exit +func (discord *Discord) Stop() { + discord.stop <- os.Kill +} + +// OnReady registers a handler for when the Discord session is ready +func (discord *Discord) OnReady(handler func(*Discord)) { + discord.session.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) { + handler(discord) + }) +} + +// OnEventCreate registers a handler when a guild scheduled event is created +func (discord *Discord) OnEventCreate(handler func(*Discord, *core.Event)) { + discord.session.AddHandler(func(s *discordgo.Session, r *discordgo.GuildScheduledEventCreate) { + if r.GuildID != discord.guildID { + return + } + event := NewEvent(r.GuildScheduledEvent) + handler(discord, event) + }) +} + +// OnEventDelete registers a handler when a guild scheduled event is deleted +func (discord *Discord) OnEventDelete(handler func(*Discord, *core.Event)) { + discord.session.AddHandler(func(s *discordgo.Session, r *discordgo.GuildScheduledEventDelete) { + if r.GuildID != discord.guildID { + return + } + event := NewEvent(r.GuildScheduledEvent) + handler(discord, event) + }) +} + +// OnEventUpdate registers a handler when a guild scheduled event is updated +func (discord *Discord) OnEventUpdate(handler func(*Discord, *core.Event)) { + discord.session.AddHandler(func(s *discordgo.Session, r *discordgo.GuildScheduledEventUpdate) { + if r.GuildID != discord.guildID { + return + } + event := NewEvent(r.GuildScheduledEvent) + handler(discord, event) + }) +} diff --git a/discord/event.go b/discord/event.go new file mode 100644 index 0000000..c33aff7 --- /dev/null +++ b/discord/event.go @@ -0,0 +1,28 @@ +package discord + +import ( + "github.com/bwmarrin/discordgo" + "github.com/yeslayla/birdbot/core" +) + +// NewEvent converts a discordgo.GuildScheduledEvent to birdbot event +func NewEvent(guildEvent *discordgo.GuildScheduledEvent) *core.Event { + event := &core.Event{ + Name: guildEvent.Name, + ID: guildEvent.ID, + Organizer: &core.User{ + ID: guildEvent.CreatorID, + }, + DateTime: guildEvent.ScheduledStartTime, + } + + event.Completed = guildEvent.Status == discordgo.GuildScheduledEventStatusCompleted + + if guildEvent.EntityType != discordgo.GuildScheduledEventEntityTypeExternal { + event.Location = core.REMOTE_LOCATION + } else { + event.Location = guildEvent.EntityMetadata.Location + } + + return event +} diff --git a/discord/user.go b/discord/user.go new file mode 100644 index 0000000..189a33a --- /dev/null +++ b/discord/user.go @@ -0,0 +1,20 @@ +package discord + +import ( + "log" + + "github.com/bwmarrin/discordgo" + "github.com/yeslayla/birdbot/core" +) + +// NewUser creates a new user object from a discordgo.User object +func NewUser(user *discordgo.User) *core.User { + if user == nil { + log.Print("Cannot user object, user is nil!") + return nil + } + + return &core.User{ + ID: user.ID, + } +} diff --git a/go.mod b/go.mod index c40dcc7..9bbf052 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/gorilla/websocket v1.4.2 // indirect github.com/joho/godotenv v1.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 8f8fd05..78dd867 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb 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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/main.go b/main.go index 22c12d2..8c33a94 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "fmt" "log" "github.com/yeslayla/birdbot/app" @@ -9,9 +10,16 @@ import ( func main() { var config_file string + var version bool flag.StringVar(&config_file, "c", "birdbot.yaml", "Path to config file") + flag.BoolVar(&version, "v", false, "List version") flag.Parse() + if version { + fmt.Printf("BirdBot %s (%s)\n", app.Version, app.Build) + return + } + bot := app.NewBot() if err := bot.Initialize(config_file); err != nil { log.Fatal("Failed to initialize: ", err)