From 19f6064066fec1561626bd3786453eb8eede5e3e Mon Sep 17 00:00:00 2001 From: naudachu Date: Sat, 25 Nov 2023 20:19:40 +0500 Subject: [PATCH] - finished coda usage --- .gitignore | 4 +- adapters/adapters.go | 2 +- client/discord/discord.go | 39 +++++++++++---- client/discord/discord_handler/common.go | 17 ++++--- client/telegram/telegram.go | 8 ++-- cmd/main.go | 44 ++++++++--------- internal/controller/control_coda.go | 27 +++++++++++ internal/controller/control_project.go | 24 +++++----- internal/controller/control_task.go | 2 +- internal/controller/controller.go | 2 +- internal/domain/config.go | 1 + internal/domain/models.go | 12 +++++ internal/domain/telegram.go | 7 --- internal/{services => external}/client.go | 2 +- internal/{services => external}/cloud.go | 2 +- internal/{services => external}/coda.go | 47 +++++++++++++++++-- .../{services => external}/dummy_telegram.go | 2 +- internal/{services => external}/git.go | 2 +- 18 files changed, 170 insertions(+), 74 deletions(-) create mode 100644 internal/controller/control_coda.go delete mode 100644 internal/domain/telegram.go rename internal/{services => external}/client.go (97%) rename internal/{services => external}/cloud.go (99%) rename internal/{services => external}/coda.go (70%) rename internal/{services => external}/dummy_telegram.go (98%) rename internal/{services => external}/git.go (99%) diff --git a/.gitignore b/.gitignore index 22ed4fe..622605e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .vscode/ +.idea/ +.github +docker/ **/**/*.env -docker/** \ No newline at end of file diff --git a/adapters/adapters.go b/adapters/adapters.go index 84d0181..44da1e6 100644 --- a/adapters/adapters.go +++ b/adapters/adapters.go @@ -16,7 +16,7 @@ type ICloud interface { type ICoda interface { ListDocs() - CreateApp(task domain.CodaApplication) + CreateApp(task domain.CodaApplication) (string, error) CreateTask(title string, desc string, creatorName string, creatorID string) (string, error) GetRowLink(id string) (string, error) } diff --git a/client/discord/discord.go b/client/discord/discord.go index c4ff776..aab5fde 100644 --- a/client/discord/discord.go +++ b/client/discord/discord.go @@ -9,7 +9,7 @@ import ( "ticket-pimp/internal/controller" "ticket-pimp/internal/domain" - "ticket-pimp/internal/services" + "ticket-pimp/internal/external" "github.com/bwmarrin/discordgo" ) @@ -42,6 +42,10 @@ var ( 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", @@ -166,7 +170,7 @@ func isRejected(s *discordgo.Session, i *discordgo.InteractionCreate) bool { } func route(s *discordgo.Session, i *discordgo.InteractionCreate, h discord_handler.Handler) { - initialResponse(s, i) + // initialResponse(s, i) if isRejected(s, i) { return @@ -175,9 +179,8 @@ func route(s *discordgo.Session, i *discordgo.InteractionCreate, h discord_handl // Определяем тип взаимодействия и хэндлим правильной функцией: switch i.Type { case discordgo.InteractionApplicationCommand: - cmd := i.ApplicationCommandData().Name - switch cmd { + switch i.ApplicationCommandData().Name { case "ping": h.Ping(s, i) case "project": @@ -190,10 +193,13 @@ func route(s *discordgo.Session, i *discordgo.InteractionCreate, h discord_handl h.CreateFolder(s, i) case "init_project": h.InitChannelAsProject(s, i) + case "coda_ticket": + h.CreateCoda(s, i) } + case discordgo.InteractionMessageComponent: - c := i.MessageComponentData().CustomID - switch c { + + switch i.MessageComponentData().CustomID { case "task_start": h.HandleTaskButtons(s, i) case "task_close": @@ -221,10 +227,11 @@ func updateForum(conf *domain.Config, s *discordgo.Session) ([]discordgo.ForumTa // Result tags array tags := forum.AvailableTags - // Check if preset tag exists into current channel + // 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]) } } @@ -241,6 +248,22 @@ func updateForum(conf *domain.Config, s *discordgo.Session) ([]discordgo.ForumTa 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 } @@ -267,7 +290,7 @@ func Run(conf *domain.Config, opts DiscordOptions) error { h := discord_handler.New( opts.Controller, &conf.Discord, - services.NewDummyClient(conf.Telegram), + external.NewDummyClient(conf.Telegram), ) // Add posts listener diff --git a/client/discord/discord_handler/common.go b/client/discord/discord_handler/common.go index 99d52d0..3519c1f 100644 --- a/client/discord/discord_handler/common.go +++ b/client/discord/discord_handler/common.go @@ -1,24 +1,23 @@ package discord_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{ + /*_, 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 - } + // if err != nil { + // s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{ + // Content: fmt.Sprintf("Something went wrong: %v", err), + // }) + // return + // } } // setFlag diff --git a/client/telegram/telegram.go b/client/telegram/telegram.go index 6f81531..5e71200 100644 --- a/client/telegram/telegram.go +++ b/client/telegram/telegram.go @@ -6,16 +6,16 @@ import ( "ticket-pimp/client/telegram/telegram_handler" "ticket-pimp/internal/controller" "ticket-pimp/internal/domain" - "ticket-pimp/internal/services" + "ticket-pimp/internal/external" "github.com/mr-linch/go-tg" "github.com/mr-linch/go-tg/tgb" ) type TelegramOptions struct { - GitService *services.Git - CloudService *services.Cloud - Coda *services.Coda + GitService *external.Git + CloudService *external.Cloud + Coda *external.Coda AppConfig *domain.Config Controller *controller.WorkflowController } diff --git a/cmd/main.go b/cmd/main.go index a9f5072..0a9e9d9 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -11,7 +11,7 @@ import ( "ticket-pimp/internal/controller" "ticket-pimp/internal/domain" - "ticket-pimp/internal/services" + "ticket-pimp/internal/external" "ticket-pimp/client/discord" "ticket-pimp/client/telegram" @@ -59,7 +59,7 @@ func Go(ctx context.Context, fns ...func(context.Context) error) error { } func applyMigrations(connString string) { - // Aply migrations: + // Apply migrations: dbConnConfig, err := pgxpool.ParseConfig(connString) if err != nil { @@ -79,17 +79,20 @@ func applyMigrations(connString string) { } fmt.Printf("Applied %d migrations!\n", n) - db.Close() + err = db.Close() + if err != nil { + log.Fatal("unable to close db connection") + } } -func run(conf *domain.Config) { +func run(c *domain.Config) { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill, syscall.SIGTERM) defer cancel() // -- DB connection init -- START connString := fmt.Sprintf( "postgresql://%s:%s@%s:%s/%s", - conf.DB.User, conf.DB.Pass, conf.DB.Host, conf.DB.Port, conf.DB.Name, + c.DB.User, c.DB.Pass, c.DB.Host, c.DB.Port, c.DB.Name, ) conn, err := pgxpool.New( ctx, @@ -97,42 +100,41 @@ func run(conf *domain.Config) { if err != nil { log.Fatalf("DB connection failed: %v", err) } - // -- DB connection init -- END - // Aply migrations: + // Apply migrations: applyMigrations(connString) // Init services instances: - gitService := services.NewGit(conf.Git) - cloudService := services.NewCloud(conf.Cloud) - codaService := services.NewCodaClient(conf.Coda) + git := external.NewGit(c.Git) + cloud := external.NewCloud(c.Cloud) + coda := external.NewCoda(c.Coda) // Controller instance init: - controller := controller.NewWorkflowController( - gitService, - cloudService, - codaService, + controller := controller.NewApp( + git, + cloud, + coda, conn, - conf, + c, ) Go(ctx, func(ctx context.Context) error { opts := discord.DiscordOptions{ Controller: controller, - Config: conf, + Config: c, } - if err := discord.Run(conf, opts); err != nil { + if err := discord.Run(c, opts); err != nil { return errors.Errorf("discord bot cannot be runned: %v", err) } return nil }, func(ctx context.Context) error { opts := telegram.TelegramOptions{ - GitService: gitService, - CloudService: cloudService, - Coda: codaService, - AppConfig: conf, + GitService: git, + CloudService: cloud, + Coda: coda, + AppConfig: c, Controller: controller, } diff --git a/internal/controller/control_coda.go b/internal/controller/control_coda.go new file mode 100644 index 0000000..b0798ed --- /dev/null +++ b/internal/controller/control_coda.go @@ -0,0 +1,27 @@ +package controller + +import ( + "context" + "fmt" + "ticket-pimp/internal/domain" +) + +func (wc *WorkflowController) CreateCoda(guildID string, chanID string) (string, error) { + + p, err := wc.GetProjectByChannelID(context.TODO(), chanID) + if err != nil { + return "", err + } + + requestResult, err := wc.ICoda.CreateApp(domain.CodaApplication{ + ID: p.Key, + Summary: p.Name, + URL: fmt.Sprintf("https://discord.com/channels/%s/%s", guildID, chanID), + Git: p.ProjectGit, + GitBuild: p.BuildGit, + Folder: p.Folder, + }) + + return requestResult, err + +} diff --git a/internal/controller/control_project.go b/internal/controller/control_project.go index b7692d2..0242846 100644 --- a/internal/controller/control_project.go +++ b/internal/controller/control_project.go @@ -3,6 +3,7 @@ package controller import ( "context" "fmt" + "strconv" "ticket-pimp/internal/domain" "ticket-pimp/internal/storage/db" @@ -67,25 +68,24 @@ func (wc *WorkflowController) ProjectCreate(ctx context.Context, project domain. } func (wc *WorkflowController) GetProjectByChannelID(ctx context.Context, id string) (*domain.Project, error) { - var proj domain.Project + dbTicket, err := wc.q.GetTicketByChannelID(ctx, pgtype.Text{String: id, Valid: true}) if err != nil { if err == pgx.ErrNoRows { return nil, nil } return nil, err - } else { - proj = domain.Project{ - ID: string(dbTicket.ID), - Key: dbTicket.Key.String, - Name: dbTicket.Key.String, - ChannelID: dbTicket.Channelid.String, - ProjectGit: dbTicket.ProjectGit.String, - BuildGit: dbTicket.BuildGit.String, - Folder: dbTicket.Folder.String, - } } - return &proj, nil + + return &domain.Project{ + ID: strconv.Itoa(int(dbTicket.ID)), + Key: dbTicket.Key.String, + Name: dbTicket.Title.String, + ChannelID: dbTicket.Channelid.String, + ProjectGit: dbTicket.ProjectGit.String, + BuildGit: dbTicket.BuildGit.String, + Folder: dbTicket.Folder.String, + }, nil } // Saves current channel as project's channel; diff --git a/internal/controller/control_task.go b/internal/controller/control_task.go index 3b4ae14..345ee28 100644 --- a/internal/controller/control_task.go +++ b/internal/controller/control_task.go @@ -94,7 +94,7 @@ func (wc *WorkflowController) InitTask(t *domain.Task) (*domain.Task, error) { wc.conf.Discord.IsTaskForum, &discordgo.ThreadStart{ Name: fmt.Sprintf("Task ID: %d, by %s", task.ID, task.Creator), - AppliedTags: []string{"Не начат"}, + AppliedTags: []string{wc.conf.Discord.Tags[domain.NewTaskState()]}, }, &msg, ) diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 14f5515..0d3bb7b 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -17,7 +17,7 @@ type WorkflowController struct { conf *domain.Config } -func NewWorkflowController( +func NewApp( git adapters.IGit, cloud adapters.ICloud, coda adapters.ICoda, diff --git a/internal/domain/config.go b/internal/domain/config.go index 9afd2d6..ef31927 100644 --- a/internal/domain/config.go +++ b/internal/domain/config.go @@ -53,6 +53,7 @@ type DiscordConfig struct { Token string IsProjectChannel string IsTaskForum string + Tags map[TaskState]string } type ApplicationConfig struct { diff --git a/internal/domain/models.go b/internal/domain/models.go index 3cef45d..cc0201b 100644 --- a/internal/domain/models.go +++ b/internal/domain/models.go @@ -83,6 +83,18 @@ const ( done ) +func State(i int) TaskState { + switch i { + case 0: + return new + case 1: + return inprogress + case 2: + return done + } + return -1 +} + func NewTaskState() TaskState { return TaskState(0) } diff --git a/internal/domain/telegram.go b/internal/domain/telegram.go deleted file mode 100644 index 11cbaa3..0000000 --- a/internal/domain/telegram.go +++ /dev/null @@ -1,7 +0,0 @@ -package domain - -type TgUser struct { - ID string - Name string - TgLink string -} diff --git a/internal/services/client.go b/internal/external/client.go similarity index 97% rename from internal/services/client.go rename to internal/external/client.go index 8d56dcd..c51f56a 100644 --- a/internal/services/client.go +++ b/internal/external/client.go @@ -1,4 +1,4 @@ -package services +package external import ( "fmt" diff --git a/internal/services/cloud.go b/internal/external/cloud.go similarity index 99% rename from internal/services/cloud.go rename to internal/external/cloud.go index b4f1692..152e43d 100644 --- a/internal/services/cloud.go +++ b/internal/external/cloud.go @@ -1,4 +1,4 @@ -package services +package external import ( "errors" diff --git a/internal/services/coda.go b/internal/external/coda.go similarity index 70% rename from internal/services/coda.go rename to internal/external/coda.go index 3cf1c5a..6d04afe 100644 --- a/internal/services/coda.go +++ b/internal/external/coda.go @@ -1,8 +1,10 @@ -package services +package external import ( + "errors" "fmt" "log" + "strings" "ticket-pimp/internal/domain" "time" @@ -14,7 +16,7 @@ type Coda struct { Config domain.CodaConfig } -func NewCodaClient(conf domain.CodaConfig) *Coda { +func NewCoda(conf domain.CodaConfig) *Coda { client := NewClient(). SetTimeout(15 * time.Second). @@ -47,14 +49,49 @@ func (c *Coda) ListDocs() { log.Print(resp) } -func (c *Coda) CreateApp(task domain.CodaApplication) { - resp, _ := c.R(). +type CodaWebhookResponse struct { + ReqID string `json:"requestId"` +} + +func (c *Coda) CreateApp(task domain.CodaApplication) (string, error) { + + var whResponse CodaWebhookResponse + c.R(). SetBody(task). SetContentType("application/json"). + SetSuccessResult(&whResponse). SetBearerAuthToken(c.Config.Develop). Post("/docs/Ic3IZpQ3Wk/hooks/automation/grid-auto-NlUwM7F7Cr") - fmt.Print(resp) + if whResponse.ReqID == "" { + return "", errors.New("coda responded w/o mutate id") + } + + var ( + // mutate string + sep string = ":" + ) + + if !strings.Contains(whResponse.ReqID, sep) { + return "", fmt.Errorf("unexpected coda response: %s", whResponse.ReqID) + } + + // arr := strings.Split(whResponse.ReqID, sep) + // if arr[0] == "mutate" { + // mutate = arr[1] + // } + + // mutateResponse, err := c.R(). + // SetContentType("application/json"). + // SetBearerAuthToken(c.Config.Develop). + // Get(fmt.Sprintf("/mutationStatus/%s", mutate)) + + // if err != nil { + // return "", fmt.Errorf("unable to get coda mutate result: %s", mutate) + // } + + // _ = mutateResponse + return whResponse.ReqID, nil } func (c *Coda) CreateTask(title string, desc string, creatorName string, creatorID string) (string, error) { diff --git a/internal/services/dummy_telegram.go b/internal/external/dummy_telegram.go similarity index 98% rename from internal/services/dummy_telegram.go rename to internal/external/dummy_telegram.go index 79ace7e..867a311 100644 --- a/internal/services/dummy_telegram.go +++ b/internal/external/dummy_telegram.go @@ -1,4 +1,4 @@ -package services +package external import ( "ticket-pimp/internal/domain" diff --git a/internal/services/git.go b/internal/external/git.go similarity index 99% rename from internal/services/git.go rename to internal/external/git.go index 4671cc6..8bf4aa3 100644 --- a/internal/services/git.go +++ b/internal/external/git.go @@ -1,4 +1,4 @@ -package services +package external import ( "fmt"