ticket-pimp/internal/controller/control_task.go

154 lines
4.1 KiB
Go

package controller
import (
"context"
"fmt"
"ticket-pimp/internal/domain"
"ticket-pimp/internal/storage/db"
"time"
"github.com/bwmarrin/discordgo"
"github.com/jackc/pgx/v5/pgtype"
)
// 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{
Creator: pgtype.Text{String: t.Creator, Valid: true},
CreatorLink: pgtype.Text{
String: t.CreatorLink,
Valid: true,
},
Description: pgtype.Text{
String: t.Description,
Valid: true,
},
})
if err != nil {
return nil, fmt.Errorf("unable to create task at the db: %v", err)
}
// ------------------------------------------------------------------------------------
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)
}
s, err := discordgo.New("Bot " + wc.conf.Discord.Token)
if err != nil {
return task, fmt.Errorf("unable to create discord session: %v", err)
}
if err := s.Open(); err != nil {
return task, fmt.Errorf("cannot open the session: %v", err)
}
msg := discordgo.MessageSend{
Content: task.DiscordMessage(domain.NewTaskState()),
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",
},
},
},
},
}
th, err := s.ForumThreadStartComplex(
wc.conf.Discord.IsTaskForum,
&discordgo.ThreadStart{
Name: fmt.Sprintf("Task ID: %d, by %s", task.ID, task.Creator),
AppliedTags: []string{wc.conf.Discord.Tags[domain.NewTaskState()]},
},
&msg,
)
if err != nil {
return task, fmt.Errorf("unable to update channel: %v", err)
}
err = wc.UpdateTasksMessageID(context.TODO(), th.ID, task.ID)
if err != nil {
return task, fmt.Errorf("unable to set discord message to task: %v", err)
}
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
}
// UpdateTask
/*
- updates task by message Id
- with an action:
0 for 'in progress' state;
1 for 'done' state;
- and assignee..
*/
func (wc *WorkflowController) UpdateTask(messageId string, opt int, assignee string) (*TaskConvertable, error) {
var (
err error
dbtask db.Task
)
switch opt {
case 0:
dbtask, err = wc.q.StartTask(context.TODO(), db.StartTaskParams{
UpdatedAt: pgtype.Timestamptz{Time: time.Now(), InfinityModifier: 0, Valid: true},
Assignee: pgtype.Text{String: assignee, Valid: true},
Messageid: pgtype.Text{String: messageId, Valid: true},
})
return &TaskConvertable{&dbtask}, err
case 1:
dbtask, err = wc.q.CloseTask(context.TODO(), db.CloseTaskParams{
DeletedAt: pgtype.Timestamptz{Time: time.Now(), InfinityModifier: 0, Valid: true},
Assignee: pgtype.Text{String: assignee, Valid: true},
Messageid: pgtype.Text{String: messageId, Valid: true},
})
return &TaskConvertable{&dbtask}, err
}
return &TaskConvertable{&dbtask}, nil
}