ticket-pimp/client/discord/discord.go

162 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package discord
import (
"errors"
"fmt"
"log"
"os"
"os/signal"
"ticket-pimp/client/discord/router"
"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 {
// Моментальный ответ для избежания столкновения с протуханием токена
initialResponse := discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Flags: discordgo.MessageFlagsEphemeral,
Content: "👩‍🍳 Cooking your query..",
},
}
s.InteractionRespond(i.Interaction, &initialResponse)
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 := router.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.IsTaskForum)
if err != nil {
log.Print(err)
}
tagsAvailable := []discordgo.ForumTag{
{
Name: "В работе",
Moderated: true,
EmojiName: "👩‍🍳",
},
{
Name: "Готово",
Moderated: true,
EmojiName: "✅",
},
}
dchan, err := s.ChannelEditComplex(forum.ID, &discordgo.ChannelEdit{
AvailableTags: &tagsAvailable,
})
if err != nil {
log.Fatal(err)
}
log.Printf("Channel %s with ID %s propagated by tags:", dchan.Name, dchan.ID)
for _, t := range dchan.AvailableTags {
log.Printf("N: %s, ID: %s", t.Name, t.ID)
}
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
}