Discord Components & Role Selection (#5)
This commit is contained in:
		
							
								
								
									
										61
									
								
								modules/announce_events.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								modules/announce_events.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
package modules
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/yeslayla/birdbot/common"
 | 
			
		||||
	"github.com/yeslayla/birdbot/mastodon"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type announceEventsModule struct {
 | 
			
		||||
	bot      common.ModuleManager
 | 
			
		||||
	mastodon *mastodon.Mastodon
 | 
			
		||||
	guildID  string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewAnnounceEventsComponent creates a new component
 | 
			
		||||
func NewAnnounceEventsComponent(mastodon *mastodon.Mastodon, guildID string) common.Module {
 | 
			
		||||
	return &announceEventsModule{
 | 
			
		||||
		mastodon: mastodon,
 | 
			
		||||
		guildID:  guildID,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialize registers event listeners
 | 
			
		||||
func (c *announceEventsModule) Initialize(birdbot common.ModuleManager) error {
 | 
			
		||||
	c.bot = birdbot
 | 
			
		||||
 | 
			
		||||
	_ = birdbot.OnEventCreate(c.OnEventCreate)
 | 
			
		||||
	_ = birdbot.OnEventDelete(c.OnEventDelete)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OnEventCreate notifies about the event creation to given providers
 | 
			
		||||
func (c *announceEventsModule) OnEventCreate(e common.Event) error {
 | 
			
		||||
	eventURL := fmt.Sprintf("https://discordapp.com/events/%s/%s", c.guildID, e.ID)
 | 
			
		||||
	c.bot.Notify(fmt.Sprintf("%s is organizing an event '%s': %s", e.Organizer.DiscordMention(), e.Name, eventURL))
 | 
			
		||||
 | 
			
		||||
	// Toot an announcement if Mastodon is configured
 | 
			
		||||
	if c.mastodon != nil {
 | 
			
		||||
		err := c.mastodon.Toot(fmt.Sprintf("A new event has been organized '%s': %s", e.Name, eventURL))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Println("Failed to send Mastodon Toot:", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *announceEventsModule) OnEventDelete(e common.Event) error {
 | 
			
		||||
	_ = c.bot.Notify(fmt.Sprintf("%s cancelled '%s' on %s, %d!", e.Organizer.DiscordMention(), e.Name, e.DateTime.Month().String(), e.DateTime.Day()))
 | 
			
		||||
 | 
			
		||||
	if c.mastodon != nil {
 | 
			
		||||
		err := c.mastodon.Toot(fmt.Sprintf("'%s' cancelled on %s, %d!", e.Name, e.DateTime.Month().String(), e.DateTime.Day()))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Println("Failed to send Mastodon Toot:", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										89
									
								
								modules/manage_event_channels.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								modules/manage_event_channels.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
package modules
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"github.com/yeslayla/birdbot/common"
 | 
			
		||||
	"github.com/yeslayla/birdbot/core"
 | 
			
		||||
	"github.com/yeslayla/birdbot/discord"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type manageEventChannelsModule struct {
 | 
			
		||||
	session           *discord.Discord
 | 
			
		||||
	categoryID        string
 | 
			
		||||
	archiveCategoryID string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewManageEventChannelsComponent creates a new component
 | 
			
		||||
func NewManageEventChannelsComponent(categoryID string, archiveCategoryID string, session *discord.Discord) common.Module {
 | 
			
		||||
	return &manageEventChannelsModule{
 | 
			
		||||
		session:           session,
 | 
			
		||||
		categoryID:        categoryID,
 | 
			
		||||
		archiveCategoryID: archiveCategoryID,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialize registers event listeners
 | 
			
		||||
func (c *manageEventChannelsModule) Initialize(birdbot common.ModuleManager) error {
 | 
			
		||||
	_ = birdbot.OnEventCreate(c.OnEventCreate)
 | 
			
		||||
	_ = birdbot.OnEventComplete(c.OnEventComplete)
 | 
			
		||||
	_ = birdbot.OnEventDelete(c.OnEventDelete)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OnEventCreate creates a new channel for an event and moves it to a given category
 | 
			
		||||
func (c *manageEventChannelsModule) OnEventCreate(e common.Event) error {
 | 
			
		||||
	channel, err := c.session.NewChannelFromName(core.GenerateChannelFromEvent(e).Name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Print("Failed to create channel for event: ", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c.categoryID != "" {
 | 
			
		||||
		err = c.session.MoveChannelToCategory(channel, c.categoryID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("Failed to move channel to events category '%s': %v", channel.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OnEventDelete deletes the channel associated with the given event
 | 
			
		||||
func (c *manageEventChannelsModule) OnEventDelete(e common.Event) error {
 | 
			
		||||
	_, err := c.session.DeleteChannel(core.GenerateChannelFromEvent(e))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Print("Failed to create channel for event: ", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OnEventComplete archives a given event channel if not given
 | 
			
		||||
// an archive category will delete the channel instead
 | 
			
		||||
func (c *manageEventChannelsModule) OnEventComplete(e common.Event) error {
 | 
			
		||||
	channel := core.GenerateChannelFromEvent(e)
 | 
			
		||||
 | 
			
		||||
	if c.archiveCategoryID != "" {
 | 
			
		||||
 | 
			
		||||
		if err := c.session.MoveChannelToCategory(channel, c.archiveCategoryID); err != nil {
 | 
			
		||||
			log.Print("Failed to move channel to archive category: ", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := c.session.ArchiveChannel(channel); err != nil {
 | 
			
		||||
			log.Print("Failed to archive channel: ", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log.Printf("Archived channel: '%s'", channel.Name)
 | 
			
		||||
 | 
			
		||||
	} else {
 | 
			
		||||
 | 
			
		||||
		// Delete Channel
 | 
			
		||||
		_, err := c.session.DeleteChannel(channel)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Print("Failed to delete channel: ", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log.Printf("Deleted channel: '%s'", channel.Name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								modules/recurring_events.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								modules/recurring_events.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
package modules
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/yeslayla/birdbot/common"
 | 
			
		||||
	"github.com/yeslayla/birdbot/discord"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type recurringEventsModule struct {
 | 
			
		||||
	session *discord.Discord
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewRecurringEventsComponent creates a new component instance
 | 
			
		||||
func NewRecurringEventsComponent() common.Module {
 | 
			
		||||
	return &recurringEventsModule{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialize registers event listeners
 | 
			
		||||
func (c *recurringEventsModule) Initialize(birdbot common.ModuleManager) error {
 | 
			
		||||
	_ = birdbot.OnEventComplete(c.OnEventComplete)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OnEventComplete checks for keywords before creating a new event
 | 
			
		||||
func (c *recurringEventsModule) OnEventComplete(e common.Event) error {
 | 
			
		||||
 | 
			
		||||
	if strings.Contains(strings.ToLower(e.Description), "recurring weekly") {
 | 
			
		||||
		startTime := e.DateTime.AddDate(0, 0, 7)
 | 
			
		||||
		finishTime := e.CompleteDateTime.AddDate(0, 0, 7)
 | 
			
		||||
		nextEvent := e
 | 
			
		||||
		nextEvent.DateTime = startTime
 | 
			
		||||
		nextEvent.CompleteDateTime = finishTime
 | 
			
		||||
 | 
			
		||||
		if err := c.session.CreateEvent(nextEvent); err != nil {
 | 
			
		||||
			log.Print("Failed to create recurring event: ", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										90
									
								
								modules/role_selection.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								modules/role_selection.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
			
		||||
package modules
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"github.com/yeslayla/birdbot/common"
 | 
			
		||||
	"github.com/yeslayla/birdbot/core"
 | 
			
		||||
	"github.com/yeslayla/birdbot/discord"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type roleSelectionModule struct {
 | 
			
		||||
	session  *discord.Discord
 | 
			
		||||
	cfg      core.RoleSelectionConfig
 | 
			
		||||
	exlusive bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewRoleSelectionComponent creates a new component
 | 
			
		||||
func NewRoleSelectionComponent(discord *discord.Discord, cfg core.RoleSelectionConfig) common.Module {
 | 
			
		||||
	return &roleSelectionModule{
 | 
			
		||||
		session:  discord,
 | 
			
		||||
		cfg:      cfg,
 | 
			
		||||
		exlusive: true,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialize setups component on discord and registers handlers
 | 
			
		||||
func (c *roleSelectionModule) Initialize(birdbot common.ModuleManager) error {
 | 
			
		||||
 | 
			
		||||
	roles := []*discord.Role{}
 | 
			
		||||
	roleButtons := []discord.Component{}
 | 
			
		||||
 | 
			
		||||
	for _, roleConfig := range c.cfg.Roles {
 | 
			
		||||
 | 
			
		||||
		// Create & Validate Roles
 | 
			
		||||
		role := c.session.GetRoleAndCreate(roleConfig.RoleName)
 | 
			
		||||
		configColor, _ := core.HexToColor(roleConfig.Color)
 | 
			
		||||
 | 
			
		||||
		if role.Color != configColor {
 | 
			
		||||
			role.Color = configColor
 | 
			
		||||
			role.Save()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Create button
 | 
			
		||||
		btn := c.session.NewButton(fmt.Sprint(c.cfg.Title, role.Name), role.Name)
 | 
			
		||||
		btn.OnClick(func(user common.User) {
 | 
			
		||||
 | 
			
		||||
			// Remove other roles if exclusive
 | 
			
		||||
			if c.exlusive {
 | 
			
		||||
				for _, r := range roles {
 | 
			
		||||
					if r.ID == role.ID {
 | 
			
		||||
						continue
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if c.session.HasRole(user, r) {
 | 
			
		||||
						c.session.UnassignRole(user, r)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Toggle role
 | 
			
		||||
			if c.session.HasRole(user, role) {
 | 
			
		||||
				if err := c.session.UnassignRole(user, role); err != nil {
 | 
			
		||||
					log.Printf("Failed to unassign role: %s", err)
 | 
			
		||||
				}
 | 
			
		||||
			} else if err := c.session.AssignRole(user, role); err != nil {
 | 
			
		||||
				log.Printf("Failed to assign role: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		roles = append(roles, role)
 | 
			
		||||
		roleButtons = append(roleButtons, btn)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	components := []discord.Component{}
 | 
			
		||||
	var actionRow *discord.ActionRow
 | 
			
		||||
	for i, btn := range roleButtons {
 | 
			
		||||
		if i%5 == 0 {
 | 
			
		||||
			actionRow = c.session.NewActionRow()
 | 
			
		||||
			components = append(components, actionRow)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		actionRow.AddComponent(btn)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.session.CreateMessageComponent(c.cfg.SelectionChannel, fmt.Sprintf("**%s**\n%s", c.cfg.Title, c.cfg.Description), components)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user