small changes;
This commit is contained in:
parent
f677ec5986
commit
d42b590a14
|
|
@ -8,34 +8,35 @@ import (
|
||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type router struct {
|
type client struct {
|
||||||
Commands []CommandRoute
|
Commands []Command
|
||||||
Components []ComponentRoute
|
Components []Component
|
||||||
Tags []discordgo.ForumTag
|
ListenPostsHandler func(s *discordgo.Session, th *discordgo.ThreadCreate)
|
||||||
|
Tags []discordgo.ForumTag
|
||||||
|
|
||||||
controller controller.WorkflowController
|
controller controller.WorkflowController
|
||||||
conf *domain.DiscordConfig
|
conf *domain.DiscordConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// Подключение роутов к Discord боту
|
// Подключение роутов к Discord боту
|
||||||
func InitRouter(wc controller.WorkflowController, conf *domain.DiscordConfig) *router {
|
func InitRouter(wc controller.WorkflowController, conf *domain.DiscordConfig) *client {
|
||||||
|
|
||||||
var r router
|
var r client
|
||||||
r.Commands = append(r.Commands,
|
|
||||||
// r.CreateRepoHandler(3),
|
|
||||||
// r.CreateFolderHandler(3),
|
|
||||||
r.Ping(),
|
|
||||||
// r.CreateTicketHandler(3),
|
|
||||||
// r.InitProjectFromChannel(3),
|
|
||||||
// r.GetInfo(),
|
|
||||||
r.CreateExternalTask(),
|
|
||||||
)
|
|
||||||
r.Components = append(r.Components,
|
|
||||||
r.StartTask(),
|
|
||||||
r.CloseTask(),
|
|
||||||
)
|
|
||||||
r.controller = wc
|
r.controller = wc
|
||||||
r.conf = conf
|
r.conf = conf
|
||||||
|
|
||||||
|
r.Commands = append(r.Commands,
|
||||||
|
r.CreateRepoHandler(3),
|
||||||
|
r.CreateFolderHandler(3),
|
||||||
|
r.Ping(),
|
||||||
|
r.CreateTicketHandler(3),
|
||||||
|
r.InitProjectFromChannel(3),
|
||||||
|
r.GetInfo(),
|
||||||
|
)
|
||||||
|
r.Components = append(r.Components,
|
||||||
|
r.HandleTaskButtons(),
|
||||||
|
)
|
||||||
|
|
||||||
r.Tags = append(
|
r.Tags = append(
|
||||||
r.Tags,
|
r.Tags,
|
||||||
discordgo.ForumTag{
|
discordgo.ForumTag{
|
||||||
|
|
@ -49,21 +50,25 @@ func InitRouter(wc controller.WorkflowController, conf *domain.DiscordConfig) *r
|
||||||
Moderated: true,
|
Moderated: true,
|
||||||
EmojiName: "✅",
|
EmojiName: "✅",
|
||||||
})
|
})
|
||||||
|
r.ListenPostsHandler = r.ListenPosts
|
||||||
|
|
||||||
return &r
|
return &r
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandRoute struct {
|
//
|
||||||
|
// Подключение роутов к Discord боту
|
||||||
|
|
||||||
|
type Command struct {
|
||||||
Command discordgo.ApplicationCommand
|
Command discordgo.ApplicationCommand
|
||||||
Handler func(s *discordgo.Session, i *discordgo.InteractionCreate)
|
Handler func(s *discordgo.Session, i *discordgo.InteractionCreate)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ComponentRoute struct {
|
type Component struct {
|
||||||
Component discordgo.MessageComponent
|
Component discordgo.MessageComponent
|
||||||
Handler func(s *discordgo.Session, i *discordgo.InteractionCreate)
|
Handler func(s *discordgo.Session, i *discordgo.InteractionCreate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *router) defaultFollowUp(answer string, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
func (h *client) defaultFollowUp(answer string, s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
|
|
||||||
// Sending result:
|
// Sending result:
|
||||||
_, err := s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
_, err := s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
package handler
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"ticket-pimp/internal/domain"
|
|
||||||
)
|
|
||||||
|
|
||||||
type test struct {
|
|
||||||
arg domain.Git
|
|
||||||
expected string
|
|
||||||
}
|
|
||||||
|
|
||||||
var tests = []test{
|
|
||||||
{domain.Git{
|
|
||||||
Name: "text",
|
|
||||||
FullName: "",
|
|
||||||
Private: false,
|
|
||||||
Url: "",
|
|
||||||
CloneUrl: "",
|
|
||||||
HtmlUrl: "https://reddit.com/",
|
|
||||||
SshUrl: "",
|
|
||||||
}, "Repo <a href=\"https://reddit.com/\">text</a> has been created!"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrepareAnswer(t *testing.T) {
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
g := newGit(&test.arg)
|
|
||||||
|
|
||||||
if output := g.PrepareAnswer(); output != test.expected {
|
|
||||||
t.Errorf("Output %q not equal to expected %q", output, test.expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -55,7 +55,7 @@ func run(conf domain.Config) {
|
||||||
go func() {
|
go func() {
|
||||||
opts := discord.DiscordOptions{
|
opts := discord.DiscordOptions{
|
||||||
Controller: controller,
|
Controller: controller,
|
||||||
AppConfig: &conf,
|
Config: &conf,
|
||||||
}
|
}
|
||||||
if err := discord.Run(conf, opts); err != nil {
|
if err := discord.Run(conf, opts); err != nil {
|
||||||
log.Fatalf("discord bot cannot be runned: %v", err)
|
log.Fatalf("discord bot cannot be runned: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,13 @@ func (wc *WorkflowController) createGitForExistingProject(ctx context.Context, r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wc *WorkflowController) CreateGit(ctx context.Context, req GitRequest) *ProjectResponse {
|
func (wc *WorkflowController) CreateGit(ctx context.Context, req GitRequest) *ProjectResponse {
|
||||||
|
if req.ChannelID == "" {
|
||||||
|
return &ProjectResponse{
|
||||||
|
Project: nil,
|
||||||
|
Message: errors.New("empty channel string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// [ ] Валидация на пустой канал?
|
|
||||||
p, err := wc.GetProjectByChannelID(ctx, req.ChannelID)
|
p, err := wc.GetProjectByChannelID(ctx, req.ChannelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ProjectResponse{
|
return &ProjectResponse{
|
||||||
|
|
@ -116,7 +121,6 @@ func (wc *WorkflowController) CreateGit(ctx context.Context, req GitRequest) *Pr
|
||||||
Message: errors.New("build git already exists"),
|
Message: errors.New("build git already exists"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// [x]
|
|
||||||
return wc.createGitForExistingProject(ctx, req, p)
|
return wc.createGitForExistingProject(ctx, req, p)
|
||||||
}
|
}
|
||||||
case p != nil && !req.IsBuildGit:
|
case p != nil && !req.IsBuildGit:
|
||||||
|
|
@ -126,7 +130,6 @@ func (wc *WorkflowController) CreateGit(ctx context.Context, req GitRequest) *Pr
|
||||||
Message: errors.New("project git already exists"),
|
Message: errors.New("project git already exists"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// [x]
|
|
||||||
return wc.createGitForExistingProject(ctx, req, p)
|
return wc.createGitForExistingProject(ctx, req, p)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -86,10 +86,10 @@ func (wc *WorkflowController) GetProjectByChannelID(ctx context.Context, id stri
|
||||||
return &proj, nil
|
return &proj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Saves current channel as project's channel;
|
||||||
func (wc *WorkflowController) InitProjectInChannel(ctx context.Context, channelID string, key string) (*domain.Project, error) {
|
func (wc *WorkflowController) InitProjectInChannel(ctx context.Context, channelID string, key string) (*domain.Project, error) {
|
||||||
dbTicket, err := wc.q.GetTicketByChannelID(ctx, pgtype.Text{String: channelID, Valid: true})
|
dbTicket, err := wc.q.GetTicketByChannelID(ctx, pgtype.Text{String: channelID, Valid: true})
|
||||||
if err == pgx.ErrNoRows {
|
if err == pgx.ErrNoRows {
|
||||||
// [ ] Логика инициализации проекта
|
|
||||||
dbTicket, err = wc.q.CreateTicket(
|
dbTicket, err = wc.q.CreateTicket(
|
||||||
ctx,
|
ctx,
|
||||||
db.CreateTicketParams{
|
db.CreateTicketParams{
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"ticket-pimp/internal/domain"
|
"ticket-pimp/internal/domain"
|
||||||
"ticket-pimp/internal/storage/db"
|
"ticket-pimp/internal/storage/db"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -13,9 +12,14 @@ import (
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (wc *WorkflowController) InitTask(t *domain.Task) (*domain.Task, error) {
|
// WriteTaskToDB
|
||||||
|
/*
|
||||||
// Записываем в базу созданную задачу ------------------------------------------
|
Makes an SQL query to create new tasks row from domain.Task entity
|
||||||
|
- Creator field: telegram nickname or Discord's Mention();
|
||||||
|
- Creator link (tg ID) in telegram case;
|
||||||
|
- Description from telegram/discord message bodies;
|
||||||
|
*/
|
||||||
|
func (wc *WorkflowController) WriteTaskToDB(t *domain.Task) (*domain.Task, error) {
|
||||||
dbtask, err := wc.q.InsertTask(context.TODO(), db.InsertTaskParams{
|
dbtask, err := wc.q.InsertTask(context.TODO(), db.InsertTaskParams{
|
||||||
Creator: pgtype.Text{String: t.Creator, Valid: true},
|
Creator: pgtype.Text{String: t.Creator, Valid: true},
|
||||||
CreatorLink: pgtype.Text{
|
CreatorLink: pgtype.Text{
|
||||||
|
|
@ -33,6 +37,29 @@ func (wc *WorkflowController) InitTask(t *domain.Task) (*domain.Task, error) {
|
||||||
// ------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------
|
||||||
|
|
||||||
task := newConvertable(&dbtask).ExtractDomain()
|
task := newConvertable(&dbtask).ExtractDomain()
|
||||||
|
return task, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitTask
|
||||||
|
/*
|
||||||
|
Runs the following:
|
||||||
|
- Use WriteTaskToDB method to make a new task row in the db;
|
||||||
|
- init new discord bot instance;
|
||||||
|
-
|
||||||
|
|
||||||
|
Possible errors:
|
||||||
|
- db record couldn't be created;
|
||||||
|
- bot couldn't be inited;
|
||||||
|
- bot session couldn't be started;
|
||||||
|
- thread couldn't be started;
|
||||||
|
- first task message couldn't be edited;
|
||||||
|
*/
|
||||||
|
func (wc *WorkflowController) InitTask(t *domain.Task) (*domain.Task, error) {
|
||||||
|
|
||||||
|
task, err := wc.WriteTaskToDB(t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to create task at the db: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Инициализируем новый клиент дискорда
|
// Инициализируем новый клиент дискорда
|
||||||
// [ ] Нездоровое получение параметров клиента из os..
|
// [ ] Нездоровое получение параметров клиента из os..
|
||||||
|
|
@ -44,16 +71,14 @@ func (wc *WorkflowController) InitTask(t *domain.Task) (*domain.Task, error) {
|
||||||
s, err := discordgo.New("Bot " + token)
|
s, err := discordgo.New("Bot " + token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return task, fmt.Errorf("unable to create discord session: %v", err)
|
return task, fmt.Errorf("unable to create discord session: %v", err)
|
||||||
// [ ] Что делать, если не получилось создать задачу?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.Open(); err != nil {
|
if err := s.Open(); err != nil {
|
||||||
return task, fmt.Errorf("cannot open the session: %v", err)
|
return task, fmt.Errorf("cannot open the session: %v", err)
|
||||||
// [ ] Что делать, если не получилось создать задачу?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := discordgo.MessageSend{
|
msg := discordgo.MessageSend{
|
||||||
Content: task.NotStartedMessage(),
|
Content: task.DiscordMessage(domain.NewTaskState()),
|
||||||
Components: []discordgo.MessageComponent{
|
Components: []discordgo.MessageComponent{
|
||||||
discordgo.ActionsRow{
|
discordgo.ActionsRow{
|
||||||
Components: []discordgo.MessageComponent{
|
Components: []discordgo.MessageComponent{
|
||||||
|
|
@ -77,7 +102,7 @@ func (wc *WorkflowController) InitTask(t *domain.Task) (*domain.Task, error) {
|
||||||
th, err := s.ForumThreadStartComplex(
|
th, err := s.ForumThreadStartComplex(
|
||||||
forumChannelID,
|
forumChannelID,
|
||||||
&discordgo.ThreadStart{
|
&discordgo.ThreadStart{
|
||||||
Name: "Task ID:" + strconv.Itoa(int(task.ID)),
|
Name: fmt.Sprintf("Task ID: %d, by %s", task.ID, task.Creator),
|
||||||
},
|
},
|
||||||
&msg,
|
&msg,
|
||||||
)
|
)
|
||||||
|
|
@ -85,10 +110,7 @@ func (wc *WorkflowController) InitTask(t *domain.Task) (*domain.Task, error) {
|
||||||
return task, fmt.Errorf("unable to update channel: %v", err)
|
return task, fmt.Errorf("unable to update channel: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wc.q.UpdateTaskWithMessageID(context.TODO(), db.UpdateTaskWithMessageIDParams{
|
err = wc.UpdateTasksMessageID(context.TODO(), th.ID, task.ID)
|
||||||
Messageid: pgtype.Text{String: th.ID, Valid: true},
|
|
||||||
ID: dbtask.ID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return task, fmt.Errorf("unable to set discord message to task: %v", err)
|
return task, fmt.Errorf("unable to set discord message to task: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +118,14 @@ func (wc *WorkflowController) InitTask(t *domain.Task) (*domain.Task, error) {
|
||||||
return task, nil
|
return task, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (wc *WorkflowController) UpdateTasksMessageID(ctx context.Context, msgID string, taskID int32) error {
|
||||||
|
err := wc.q.UpdateTaskWithMessageID(context.TODO(), db.UpdateTaskWithMessageIDParams{
|
||||||
|
Messageid: pgtype.Text{String: msgID, Valid: true},
|
||||||
|
ID: taskID,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (wc *WorkflowController) UpdateTask(id string, opt int, user string) (*TaskConvertable, error) {
|
func (wc *WorkflowController) UpdateTask(id string, opt int, user string) (*TaskConvertable, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,13 @@ import (
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FullProjectInit
|
||||||
|
/*
|
||||||
|
Deprecated method to create a project with all related data:
|
||||||
|
- git;
|
||||||
|
- git for the project's build;
|
||||||
|
- cloud folder;
|
||||||
|
*/
|
||||||
func (wc *WorkflowController) FullProjectInit(name, key, id string) (string, error) {
|
func (wc *WorkflowController) FullProjectInit(name, key, id string) (string, error) {
|
||||||
|
|
||||||
appKey := fmt.Sprintf("%s-%s", key, id)
|
appKey := fmt.Sprintf("%s-%s", key, id)
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ type TelegramConfig struct {
|
||||||
type DiscordConfig struct {
|
type DiscordConfig struct {
|
||||||
Token string
|
Token string
|
||||||
IsProjectChannel string
|
IsProjectChannel string
|
||||||
|
IsTaskForum string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplicationConfig struct {
|
type ApplicationConfig struct {
|
||||||
|
|
@ -95,6 +96,7 @@ func InitConfig(envFilePath string) Config {
|
||||||
Discord: DiscordConfig{
|
Discord: DiscordConfig{
|
||||||
Token: os.Getenv("DISCORD_TOKEN"),
|
Token: os.Getenv("DISCORD_TOKEN"),
|
||||||
IsProjectChannel: os.Getenv("PROJECTS_CHANNEL_GROUP"),
|
IsProjectChannel: os.Getenv("PROJECTS_CHANNEL_GROUP"),
|
||||||
|
IsTaskForum: os.Getenv("TASKS_CHANNEL"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,38 +69,52 @@ type Task struct {
|
||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) NotStartedMessage() string {
|
type TaskState int
|
||||||
|
|
||||||
return fmt.Sprintf(
|
const (
|
||||||
"## TaskID: %d\nCreated by: %s\n>>> %s\n",
|
new TaskState = iota
|
||||||
t.ID,
|
inprogress
|
||||||
t.Creator,
|
done
|
||||||
t.Description,
|
)
|
||||||
)
|
|
||||||
|
func NewTaskState() TaskState {
|
||||||
|
return TaskState(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) StartedMessage() string {
|
func InrpogressTaskState() TaskState {
|
||||||
|
return TaskState(1)
|
||||||
return fmt.Sprintf(
|
|
||||||
"## TaskID: %d\nCreated by: %s\n Assignee: %s\n🚀 Started at: %s\n>>> %s\n",
|
|
||||||
t.ID,
|
|
||||||
t.Creator,
|
|
||||||
t.Assignee,
|
|
||||||
t.UpdatedAt,
|
|
||||||
t.Description,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) ClosedMessage() string {
|
func DoneTaskState() TaskState {
|
||||||
|
return TaskState(2)
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(
|
// Creates a string for discordgo.DiscordMessage.Content
|
||||||
"## TaskID: %d\nCreated by: %s\n Assignee: %s\n✅ Closed at: %s\n>>> %s\n",
|
// State: New task;
|
||||||
t.ID,
|
func (t *Task) DiscordMessage(ts TaskState) string {
|
||||||
t.Creator,
|
switch ts {
|
||||||
t.Assignee,
|
case new:
|
||||||
t.DeletedAt,
|
return fmt.Sprintf(
|
||||||
t.Description,
|
"Created at: %s \n>>> %s\n",
|
||||||
)
|
t.CreatedAt,
|
||||||
|
t.Description,
|
||||||
|
)
|
||||||
|
case inprogress:
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"**TaskID: %d** Started by: %s\n🚀 Started at: %s\n",
|
||||||
|
t.ID,
|
||||||
|
t.Assignee,
|
||||||
|
t.UpdatedAt,
|
||||||
|
)
|
||||||
|
case done:
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"**TaskID: %d** Closed by: %s\n✅ Closed at: %s\n",
|
||||||
|
t.ID,
|
||||||
|
t.Assignee,
|
||||||
|
t.DeletedAt,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return "task state not provided"
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTask(summ, desc, c, cLink string) *Task {
|
func NewTask(summ, desc, c, cLink string) *Task {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue