311 lines
7.7 KiB
Go
311 lines
7.7 KiB
Go
package discord
|
||
|
||
import (
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"os/signal"
|
||
"ticket-pimp/client/discord/discord_handler"
|
||
"ticket-pimp/client/discord/discord_router"
|
||
|
||
"ticket-pimp/internal/controller"
|
||
"ticket-pimp/internal/domain"
|
||
"ticket-pimp/internal/external"
|
||
|
||
"github.com/bwmarrin/discordgo"
|
||
)
|
||
|
||
var (
|
||
// minLength int = 3
|
||
// repoType string = "repo_type"
|
||
// projectRepo string = "project_repo"
|
||
// buildRepo string = "build_repo"
|
||
// nameOption string = "name"
|
||
tagsPreset = [3]discordgo.ForumTag{
|
||
{
|
||
Name: "В работе",
|
||
Moderated: true,
|
||
EmojiName: "👩🍳",
|
||
},
|
||
{
|
||
Name: "Готово",
|
||
Moderated: true,
|
||
EmojiName: "✅",
|
||
},
|
||
{
|
||
Name: "Не начат",
|
||
Moderated: true,
|
||
EmojiName: "🚧",
|
||
},
|
||
}
|
||
|
||
// commands = []discordgo.ApplicationCommand{
|
||
// {
|
||
// Name: "ping",
|
||
// Description: "pongs in a reply",
|
||
// },
|
||
// {
|
||
// Name: "coda_ticket",
|
||
// Description: "Creates ticket in Coda.io w/ provided info",
|
||
// },
|
||
// {
|
||
// Name: "init_project",
|
||
// Description: "Connect project with Coda ID",
|
||
// Options: []*discordgo.ApplicationCommandOption{
|
||
// {
|
||
// Type: discordgo.ApplicationCommandOptionString,
|
||
// Name: "key",
|
||
// Description: "Project's key from Coda.io",
|
||
// Required: true,
|
||
// MinLength: &minLength,
|
||
// },
|
||
// },
|
||
// },
|
||
// {
|
||
// Name: "project",
|
||
// Description: "Create new development ticket",
|
||
// Options: []*discordgo.ApplicationCommandOption{
|
||
// {
|
||
// Type: discordgo.ApplicationCommandOptionString,
|
||
// Name: "project_name",
|
||
// Description: "Temporary project name",
|
||
// Required: true,
|
||
// MinLength: &minLength,
|
||
// },
|
||
// },
|
||
// },
|
||
// {
|
||
// Name: "info",
|
||
// Description: "Get project's info",
|
||
// },
|
||
// {
|
||
// Name: "repo",
|
||
// Description: "Creates repository of selected type. Name used for projects channels only",
|
||
// Options: []*discordgo.ApplicationCommandOption{
|
||
// {
|
||
// Type: discordgo.ApplicationCommandOptionString,
|
||
// Name: repoType,
|
||
// Description: "The type of repo",
|
||
// Required: true,
|
||
// Choices: []*discordgo.ApplicationCommandOptionChoice{
|
||
// {
|
||
// Name: "Unity project repo",
|
||
// Value: projectRepo,
|
||
// },
|
||
// {
|
||
// Name: "XCode build repo",
|
||
// Value: buildRepo,
|
||
// },
|
||
// },
|
||
// },
|
||
// {
|
||
// Type: discordgo.ApplicationCommandOptionString,
|
||
// Name: nameOption,
|
||
// Description: "Type the repository's name",
|
||
// Required: false,
|
||
// MinLength: &minLength,
|
||
// },
|
||
// },
|
||
// },
|
||
// {
|
||
// Name: "folder",
|
||
// Description: "Command for cloud folder creation",
|
||
// Options: []*discordgo.ApplicationCommandOption{
|
||
// {
|
||
// Type: discordgo.ApplicationCommandOptionString,
|
||
// Name: nameOption,
|
||
// Description: "Type the folder's name",
|
||
// Required: false,
|
||
// MinLength: &minLength,
|
||
// },
|
||
// },
|
||
// },
|
||
// }
|
||
)
|
||
|
||
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 updateForum(conf *domain.Config, s *discordgo.Session) ([]discordgo.ForumTag, error) {
|
||
|
||
log.Println("Updating forum chan...")
|
||
|
||
// Get tasks channel instance:
|
||
forum, err := s.Channel(conf.Discord.IsTaskForum)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// Map all pre-set tags
|
||
var tagsMap = map[string]discordgo.ForumTag{}
|
||
for _, t := range forum.AvailableTags {
|
||
tagsMap[t.Name] = t
|
||
}
|
||
|
||
// Result tags array
|
||
tags := forum.AvailableTags
|
||
|
||
// Check if preset tag exists into current channel..
|
||
for i := 0; i < len(tagsPreset); i++ {
|
||
_, ok := tagsMap[tagsPreset[i].Name]
|
||
if !ok {
|
||
// .. and append them if they aren't
|
||
tags = append(tags, tagsPreset[i])
|
||
}
|
||
}
|
||
|
||
dchan, err := s.ChannelEditComplex(forum.ID, &discordgo.ChannelEdit{
|
||
AvailableTags: &tags,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
log.Printf("Channel %s with ID %s propagated by tags:", dchan.Name, dchan.ID)
|
||
for _, t := range dchan.AvailableTags {
|
||
fmt.Printf("N: %s, ID: %s", t.Name, t.ID)
|
||
}
|
||
|
||
// Update config w/ tags:
|
||
confTags := make(map[domain.TaskState]string)
|
||
|
||
for _, tag := range dchan.AvailableTags {
|
||
switch tag.Name {
|
||
case "Не начат":
|
||
confTags[domain.State(0)] = tag.ID
|
||
case "В работе":
|
||
confTags[domain.State(1)] = tag.ID
|
||
case "Готово":
|
||
confTags[domain.State(2)] = tag.ID
|
||
}
|
||
}
|
||
|
||
conf.Discord.Tags = confTags
|
||
|
||
return dchan.AvailableTags, nil
|
||
}
|
||
|
||
// commandRegistration
|
||
// unused, cause method was deprecated;
|
||
// func commandRegistration(s *discordgo.Session, commands []discordgo.ApplicationCommand) []*discordgo.ApplicationCommand {
|
||
// oldCommands, err := s.ApplicationCommands(s.State.User.ID, s.State.Application.GuildID)
|
||
// if err != nil {
|
||
// log.Panicf("Cannot get old commands: %v", err)
|
||
// }
|
||
|
||
// var removedCommands []string
|
||
// for _, cmd := range oldCommands {
|
||
// err := s.ApplicationCommandDelete(s.State.User.ID, s.State.Application.GuildID, cmd.ID)
|
||
// if err != nil {
|
||
// log.Printf("commands removed: %v", removedCommands)
|
||
// log.Panicf("removing old comands failed with %s command, err: %v", cmd.Name, err)
|
||
// }
|
||
// removedCommands = append(removedCommands, cmd.Name)
|
||
// }
|
||
// log.Printf("commands removed: %v", removedCommands)
|
||
|
||
// log.Println("Adding commands...")
|
||
// var cmds []*discordgo.ApplicationCommand
|
||
// for _, cmd := range commands {
|
||
// cmd, err := s.ApplicationCommandCreate(s.State.User.ID, "", &cmd)
|
||
// if err != nil {
|
||
// log.Panicf("Cannot create '%v' command: %v", cmd.Name, err)
|
||
// }
|
||
// cmds = append(cmds, cmd)
|
||
// log.Println(cmd.Name + " command added")
|
||
// }
|
||
// return cmds
|
||
// }
|
||
|
||
// Run - метод
|
||
//
|
||
// 1. Инициализирует бота Discord, создаёт некоторое подобие роутера
|
||
// 2. Объявляет доступные роутинги
|
||
// 3. Объявляет доступные для роутов хэндлеры
|
||
func Run(conf *domain.Config, opts DiscordOptions) error {
|
||
|
||
// bot init
|
||
s := initBotWith(conf.Discord.Token)
|
||
|
||
// Init new handler
|
||
h := discord_handler.New(
|
||
opts.Controller,
|
||
&conf.Discord,
|
||
external.NewDummyClient(conf.Telegram),
|
||
)
|
||
|
||
r := discord_router.NewApp(s)
|
||
|
||
// Depretated
|
||
// var commonMw = []discord_router.Middleware{
|
||
// h.WithInitialResponse,
|
||
// h.RejectPM,
|
||
// }
|
||
|
||
// Depretated
|
||
// r.Use(commonMw...).
|
||
// Route("ping", h.Ping).
|
||
// Route("project", h.CreateProject).
|
||
// Route("info", h.ProjectInfo).
|
||
// Route("repo", h.CreateGit).
|
||
// Route("folder", h.CreateFolder).
|
||
// Route("init_project", h.InitChannelAsProject).
|
||
// Route("coda_ticket", h.CreateCoda)
|
||
|
||
// and components
|
||
r.
|
||
/*Use().*/ // Combining into group duplicates replies
|
||
Route("task_start", h.HandleTaskButtons).
|
||
Route("task_close", h.HandleTaskButtons)
|
||
|
||
// Add posts listener
|
||
s.AddHandler(h.ListenPosts)
|
||
|
||
// Add interactions handlers
|
||
s.AddHandler(r.Serve)
|
||
|
||
// session opening
|
||
if err := s.Open(); err != nil {
|
||
return fmt.Errorf("cannot open the session: %v", err)
|
||
}
|
||
|
||
// Forum update
|
||
tags, err := updateForum(conf, s)
|
||
if err != nil {
|
||
log.Println(err.Error())
|
||
}
|
||
|
||
//Update handler with tags:
|
||
h.SetAvailableTags(tags)
|
||
|
||
// commands registration
|
||
// cmds := commandRegistration(s, commands)
|
||
|
||
// gracefull shutdown
|
||
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
|
||
}
|