- start implementing onion arch;
This commit is contained in:
parent
f7dd74ffff
commit
47cae1e99d
|
|
@ -0,0 +1,18 @@
|
|||
package adapters
|
||||
|
||||
import "ticket-pimp/internal/domain"
|
||||
|
||||
type IDummyTelegram interface {
|
||||
DummyNotification(id string, text string)
|
||||
}
|
||||
|
||||
type ICloud interface {
|
||||
CreateFolder(name string) domain.Response
|
||||
}
|
||||
|
||||
type ICoda interface {
|
||||
ListDocs()
|
||||
CreateApp(task domain.CodaApplication)
|
||||
CreateTask(title string, desc string, creatorName string, creatorID string) (string, error)
|
||||
GetRowLink(id string) (string, error)
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"ticket-pimp/client/discord/handler"
|
||||
"ticket-pimp/client/discord/router"
|
||||
"ticket-pimp/internal/controller"
|
||||
"ticket-pimp/internal/domain"
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ func Run(conf domain.Config, opts DiscordOptions) error {
|
|||
|
||||
s := initBotWith(token)
|
||||
|
||||
router := handler.InitRouter(*opts.Controller, &conf.Discord, &conf.Telegram)
|
||||
router := router.InitRouter(*opts.Controller, &conf.Discord, &conf.Telegram)
|
||||
|
||||
commandHandlers := map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){}
|
||||
for _, handler := range router.Commands {
|
||||
|
|
@ -89,18 +89,35 @@ func Run(conf domain.Config, opts DiscordOptions) error {
|
|||
|
||||
// UPDATE FORUM IF NEEDED:
|
||||
|
||||
forum, err := s.Channel(conf.Discord.IsProjectChannel)
|
||||
forum, err := s.Channel(conf.Discord.IsTaskForum)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
_, err = s.ChannelEditComplex(forum.ID, &discordgo.ChannelEdit{
|
||||
AvailableTags: &router.Tags,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func (h *Handler) defaultFollowUp(answer string, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
|
||||
// Sending result:
|
||||
_, err := s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||
Content: answer,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||
Content: fmt.Sprintf("Something went wrong: %v", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"ticket-pimp/adapters"
|
||||
"ticket-pimp/internal/controller"
|
||||
"ticket-pimp/internal/domain"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
controller *controller.WorkflowController
|
||||
conf *domain.DiscordConfig
|
||||
tg adapters.IDummyTelegram
|
||||
}
|
||||
|
||||
func NewHandler(
|
||||
controller *controller.WorkflowController,
|
||||
conf *domain.DiscordConfig,
|
||||
tg adapters.IDummyTelegram,
|
||||
) *Handler {
|
||||
return &Handler{
|
||||
controller: controller,
|
||||
conf: conf,
|
||||
tg: tg,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) ping(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
|
||||
err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: "Pong to: " + i.Member.User.Mention(),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// setFlag
|
||||
// sets tag with In progress and Done text to discords channel;
|
||||
func (h *Handler) setFlag(s *discordgo.Session, i *discordgo.InteractionCreate, tag *discordgo.ForumTag) error {
|
||||
|
||||
th, err := s.Channel(i.ChannelID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
forum, err := s.Channel(th.ParentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Проверка на существование тега в списке тегов:
|
||||
if len(forum.AvailableTags) != 0 {
|
||||
for _, some := range forum.AvailableTags {
|
||||
if some.Name == tag.Name {
|
||||
_, err := s.ChannelEditComplex(i.ChannelID, &discordgo.ChannelEdit{
|
||||
AppliedTags: &[]string{some.ID},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListenPosts
|
||||
// ..listens to new posts in specific channel
|
||||
// to act them like a task
|
||||
func (h *Handler) ListenPosts(s *discordgo.Session, th *discordgo.ThreadCreate) {
|
||||
|
||||
// Check if thread starter is not a bot, and thread started at the tasks channel;
|
||||
if th.ParentID != h.conf.IsTaskForum || th.OwnerID == s.State.User.ID {
|
||||
return
|
||||
}
|
||||
|
||||
msgs, _ := s.ChannelMessages(th.ID, 1, "", "", "")
|
||||
|
||||
msg, _ := s.ChannelMessage(th.ID, msgs[0].ID)
|
||||
|
||||
if msg.Author.ID == s.State.User.ID {
|
||||
return
|
||||
}
|
||||
|
||||
content := th.Name
|
||||
content += "\n" + msg.Content
|
||||
|
||||
user, _ := s.GuildMember(th.GuildID, msg.Author.ID)
|
||||
|
||||
t, err := h.controller.WriteTaskToDB(&domain.Task{
|
||||
Description: content,
|
||||
Creator: user.User.Mention(),
|
||||
})
|
||||
if err != nil {
|
||||
s.ChannelMessageSend(th.ID, fmt.Sprintf("unable to write task to db, %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// [x] -- Отредактировать Thread name как для задачи
|
||||
_, err = s.ChannelEditComplex(th.ID, &discordgo.ChannelEdit{
|
||||
Name: fmt.Sprintf("Task ID: %d, by %s", t.ID, t.Creator),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("th edition is not complete: %v", err)
|
||||
}
|
||||
|
||||
// Fix the original task message:
|
||||
taskMessage, err := s.ChannelMessageSendComplex(th.ID, &discordgo.MessageSend{
|
||||
Content: content,
|
||||
Components: []discordgo.MessageComponent{
|
||||
discordgo.ActionsRow{
|
||||
Components: []discordgo.MessageComponent{
|
||||
discordgo.Button{
|
||||
Label: "Start",
|
||||
Style: discordgo.SuccessButton,
|
||||
Disabled: false,
|
||||
CustomID: "task_start",
|
||||
},
|
||||
discordgo.Button{
|
||||
Label: "Close",
|
||||
Style: discordgo.DangerButton,
|
||||
Disabled: true,
|
||||
CustomID: "task_close",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("th start message edition is not complete: %v", err)
|
||||
}
|
||||
|
||||
err = h.controller.UpdateTasksMessageID(context.TODO(), taskMessage.ID, t.ID)
|
||||
if err != nil {
|
||||
s.ChannelMessageSend(th.ID, fmt.Sprintf("unable to update task at the db, %v", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// handleTaskBurrons
|
||||
// .. handler function to work with the Action Buttons over a task
|
||||
func (h *Handler) handleTaskButton(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
|
||||
// Send an empty interaction response; ----------------------------------------------------------------
|
||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseUpdateMessage,
|
||||
Data: &discordgo.InteractionResponseData{},
|
||||
})
|
||||
|
||||
// Get assignee value; ---------------------------------------------------------------------------------
|
||||
user := i.Member.User.Mention()
|
||||
|
||||
var (
|
||||
opt int = -1
|
||||
doneButtonIsDisabled bool = false
|
||||
state domain.TaskState = domain.NewTaskState()
|
||||
message string
|
||||
)
|
||||
|
||||
// Check what flow was touched: -------------------------------------------------------------------------
|
||||
switch i.Interaction.MessageComponentData().CustomID {
|
||||
case "task_start":
|
||||
opt = 0
|
||||
doneButtonIsDisabled = false
|
||||
state = domain.InrpogressTaskState()
|
||||
message = "взята в работу"
|
||||
case "task_close":
|
||||
opt = 1
|
||||
doneButtonIsDisabled = true
|
||||
state = domain.DoneTaskState()
|
||||
message = "выполнена"
|
||||
}
|
||||
|
||||
// Send the task update to db --------------------------------------------------------------------------
|
||||
convertable, err := h.controller.UpdateTask(i.Message.ID, opt, user)
|
||||
if err != nil {
|
||||
s.ChannelMessageSend(i.ChannelID, fmt.Sprintf("Unable to update task at the db w/ error: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map DB's response to domain.Task: -------------------------------------------------------------------
|
||||
task := convertable.
|
||||
ExtractDomain()
|
||||
|
||||
newContent := task.DiscordMessage(state)
|
||||
|
||||
// Send message to the creator in Telegram: -------------------------------------------------------------
|
||||
|
||||
if task.CreatorLink != "" {
|
||||
h.tg.DummyNotification(
|
||||
task.CreatorLink,
|
||||
fmt.Sprintf("Task ID: %d %s", task.ID, message))
|
||||
}
|
||||
|
||||
// Send a message to the thread about the task was started: ---------------------------------------------
|
||||
_, err = s.ChannelMessageSendComplex(i.ChannelID, &discordgo.MessageSend{
|
||||
Content: newContent,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("error while sending start task message: %v", err)
|
||||
}
|
||||
|
||||
// Fix the original task message: ----------------------------------------------------------------------
|
||||
_, err = s.ChannelMessageEditComplex(&discordgo.MessageEdit{
|
||||
Channel: i.ChannelID,
|
||||
ID: i.Message.ID,
|
||||
Components: []discordgo.MessageComponent{
|
||||
discordgo.ActionsRow{
|
||||
Components: []discordgo.MessageComponent{
|
||||
discordgo.Button{
|
||||
Label: "Close",
|
||||
Style: discordgo.DangerButton,
|
||||
Disabled: doneButtonIsDisabled,
|
||||
CustomID: "task_close",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("th start message edition is not complete: %v", err)
|
||||
}
|
||||
|
||||
// [ ] Устанавливаем тэги статуса на тред ---------------------------------------------------------------------
|
||||
// err = h.setFlag(s, i, &h.Tags[opt])
|
||||
// if err != nil {
|
||||
// log.Printf("error while `start` tag setting: %v", err)
|
||||
// }
|
||||
}
|
||||
|
||||
func (h *Handler) createFolderHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
const (
|
||||
nameOption string = "folder_name"
|
||||
)
|
||||
|
||||
// Моментальный ответ для избежания столкновения с протуханием токена
|
||||
initialResponse := discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
Content: "👩🍳 Cooking your query..",
|
||||
},
|
||||
}
|
||||
|
||||
s.InteractionRespond(i.Interaction, &initialResponse)
|
||||
|
||||
// Определение переменной для ответа
|
||||
var result string = "unexpected result"
|
||||
|
||||
// Определение выбранных вариантов ответа
|
||||
options := i.ApplicationCommandData().Options
|
||||
|
||||
optionMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(options))
|
||||
for _, opt := range options {
|
||||
optionMap[opt.Name] = opt
|
||||
}
|
||||
|
||||
// Creating request:
|
||||
var req controller.FolderRequest
|
||||
name, insertedValueNotNil := optionMap[nameOption]
|
||||
dchan, err := s.Channel(i.ChannelID)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("error while identifying channel: %v", err)
|
||||
} else {
|
||||
|
||||
if dchan.ParentID == h.conf.IsProjectChannel {
|
||||
req.ChannelID = dchan.ID
|
||||
if insertedValueNotNil {
|
||||
req.InsertedName = name.StringValue()
|
||||
}
|
||||
|
||||
} else {
|
||||
req.ChannelID = ""
|
||||
if insertedValueNotNil {
|
||||
req.InsertedName = name.StringValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Making request:
|
||||
resp := h.controller.CreateFolder(context.TODO(), req)
|
||||
if resp.Project == nil {
|
||||
result = "Надо написать имя для папки, или создать папку из проекта!"
|
||||
} else {
|
||||
result = resp.Project.DiscordString()
|
||||
if resp.Message != nil {
|
||||
result += "Errors: " + resp.Message.Error()
|
||||
}
|
||||
}
|
||||
|
||||
h.defaultFollowUp(result, s, i)
|
||||
}
|
||||
|
||||
func (h *Handler) createRepoHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
const (
|
||||
repoType = "repo_type"
|
||||
projectRepo = "project_repo"
|
||||
buildRepo = "build_repo"
|
||||
nameOption = "repo_name"
|
||||
)
|
||||
// Моментальный ответ для избежания столкновения с протуханием токена
|
||||
initialResponse := discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
Content: "👩🍳 Cooking your query..",
|
||||
},
|
||||
}
|
||||
|
||||
s.InteractionRespond(i.Interaction, &initialResponse)
|
||||
|
||||
// Определение переменной для ответа
|
||||
var result string = "unexpected result"
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Creating request:
|
||||
var req controller.GitRequest
|
||||
name, insertedValueNotNil := optionMap[nameOption]
|
||||
isBuild := optionMap[repoType]
|
||||
switch isBuild.StringValue() {
|
||||
case buildRepo:
|
||||
req.IsBuildGit = true
|
||||
case projectRepo:
|
||||
req.IsBuildGit = false
|
||||
}
|
||||
dchan, err := s.Channel(i.ChannelID)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("error while identifying channel: %v", err)
|
||||
} else {
|
||||
|
||||
if dchan.ParentID == h.conf.IsProjectChannel {
|
||||
req.ChannelID = dchan.ID
|
||||
if insertedValueNotNil {
|
||||
req.InsertedName = name.StringValue()
|
||||
}
|
||||
} else {
|
||||
req.ChannelID = ""
|
||||
if insertedValueNotNil {
|
||||
req.InsertedName = name.StringValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Making request:
|
||||
resp := h.controller.CreateGit(context.TODO(), req)
|
||||
if resp.Project == nil {
|
||||
if resp.Message != nil {
|
||||
result = resp.Message.Error()
|
||||
}
|
||||
} else {
|
||||
|
||||
result = resp.Project.DiscordString()
|
||||
if resp.Message != nil {
|
||||
result += "Errors: " + resp.Message.Error()
|
||||
}
|
||||
|
||||
}
|
||||
h.defaultFollowUp(result, s, i)
|
||||
}
|
||||
|
||||
// PROJECT
|
||||
func (h *Handler) getInfo(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
|
||||
// Моментальный ответ для избежания столкновения с протуханием токена
|
||||
initialResponse := discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
Content: "👩🍳 Cooking your query..",
|
||||
},
|
||||
}
|
||||
|
||||
s.InteractionRespond(i.Interaction, &initialResponse)
|
||||
|
||||
var result string
|
||||
|
||||
// Get channel from the request
|
||||
dchan, err := s.Channel(i.ChannelID)
|
||||
if err != nil {
|
||||
result = "unable to get channel from the message"
|
||||
} else {
|
||||
project, err := h.controller.GetProjectByChannelID(context.TODO(), dchan.ID)
|
||||
if err != nil {
|
||||
result = err.Error()
|
||||
} else {
|
||||
if project != nil {
|
||||
result = project.DiscordString()
|
||||
if err != nil {
|
||||
result += "Errors: " + err.Error()
|
||||
}
|
||||
} else {
|
||||
result = "Something wrong with retrieving project from db"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
h.defaultFollowUp(result, s, i)
|
||||
}
|
||||
|
||||
func (h *Handler) initProjectFromChannel(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
|
||||
// Моментальный ответ для избежания столкновения с протуханием токена
|
||||
initialResponse := discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
Content: "👩🍳 Cooking your query..",
|
||||
},
|
||||
}
|
||||
|
||||
s.InteractionRespond(i.Interaction, &initialResponse)
|
||||
|
||||
var result string
|
||||
|
||||
// Get channel from the request
|
||||
dchan, err := s.Channel(i.ChannelID)
|
||||
if err != nil {
|
||||
result = "unable to get channel from the message"
|
||||
} else {
|
||||
if dchan.ParentID != h.conf.IsProjectChannel {
|
||||
// Sending result:
|
||||
_, err := s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||
Content: "This channel is not at the project's group",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||
Content: fmt.Sprintf("Something went wrong: %v", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 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["key"]; ok {
|
||||
var errMsg error = nil
|
||||
|
||||
project, err := h.controller.InitProjectInChannel(context.TODO(), i.ChannelID, option.StringValue())
|
||||
if err != nil {
|
||||
result = fmt.Sprintf("unable to init project: %v", err)
|
||||
} else {
|
||||
result = project.DiscordString()
|
||||
if errMsg != nil {
|
||||
result += "Errors: " + errMsg.Error()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h.defaultFollowUp(result, s, i)
|
||||
}
|
||||
|
||||
func (h *Handler) createTicketHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
|
||||
// Моментальный ответ для избежания столкновения с протуханием токена
|
||||
initialResponse := discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
Content: "👩🍳 Cooking your query..",
|
||||
},
|
||||
}
|
||||
|
||||
s.InteractionRespond(i.Interaction, &initialResponse)
|
||||
|
||||
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)
|
||||
_, err := s.ChannelDelete(dchan.ID)
|
||||
if err != nil {
|
||||
result += fmt.Sprintf("\nunable to clean channel: %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 %s created, but unable to edit follow up message: %v\n", p.ShortName, err)
|
||||
|
||||
} else {
|
||||
_, err = s.ChannelMessageSend(dchan.ID, "Hello!")
|
||||
if err != nil {
|
||||
log.Printf("message send problem: %v\n", err)
|
||||
}
|
||||
result = "Project " + p.ShortName + "Was created"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h.defaultFollowUp(result, s, i)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package handler
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -198,10 +198,10 @@ func (c *client) handleTaskButton(s *discordgo.Session, i *discordgo.Interaction
|
|||
}
|
||||
|
||||
// Устанавливаем тэги статуса на тред ---------------------------------------------------------------------
|
||||
err = c.setFlag(s, i, &c.Tags[opt])
|
||||
if err != nil {
|
||||
log.Printf("error while `start` tag setting: %v", err)
|
||||
}
|
||||
// err = c.setFlag(s, i, &c.Tags[opt])
|
||||
// if err != nil {
|
||||
// log.Printf("error while `start` tag setting: %v", err)
|
||||
// }
|
||||
}
|
||||
|
||||
type TelegramMessage struct {
|
||||
|
|
@ -212,6 +212,7 @@ type TelegramMessage struct {
|
|||
DisablePreview bool `json:"disable_web_page_preview"`
|
||||
}
|
||||
|
||||
// [ ] As a separate service?
|
||||
func (c *client) sendTelegramMessageToCreator(tgChatID string, text string) {
|
||||
|
||||
http := req.C()
|
||||
|
|
@ -224,26 +225,4 @@ func (c *client) sendTelegramMessageToCreator(tgChatID string, text string) {
|
|||
DisablePreview: true,
|
||||
}).
|
||||
Post("https://api.telegram.org/bot" + c.tgConf.Token + "/sendMessage")
|
||||
// [HTTP Kit Marlerino]::POST(
|
||||
// "https://api.telegram.org/bot" + Config.botToken +
|
||||
// "/sendMessage",
|
||||
// "",
|
||||
// Object(
|
||||
// "chat_id",
|
||||
// thisRow.[Creator ID].ToText(),
|
||||
// "text",
|
||||
// Format(
|
||||
// "<a href='{1}'>{2}</a> взята в работу",
|
||||
// thisRow.ObjectLink().ToText(),
|
||||
// "Задача"
|
||||
// ),
|
||||
// "disable_notification",
|
||||
// true,
|
||||
// "parse_mode",
|
||||
// "HTML",
|
||||
// "disable_web_page_preview",
|
||||
// true
|
||||
// )
|
||||
// )
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package handler
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package handler
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package handler
|
||||
package router
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package handler
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package handler
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -12,7 +12,7 @@ type client struct {
|
|||
Commands []Command
|
||||
Components []Component
|
||||
|
||||
Tags []discordgo.ForumTag
|
||||
// Tags []discordgo.ForumTag
|
||||
|
||||
controller controller.WorkflowController
|
||||
conf *domain.DiscordConfig
|
||||
|
|
@ -27,30 +27,16 @@ func InitRouter(wc controller.WorkflowController, conf *domain.DiscordConfig, tg
|
|||
r.conf = conf
|
||||
|
||||
r.Commands = append(r.Commands,
|
||||
r.CreateRepoHandler(3),
|
||||
r.CreateFolderHandler(3),
|
||||
// r.CreateRepoHandler(3),
|
||||
// r.CreateFolderHandler(3),
|
||||
r.Ping(),
|
||||
r.CreateTicketHandler(3),
|
||||
r.InitProjectFromChannel(3),
|
||||
r.GetInfo(),
|
||||
// r.CreateTicketHandler(3),
|
||||
// r.InitProjectFromChannel(3),
|
||||
// r.GetInfo(),
|
||||
)
|
||||
r.Components = append(r.Components,
|
||||
r.HandleTaskButtons(),
|
||||
)
|
||||
|
||||
r.Tags = append(
|
||||
r.Tags,
|
||||
discordgo.ForumTag{
|
||||
Name: "В работе",
|
||||
Moderated: true,
|
||||
EmojiName: "👩🍳",
|
||||
},
|
||||
|
||||
discordgo.ForumTag{
|
||||
Name: "Готово",
|
||||
Moderated: true,
|
||||
EmojiName: "✅",
|
||||
})
|
||||
r.tgConf = tgConf
|
||||
|
||||
return &r
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"ticket-pimp/adapters"
|
||||
"ticket-pimp/internal/controller"
|
||||
"ticket-pimp/internal/services"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
git services.IGit
|
||||
cloud services.ICloud
|
||||
coda services.ICoda
|
||||
cloud adapters.ICloud
|
||||
coda adapters.ICoda
|
||||
key string
|
||||
id string
|
||||
controller *controller.WorkflowController
|
||||
|
|
@ -16,8 +17,8 @@ type Handler struct {
|
|||
|
||||
func NewHandler(
|
||||
git services.IGit,
|
||||
cloud services.ICloud,
|
||||
coda services.ICoda,
|
||||
cloud adapters.ICloud,
|
||||
coda adapters.ICoda,
|
||||
controller *controller.WorkflowController,
|
||||
) *Handler {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"ticket-pimp/adapters"
|
||||
"ticket-pimp/internal/domain"
|
||||
"ticket-pimp/internal/services"
|
||||
"ticket-pimp/internal/storage/db"
|
||||
|
|
@ -11,8 +12,8 @@ import (
|
|||
|
||||
type WorkflowController struct {
|
||||
IGit services.IGit
|
||||
ICloud services.ICloud
|
||||
ICoda services.ICoda
|
||||
ICloud adapters.ICloud
|
||||
ICoda adapters.ICoda
|
||||
pool *pgxpool.Pool
|
||||
q *db.Queries
|
||||
ATags []discordgo.ForumTag
|
||||
|
|
@ -20,8 +21,8 @@ type WorkflowController struct {
|
|||
|
||||
func NewWorkflowController(
|
||||
git services.IGit,
|
||||
cloud services.ICloud,
|
||||
coda services.ICoda,
|
||||
cloud adapters.ICloud,
|
||||
coda adapters.ICoda,
|
||||
pool *pgxpool.Pool,
|
||||
) *WorkflowController {
|
||||
return &WorkflowController{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ type Folder struct {
|
|||
PrivateURL string // http://domain/apps/files/?dir=/temp/k OR http://domain/f/3333
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Folder *Folder
|
||||
ErrMessage error
|
||||
}
|
||||
|
||||
type CodaApplication struct {
|
||||
ID string `json:"id"`
|
||||
Summary string `json:"summary"`
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@ type Cloud struct {
|
|||
Config domain.CloudConfig
|
||||
}
|
||||
|
||||
type ICloud interface {
|
||||
CreateFolder(name string) Response
|
||||
}
|
||||
|
||||
func NewCloud(conf domain.CloudConfig) *Cloud {
|
||||
|
||||
client := NewClient().
|
||||
|
|
@ -35,13 +31,8 @@ func NewCloud(conf domain.CloudConfig) *Cloud {
|
|||
}
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Folder *domain.Folder
|
||||
ErrMessage error
|
||||
}
|
||||
|
||||
func (c *Cloud) CreateFolder(name string) Response {
|
||||
var R Response
|
||||
func (c *Cloud) CreateFolder(name string) domain.Response {
|
||||
var R domain.Response
|
||||
|
||||
rootDir := c.Config.RootDir
|
||||
user := c.Config.User
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package services
|
||||
|
||||
import "ticket-pimp/internal/domain"
|
||||
|
||||
type DummyTelegram struct {
|
||||
*CommonClient
|
||||
config domain.TelegramConfig
|
||||
}
|
||||
|
||||
type TelegramMessage struct {
|
||||
ChatID string `json:"chat_id"`
|
||||
Text string `json:"text"`
|
||||
DisableNotification bool `json:"disable_notification"`
|
||||
ParseMode string `json:"parse_mode"`
|
||||
DisablePreview bool `json:"disable_web_page_preview"`
|
||||
}
|
||||
|
||||
func (tg *DummyTelegram) DummyNotification(id string, text string) {
|
||||
tg.R().
|
||||
SetBody(&TelegramMessage{
|
||||
ChatID: id,
|
||||
Text: text,
|
||||
DisableNotification: true,
|
||||
ParseMode: "HTML",
|
||||
DisablePreview: true,
|
||||
}).
|
||||
Post("https://api.telegram.org/bot" + tg.config.Token + "/sendMessage")
|
||||
}
|
||||
Loading…
Reference in New Issue