ticket-pimp/client/discord/discord.go

134 lines
3.2 KiB
Go

package discord
import (
"errors"
"fmt"
"log"
"os"
"os/signal"
"ticket-pimp/client/discord/handler"
"ticket-pimp/internal/controller"
"ticket-pimp/internal/domain"
"github.com/bwmarrin/discordgo"
)
func initBotWith(token string) *discordgo.Session {
discord, err := discordgo.New("Bot " + token)
if err != nil {
log.Fatalf("unable to create discord session: %v", err)
}
return discord
}
type DiscordOptions struct {
Config *domain.Config
Controller *controller.WorkflowController
}
func checkPrivateMessaging(s *discordgo.Session, i *discordgo.InteractionCreate) error {
dchan, err := s.Channel(i.ChannelID)
if err != nil {
return err
}
if dchan.Type == discordgo.ChannelTypeDM {
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: "Yo, fella! I'm not working in private!",
},
})
return errors.New("no private messages! lol")
}
return nil
}
func Run(conf domain.Config, opts DiscordOptions) error {
token := conf.Discord.Token
s := initBotWith(token)
router := handler.InitRouter(*opts.Controller, &conf.Discord, &conf.Telegram)
commandHandlers := map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){}
for _, handler := range router.Commands {
commandHandlers[handler.Command.Name] = handler.Handler
}
componentsHandlers := map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){
"task_start": router.Components[0].Handler,
"task_close": router.Components[0].Handler,
}
s.AddHandler(router.ListenPosts)
s.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
err := checkPrivateMessaging(s, i)
if err != nil {
return
}
switch i.Type {
case discordgo.InteractionApplicationCommand:
if h, ok := commandHandlers[i.ApplicationCommandData().Name]; ok {
h(s, i)
}
case discordgo.InteractionMessageComponent:
if h, ok := componentsHandlers[i.MessageComponentData().CustomID]; ok {
h(s, i)
}
}
})
if err := s.Open(); err != nil {
return fmt.Errorf("cannot open the session: %v", err)
}
// UPDATE FORUM IF NEEDED:
forum, err := s.Channel(conf.Discord.IsProjectChannel)
if err != nil {
log.Print(err)
}
_, err = s.ChannelEditComplex(forum.ID, &discordgo.ChannelEdit{
AvailableTags: &router.Tags,
})
if err != nil {
log.Fatal(err)
}
log.Println("Adding commands...")
var cmds []*discordgo.ApplicationCommand
var logString []string
for _, h := range router.Commands {
cmd, err := s.ApplicationCommandCreate(s.State.User.ID, "", &h.Command)
if err != nil {
log.Panicf("Cannot create '%v' command: %v", h.Command.Name, err)
}
cmds = append(cmds, cmd)
logString = append(logString, cmd.Name)
}
log.Println("Following commands added:")
log.Println(logString)
defer s.Close()
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
<-stop
log.Println("Graceful shutdown")
log.Println("Removing commands...")
for _, h := range cmds {
err := s.ApplicationCommandDelete(s.State.User.ID, "", h.ID)
if err != nil {
log.Panicf("Cannot delete '%v' command: %v", h.Name, err)
}
}
return nil
}