ticket-pimp/client/discord/discord.go

236 lines
5.2 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 (
"fmt"
"log"
"os"
"os/signal"
"ticket-pimp/client/discord/discord_handler"
"ticket-pimp/internal/controller"
"ticket-pimp/internal/domain"
"ticket-pimp/internal/services"
"github.com/bwmarrin/discordgo"
)
var (
minLength int = 3
repoType string = "repo_type"
projectRepo string = "project_repo"
buildRepo string = "build_repo"
nameOption string = "repo_name"
)
var tags = []discordgo.ForumTag{
{
Name: "В работе",
Moderated: true,
EmojiName: "👩‍🍳",
},
{
Name: "Готово",
Moderated: true,
EmojiName: "✅",
},
}
var commands = []discordgo.ApplicationCommand{
{
Name: "ping",
Description: "pongs in a reply",
},
{
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 Run(conf domain.Config, opts DiscordOptions) error {
s := initBotWith(conf.Discord.Token)
h := discord_handler.New(
opts.Controller,
&conf.Discord,
services.NewDummyClient(conf.Telegram),
tags,
)
commandHandlers := map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){}
for _, cmd := range commands {
var f func(s *discordgo.Session, i *discordgo.InteractionCreate)
switch cmd.Name {
case "ping":
f = h.Ping
case "project":
f = h.CreateTicket
case "info":
f = h.ProjectInfo
case "repo":
f = h.CreateGit
case "folder":
f = h.CreateFolder
case "init_project":
f = h.InitChannelAsProject
}
commandHandlers[cmd.Name] = f
}
componentsHandlers := map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){
"task_start": h.HandleTaskButtons,
"task_close": h.HandleTaskButtons,
}
s.AddHandler(h.ListenPosts)
s.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
h.AllInteractions(s, i)
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)
}
dchan, err := s.ChannelEditComplex(forum.ID, &discordgo.ChannelEdit{
AvailableTags: &tags,
})
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
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")
}
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
}