package handler import ( "context" "fmt" "log" "ticket-pimp/internal/controller" "ticket-pimp/internal/domain" "github.com/bwmarrin/discordgo" ) type router struct { Routes []route controller controller.WorkflowController } // Подключение роутов к Discord боту func InitRouter(wc controller.WorkflowController) *router { var r router r.Routes = append( r.Routes, r.CreateRepoHandler(3), r.CreateFolderHandler(3), r.CreateTicketHandler(3), ) r.controller = wc return &r } type route struct { Command discordgo.ApplicationCommand Handler func(s *discordgo.Session, i *discordgo.InteractionCreate) } func (h *router) CreateRepoHandler(repoNameMinLength int) route { const ( projectRepo = "project_repo" buildRepo = "build_repo" ) return route{ Command: discordgo.ApplicationCommand{ Name: "repo", Description: "Command for repository creation", Options: []*discordgo.ApplicationCommandOption{ { Type: discordgo.ApplicationCommandOptionString, Name: "repo_type", 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: "repo_name", Description: "Type the repository's name", Required: false, MinLength: &repoNameMinLength, }, }, }, Handler: func(s *discordgo.Session, i *discordgo.InteractionCreate) { var result string // Access options in the order provided by the user. options := i.ApplicationCommandData().Options // Or convert the slice into a map optionMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(options)) for _, opt := range options { optionMap[opt.Name] = opt } var str string = "" project, err := h.controller.GetProjectByChannelID(context.TODO(), i.ChannelID) if err != nil { result = fmt.Sprintf("unable to retrieve project from db, error: %v", err) } else { var suffix string if option, ok := optionMap["repo_type"]; ok { switch option.Value { case projectRepo: suffix = "" case buildRepo: suffix = "-build" } } if project == nil { if option, ok := optionMap["repo_name"]; ok { str = option.StringValue() } else { str = "" } } else { str = project.ShortName } if str == "" { result = "Ты, либо в проекте репо создавай, либо имя напиши, блет!" } else { str = str + suffix // var g *domain.Git g, err := h.controller.IGit.CreateRepo(str) if err != nil { result = fmt.Sprintf("error while repo creation: %v", err) } else { result = "🚀 " + g.HtmlUrl + " was created" } } } discerr := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ // Ignore type for now, they will be discussed in "responses" Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: result, }, }) log.Println(discerr) }, } } func (h *router) CreateFolderHandler(nameMinLenght int) route { const ( nameOption string = "folder_name" ) return route{ Command: discordgo.ApplicationCommand{ Name: "folder", Description: "Command for cloud folder creation", Options: []*discordgo.ApplicationCommandOption{ { Type: discordgo.ApplicationCommandOptionString, Name: nameOption, Description: "Type the repository's name", Required: false, MinLength: &nameMinLenght, }, }, }, Handler: func(s *discordgo.Session, i *discordgo.InteractionCreate) { var result string // Access options in the order provided by the user. options := i.ApplicationCommandData().Options // Or convert the slice into a map optionMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(options)) for _, opt := range options { optionMap[opt.Name] = opt } var str string = "" project, err := h.controller.GetProjectByChannelID(context.TODO(), i.ChannelID) if err != nil { result = fmt.Sprintf("unable to retrieve project from db, error: %v", err) } else { if project == nil { if option, ok := optionMap[nameOption]; ok { str = option.StringValue() } else { str = "" } } else { str = project.ShortName } if str == "" { result = "Ты, либо в проекте директорию создавай, либо имя напиши, блет!" } else { f, err := h.controller.ICloud.CreateFolder(str) if err != nil { result = fmt.Sprintf("error while cloud folder creation: %v", err) } else { result = "📂 Folder: " + f.PrivateURL + " was created" } } } discerr := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ // Ignore type for now, they will be discussed in "responses" Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: result, }, }) log.Println(discerr) }, } } func (h *router) CreateTicketHandler(repoNameMinLength int) route { return route{ Command: discordgo.ApplicationCommand{ Name: "project", Description: "Create new development ticket", Options: []*discordgo.ApplicationCommandOption{ { Type: discordgo.ApplicationCommandOptionString, Name: "project_name", Description: "Temporary project name", Required: true, MinLength: &repoNameMinLength, }, }, }, Handler: func(s *discordgo.Session, i *discordgo.InteractionCreate) { var result string // Access options in the order provided by the user. options := i.ApplicationCommandData().Options // Or convert the slice into a map optionMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(options)) for _, opt := range options { optionMap[opt.Name] = opt } if option, ok := optionMap["project_name"]; ok { dchan, err := s.GuildChannelCreate(i.GuildID, option.StringValue(), discordgo.ChannelTypeGuildText) if err != nil { result = fmt.Sprintf("chan creation problem: %v\n", err) } else { p, err := h.controller.ProjectCreate(context.TODO(), domain.Project{ ChannelID: dchan.ID, }) if err != nil { result = fmt.Sprintf("unable to create project: %v\n", err) } else { edit := discordgo.ChannelEdit{ Name: p.ShortName, ParentID: "1150719794853716028", } dchan, err = s.ChannelEdit(dchan.ID, &edit) if err != nil { result = fmt.Sprintf("channel created, but unable to edit: %v\n", err) } else { _, err = s.ChannelMessageSend(dchan.ID, "Hello!") if err != nil { log.Printf("message send problem: %v\n", err) } result = dchan.ID } } } } s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ // Ignore type for now, they will be discussed in "responses" Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: result, }, }) }, } }