Merge branch 'instant-reply' into discord-bot-integration
This commit is contained in:
commit
b5f798ad8e
|
|
@ -7,7 +7,6 @@ RUN apk add git
|
|||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install -ldflags '-extldflags "-static"' -tags timetzdata ./cmd/main.go
|
||||
|
||||
FROM scratch
|
||||
# the test program:
|
||||
COPY --from=app-builder /go/bin/main /ticket-pimp
|
||||
COPY --from=app-builder /go/src/ticket-pimp/cmd/prod.env /
|
||||
# the tls certificates:
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ func run(conf domain.Config) {
|
|||
}
|
||||
}()
|
||||
|
||||
// go func() {
|
||||
opts := telegram.TelegramOptions{
|
||||
// TicketsRepo: db,
|
||||
GitService: gitService,
|
||||
|
|
@ -75,6 +74,4 @@ func run(conf domain.Config) {
|
|||
log.Fatalf("telegram bot cannot be runned: %v", err)
|
||||
defer os.Exit(1)
|
||||
}
|
||||
// }()
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ import (
|
|||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func initBotWith(token string) (*discordgo.Session, error) {
|
||||
func initBotWith(token string) *discordgo.Session {
|
||||
discord, err := discordgo.New("Bot " + token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.Fatalf("unable to create discord session: %v", err)
|
||||
}
|
||||
return discord, nil
|
||||
return discord
|
||||
}
|
||||
|
||||
type DiscordOptions struct {
|
||||
|
|
@ -28,10 +28,7 @@ type DiscordOptions struct {
|
|||
func Run(conf domain.Config, opts DiscordOptions) error {
|
||||
token := conf.Discord.Token
|
||||
|
||||
session, err := initBotWith(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
session := initBotWith(token)
|
||||
|
||||
router := handler.InitRouter(*opts.Controller)
|
||||
|
||||
|
|
@ -41,7 +38,6 @@ func Run(conf domain.Config, opts DiscordOptions) error {
|
|||
}
|
||||
|
||||
session.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
|
||||
if h, ok := commandHandlers[i.ApplicationCommandData().Name]; ok {
|
||||
h(s, i)
|
||||
}
|
||||
|
|
@ -73,7 +69,7 @@ func Run(conf domain.Config, opts DiscordOptions) error {
|
|||
|
||||
log.Println("Removing commands...")
|
||||
for _, h := range cmds {
|
||||
err = session.ApplicationCommandDelete(session.State.User.ID, "", h.ID)
|
||||
err := session.ApplicationCommandDelete(session.State.User.ID, "", h.ID)
|
||||
if err != nil {
|
||||
log.Panicf("Cannot delete '%v' command: %v", h.Name, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"ticket-pimp/internal/controller"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
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 folder's name",
|
||||
Required: false,
|
||||
MinLength: &nameMinLenght,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Handler: func(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 = "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 == strconv.Itoa(1150719794853716028) {
|
||||
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 = fmt.Sprintf(
|
||||
"## Project info:\n🔑 key: %s\n📂 folder: %s\n👾 project git: %s\n🚀 build git: %s\n\nErrors: %v",
|
||||
resp.Project.ShortName,
|
||||
resp.Project.Cloud,
|
||||
resp.Project.ProjectGit,
|
||||
resp.Project.BuildGit,
|
||||
resp.Message,
|
||||
)
|
||||
}
|
||||
|
||||
// Sending result:
|
||||
_, err = s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||
Content: result,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||
Content: fmt.Sprintf("Something went wrong: %v", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"ticket-pimp/internal/controller"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func (h *router) CreateRepoHandler(repoNameMinLength int) route {
|
||||
const (
|
||||
repoType = "repo_type"
|
||||
projectRepo = "project_repo"
|
||||
buildRepo = "build_repo"
|
||||
nameOption = "repo_name"
|
||||
)
|
||||
|
||||
return route{
|
||||
Command: discordgo.ApplicationCommand{
|
||||
Name: "repo",
|
||||
Description: "Command for repository creation",
|
||||
Options: []*discordgo.ApplicationCommandOption{
|
||||
{
|
||||
Type: discordgo.ApplicationCommandOptionString,
|
||||
Name: repoType,
|
||||
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: nameOption,
|
||||
Description: "Type the repository's name",
|
||||
Required: false,
|
||||
MinLength: &repoNameMinLength,
|
||||
},
|
||||
},
|
||||
},
|
||||
Handler: func(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 = "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 == strconv.Itoa(1150719794853716028) {
|
||||
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 {
|
||||
result = resp.Message.Error()
|
||||
} else {
|
||||
result = fmt.Sprintf(
|
||||
"## Project info:\n🔑 key: %s\n📂 folder: %s\n👾 project git: %s\n🚀 build git: %s\n\nErrors: %v",
|
||||
resp.Project.ShortName,
|
||||
resp.Project.Cloud,
|
||||
resp.Project.ProjectGit,
|
||||
resp.Project.BuildGit,
|
||||
resp.Message,
|
||||
)
|
||||
}
|
||||
// Sending result:
|
||||
_, err = s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||
Content: result,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
s.FollowupMessageCreate(i.Interaction, true, &discordgo.WebhookParams{
|
||||
Content: fmt.Sprintf("Something went wrong: %v", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func (h *router) Ping() route {
|
||||
return route{
|
||||
Command: discordgo.ApplicationCommand{
|
||||
Name: "ping",
|
||||
Description: "pongs in a reply",
|
||||
},
|
||||
Handler: func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
log.Println("ok, I'm here..")
|
||||
|
||||
err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: "`pong`",
|
||||
Title: "Pong reply",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"ticket-pimp/internal/domain"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
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,
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,7 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"ticket-pimp/internal/controller"
|
||||
"ticket-pimp/internal/domain"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
|
@ -21,10 +17,10 @@ func InitRouter(wc controller.WorkflowController) *router {
|
|||
var r router
|
||||
r.Routes = append(
|
||||
r.Routes,
|
||||
// r.CreateRepoHandler(3),
|
||||
r.CreateRepoHandler(3),
|
||||
r.CreateFolderHandler(3),
|
||||
r.Ping(),
|
||||
// r.CreateTicketHandler(3),
|
||||
r.CreateTicketHandler(3),
|
||||
)
|
||||
r.controller = wc
|
||||
|
||||
|
|
@ -35,284 +31,3 @@ type route struct {
|
|||
Command discordgo.ApplicationCommand
|
||||
Handler func(s *discordgo.Session, i *discordgo.InteractionCreate)
|
||||
}
|
||||
|
||||
func (h *router) Ping() route {
|
||||
return route{
|
||||
Command: discordgo.ApplicationCommand{
|
||||
Name: "ping",
|
||||
Description: "pongs in a reply",
|
||||
},
|
||||
Handler: func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
log.Println("ok, I'm here..")
|
||||
|
||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseDeferredMessageUpdate,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: "`pong`",
|
||||
Title: "Pong reply",
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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 folder's name",
|
||||
Required: false,
|
||||
MinLength: &nameMinLenght,
|
||||
},
|
||||
},
|
||||
},
|
||||
Handler: func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
var result string
|
||||
|
||||
resp := discordgo.InteractionResponse{
|
||||
|
||||
Type: discordgo.InteractionResponseUpdateMessage,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: "Folder is going to be created..",
|
||||
},
|
||||
}
|
||||
err := s.InteractionRespond(i.Interaction, &resp)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
options := i.ApplicationCommandData().Options
|
||||
|
||||
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 = fmt.Sprint(f.PrivateURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resp = discordgo.InteractionResponse{
|
||||
// // Ignore type for now, they will be discussed in "responses"
|
||||
// Type: discordgo.InteractionResponseUpdateMessage,
|
||||
// Data: &discordgo.InteractionResponseData{
|
||||
// Content: result,
|
||||
// Title: "📂 Folder was created",
|
||||
// },
|
||||
// }
|
||||
|
||||
webhookEdit := discordgo.WebhookEdit{
|
||||
Content: &result,
|
||||
}
|
||||
s.InteractionResponseEdit(i.Interaction, &webhookEdit)
|
||||
|
||||
// discerr := s.InteractionRespond(i.Interaction, &resp)
|
||||
// if discerr != nil {
|
||||
// log.Println(discerr)
|
||||
// }
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp := &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: result,
|
||||
},
|
||||
}
|
||||
|
||||
s.InteractionRespond(i.Interaction, resp)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"ticket-pimp/internal/domain"
|
||||
"ticket-pimp/internal/storage/db"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type FolderRequest struct {
|
||||
ChannelID string
|
||||
InsertedName string
|
||||
}
|
||||
|
||||
func (wc *WorkflowController) CreateFolder(ctx context.Context, req FolderRequest) *ProjectResponse {
|
||||
|
||||
project, err := wc.GetProjectByChannelID(ctx, req.ChannelID)
|
||||
if err != nil {
|
||||
return &ProjectResponse{
|
||||
Project: nil,
|
||||
Message: fmt.Errorf("unable to retrieve project from db: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
name string
|
||||
dbticket db.Ticket
|
||||
result ProjectResponse
|
||||
)
|
||||
|
||||
if project != nil {
|
||||
switch {
|
||||
case project.Cloud != "":
|
||||
return &ProjectResponse{
|
||||
Project: project,
|
||||
Message: nil,
|
||||
}
|
||||
case project.ShortName != "":
|
||||
name = project.ShortName
|
||||
case req.InsertedName != "":
|
||||
name = req.InsertedName
|
||||
}
|
||||
response := wc.ICloud.CreateFolder(name)
|
||||
|
||||
dbticket, err = wc.q.UpdateTicketFolder(
|
||||
ctx,
|
||||
db.UpdateTicketFolderParams{
|
||||
Folder: pgtype.Text{String: response.Folder.PrivateURL, Valid: true},
|
||||
UpdatedAt: pgtype.Timestamptz{Time: time.Now(), InfinityModifier: 0, Valid: true},
|
||||
Channelid: pgtype.Text{String: req.ChannelID, Valid: true},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("unable to scan row from db: %v", err)
|
||||
return &ProjectResponse{
|
||||
Project: project,
|
||||
Message: fmt.Errorf("unable to update project: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
result = ProjectResponse{
|
||||
Project: &domain.Project{
|
||||
ID: string(dbticket.ID),
|
||||
ShortName: dbticket.Key.String,
|
||||
ChannelID: dbticket.Channelid.String,
|
||||
ProjectGit: dbticket.ProjectGit.String,
|
||||
BuildGit: dbticket.BuildGit.String,
|
||||
Cloud: dbticket.Folder.String,
|
||||
},
|
||||
Message: response.ErrMessage,
|
||||
}
|
||||
} else {
|
||||
if req.InsertedName != "" {
|
||||
response := wc.ICloud.CreateFolder(req.InsertedName)
|
||||
result = ProjectResponse{
|
||||
Project: &domain.Project{
|
||||
Cloud: response.Folder.PrivateURL,
|
||||
},
|
||||
Message: response.ErrMessage,
|
||||
}
|
||||
} else {
|
||||
return &ProjectResponse{
|
||||
Project: nil,
|
||||
Message: errors.New("передано пустое имя"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &result
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"ticket-pimp/internal/domain"
|
||||
"ticket-pimp/internal/storage/db"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type GitRequest struct {
|
||||
ChannelID string
|
||||
InsertedName string
|
||||
IsBuildGit bool
|
||||
}
|
||||
|
||||
func (wc *WorkflowController) createGitForExistingProject(ctx context.Context, req GitRequest, p *domain.Project) *ProjectResponse {
|
||||
var (
|
||||
name string = ""
|
||||
dbticket db.Ticket
|
||||
)
|
||||
switch {
|
||||
case p.ShortName != "":
|
||||
name = p.ShortName
|
||||
if req.IsBuildGit {
|
||||
name += "-build"
|
||||
}
|
||||
case req.InsertedName != "":
|
||||
name = req.InsertedName
|
||||
if req.IsBuildGit {
|
||||
name += "-build"
|
||||
}
|
||||
}
|
||||
|
||||
// response := wc.ICloud.CreateFolder(name)
|
||||
git, err := wc.IGit.CreateRepo(name)
|
||||
if err != nil {
|
||||
return &ProjectResponse{
|
||||
Project: p,
|
||||
Message: fmt.Errorf("unable to create git w/ an error: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
if req.IsBuildGit {
|
||||
dbticket, err = wc.q.UpdateTicketBuildGit(
|
||||
ctx,
|
||||
db.UpdateTicketBuildGitParams{
|
||||
BuildGit: pgtype.Text{String: git.HtmlUrl, Valid: true},
|
||||
UpdatedAt: pgtype.Timestamptz{Time: time.Now(), InfinityModifier: 0, Valid: true},
|
||||
Channelid: pgtype.Text{String: req.ChannelID, Valid: true},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("unable to scan row from db: %v", err)
|
||||
return &ProjectResponse{
|
||||
Project: p,
|
||||
Message: fmt.Errorf("unable to update project: %v", err),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dbticket, err = wc.q.UpdateTicketProjectGit(
|
||||
ctx,
|
||||
db.UpdateTicketProjectGitParams{
|
||||
ProjectGit: pgtype.Text{String: git.HtmlUrl, Valid: true},
|
||||
UpdatedAt: pgtype.Timestamptz{Time: time.Now(), InfinityModifier: 0, Valid: true},
|
||||
Channelid: pgtype.Text{String: req.ChannelID, Valid: true},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("unable to scan row from db: %v", err)
|
||||
return &ProjectResponse{
|
||||
Project: p,
|
||||
Message: fmt.Errorf("unable to update project: %v", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &ProjectResponse{
|
||||
Project: &domain.Project{
|
||||
ID: string(dbticket.ID),
|
||||
ShortName: dbticket.Key.String,
|
||||
ChannelID: dbticket.Channelid.String,
|
||||
ProjectGit: dbticket.ProjectGit.String,
|
||||
BuildGit: dbticket.BuildGit.String,
|
||||
Cloud: dbticket.Folder.String,
|
||||
},
|
||||
Message: err,
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *WorkflowController) CreateGit(ctx context.Context, req GitRequest) *ProjectResponse {
|
||||
|
||||
// [ ] Валидация на пустой канал?
|
||||
p, err := wc.GetProjectByChannelID(ctx, req.ChannelID)
|
||||
if err != nil {
|
||||
return &ProjectResponse{
|
||||
Project: nil,
|
||||
Message: fmt.Errorf("unable to retrieve project from db: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
// var (
|
||||
// name string
|
||||
// dbticket db.Ticket
|
||||
// result ProjectResponse
|
||||
// )
|
||||
|
||||
switch {
|
||||
case p != nil && req.IsBuildGit:
|
||||
if p.BuildGit != "" {
|
||||
return &ProjectResponse{
|
||||
Project: p,
|
||||
Message: errors.New("build git already exists"),
|
||||
}
|
||||
} else {
|
||||
// [x]
|
||||
return wc.createGitForExistingProject(ctx, req, p)
|
||||
}
|
||||
case p != nil && !req.IsBuildGit:
|
||||
if p.ProjectGit != "" {
|
||||
return &ProjectResponse{
|
||||
Project: p,
|
||||
Message: errors.New("project git already exists"),
|
||||
}
|
||||
} else {
|
||||
// [x]
|
||||
return wc.createGitForExistingProject(ctx, req, p)
|
||||
}
|
||||
default:
|
||||
if req.InsertedName != "" {
|
||||
|
||||
if req.IsBuildGit {
|
||||
req.InsertedName += "-build"
|
||||
}
|
||||
|
||||
git, err := wc.IGit.CreateRepo(req.InsertedName)
|
||||
if err != nil || git == nil {
|
||||
return &ProjectResponse{
|
||||
Project: nil,
|
||||
Message: err,
|
||||
}
|
||||
} else {
|
||||
if req.IsBuildGit {
|
||||
return &ProjectResponse{
|
||||
Project: &domain.Project{
|
||||
BuildGit: git.HtmlUrl,
|
||||
},
|
||||
Message: err,
|
||||
}
|
||||
}
|
||||
return &ProjectResponse{
|
||||
Project: &domain.Project{
|
||||
ProjectGit: git.HtmlUrl,
|
||||
},
|
||||
Message: err,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return &ProjectResponse{
|
||||
Project: nil,
|
||||
Message: errors.New("передано пустое имя"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -78,6 +78,9 @@ func (wc *WorkflowController) GetProjectByChannelID(ctx context.Context, id stri
|
|||
ShortName: dbTicket.Key.String,
|
||||
Name: dbTicket.Key.String,
|
||||
ChannelID: dbTicket.Channelid.String,
|
||||
ProjectGit: dbTicket.ProjectGit.String,
|
||||
BuildGit: dbTicket.BuildGit.String,
|
||||
Cloud: dbTicket.Folder.String,
|
||||
}
|
||||
}
|
||||
return &proj, nil
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
"ticket-pimp/internal/domain"
|
||||
"ticket-pimp/internal/storage/db"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
func (wc *WorkflowController) FullProjectInit(name, key, id string) (string, error) {
|
||||
|
||||
appKey := fmt.Sprintf("%s-%s", key, id)
|
||||
|
||||
var (
|
||||
git, gitBuild *domain.Git
|
||||
cloud *domain.Folder
|
||||
)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(3)
|
||||
|
||||
go func(ref **domain.Git) {
|
||||
defer wg.Done()
|
||||
*ref, _ = wc.IGit.CreateRepo(appKey)
|
||||
}(&git)
|
||||
|
||||
go func(ref **domain.Git) {
|
||||
defer wg.Done()
|
||||
*ref, _ = wc.IGit.CreateRepo(appKey + "-build")
|
||||
}(&gitBuild)
|
||||
|
||||
go func(ref **domain.Folder) {
|
||||
defer wg.Done()
|
||||
|
||||
*ref = wc.ICloud.CreateFolder(appKey).Folder
|
||||
}(&cloud)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
var gitResult, gitBuildResult, cloudResult string
|
||||
|
||||
if git == nil {
|
||||
gitResult = "cannot create git"
|
||||
} else {
|
||||
gitResult = git.HtmlUrl
|
||||
}
|
||||
|
||||
if gitBuild == nil {
|
||||
gitBuildResult = "cannot create git"
|
||||
} else {
|
||||
gitBuildResult = fmt.Sprintf("ssh://%s/%s.git", gitBuild.SshUrl, gitBuild.FullName)
|
||||
}
|
||||
|
||||
if cloud == nil {
|
||||
cloudResult = "cannot create folder"
|
||||
} else {
|
||||
cloudResult = cloud.PrivateURL
|
||||
}
|
||||
ctx := context.TODO()
|
||||
|
||||
insertedTicket, err := wc.q.CreateTicket(ctx, db.CreateTicketParams{
|
||||
Key: pgtype.Text{String: appKey, Valid: true},
|
||||
Channelid: pgtype.Text{},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Print(insertedTicket)
|
||||
|
||||
wc.ICoda.CreateApp(domain.CodaApplication{
|
||||
ID: appKey,
|
||||
Summary: strings.TrimSpace(name),
|
||||
Git: gitResult,
|
||||
GitBuild: gitBuildResult,
|
||||
Folder: cloudResult,
|
||||
})
|
||||
|
||||
return appKey, nil
|
||||
}
|
||||
|
|
@ -1,16 +1,10 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
"ticket-pimp/internal/domain"
|
||||
"ticket-pimp/internal/services"
|
||||
"ticket-pimp/internal/storage/db"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
|
|
@ -37,72 +31,7 @@ func NewWorkflowController(
|
|||
}
|
||||
}
|
||||
|
||||
func (wc *WorkflowController) FullProjectInit(name, key, id string) (string, error) {
|
||||
|
||||
appKey := fmt.Sprintf("%s-%s", key, id)
|
||||
|
||||
var (
|
||||
git, gitBuild *domain.Git
|
||||
cloud *domain.Folder
|
||||
)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(3)
|
||||
|
||||
go func(ref **domain.Git) {
|
||||
defer wg.Done()
|
||||
*ref, _ = wc.IGit.CreateRepo(appKey)
|
||||
}(&git)
|
||||
|
||||
go func(ref **domain.Git) {
|
||||
defer wg.Done()
|
||||
*ref, _ = wc.IGit.CreateRepo(appKey + "-build")
|
||||
}(&gitBuild)
|
||||
|
||||
go func(ref **domain.Folder) {
|
||||
defer wg.Done()
|
||||
*ref, _ = wc.ICloud.CreateFolder(appKey)
|
||||
}(&cloud)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
var gitResult, gitBuildResult, cloudResult string
|
||||
|
||||
if git == nil {
|
||||
gitResult = "cannot create git"
|
||||
} else {
|
||||
gitResult = git.HtmlUrl
|
||||
}
|
||||
|
||||
if gitBuild == nil {
|
||||
gitBuildResult = "cannot create git"
|
||||
} else {
|
||||
gitBuildResult = fmt.Sprintf("ssh://%s/%s.git", gitBuild.SshUrl, gitBuild.FullName)
|
||||
}
|
||||
|
||||
if cloud == nil {
|
||||
cloudResult = "cannot create folder"
|
||||
} else {
|
||||
cloudResult = cloud.PrivateURL
|
||||
}
|
||||
ctx := context.TODO()
|
||||
|
||||
insertedTicket, err := wc.q.CreateTicket(ctx, db.CreateTicketParams{
|
||||
Key: pgtype.Text{String: appKey, Valid: true},
|
||||
Channelid: pgtype.Text{},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Print(insertedTicket)
|
||||
|
||||
wc.ICoda.CreateApp(domain.CodaApplication{
|
||||
ID: appKey,
|
||||
Summary: strings.TrimSpace(name),
|
||||
Git: gitResult,
|
||||
GitBuild: gitBuildResult,
|
||||
Folder: cloudResult,
|
||||
})
|
||||
|
||||
return appKey, nil
|
||||
type ProjectResponse struct {
|
||||
Project *domain.Project
|
||||
Message error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"ticket-pimp/internal/domain"
|
||||
db "ticket-pimp/internal/storage/db"
|
||||
)
|
||||
|
||||
type IConfigController interface {
|
||||
Get(context.Context) (domain.ApplicationConfig, error)
|
||||
Update(context.Context) (domain.ApplicationConfig, error)
|
||||
}
|
||||
|
||||
type AppConfig struct {
|
||||
db *db.Queries
|
||||
}
|
||||
|
||||
func NewAppConfig(db *db.Queries) AppConfig {
|
||||
return AppConfig{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
|
@ -87,6 +87,10 @@ type Project struct {
|
|||
ShortName string `json:"shortName"`
|
||||
Name string `json:"name"`
|
||||
ChannelID string `json:"channel_id"`
|
||||
|
||||
ProjectGit string `json:"project_git"`
|
||||
BuildGit string `json:"build_git"`
|
||||
Cloud string `json:"cloud"`
|
||||
}
|
||||
|
||||
type ProjectID struct {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package helpers
|
||||
|
||||
type ErrorMessage struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func GitNaming(input string) string {
|
||||
func ValidNaming(input string) string {
|
||||
// Remove leading and trailing whitespace
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ var tests = []test{
|
|||
func TestGitNaming(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
if output := GitNaming(test.arg); output != test.expected {
|
||||
if output := ValidNaming(test.arg); output != test.expected {
|
||||
t.Errorf("Output %q not equal to expected %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"ticket-pimp/internal/domain"
|
||||
"ticket-pimp/internal/helpers"
|
||||
"time"
|
||||
|
|
@ -14,7 +17,7 @@ type Cloud struct {
|
|||
}
|
||||
|
||||
type ICloud interface {
|
||||
CreateFolder(name string) (*domain.Folder, error)
|
||||
CreateFolder(name string) Response
|
||||
}
|
||||
|
||||
func NewCloud(conf domain.CloudConfig) *Cloud {
|
||||
|
|
@ -32,40 +35,76 @@ func NewCloud(conf domain.CloudConfig) *Cloud {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Cloud) CreateFolder(name string) (*domain.Folder, error) {
|
||||
type Response struct {
|
||||
Folder *domain.Folder
|
||||
ErrMessage error
|
||||
}
|
||||
|
||||
func (c *Cloud) CreateFolder(name string) Response {
|
||||
var R Response
|
||||
|
||||
rootDir := c.Config.RootDir
|
||||
user := c.Config.User
|
||||
|
||||
davPath := "/remote.php/dav/files/"
|
||||
parentPath := "/apps/files/?dir="
|
||||
|
||||
name = helpers.GitNaming(name)
|
||||
name = helpers.ValidNaming(name)
|
||||
|
||||
cloud := domain.Folder{
|
||||
R.Folder = &domain.Folder{
|
||||
Title: name,
|
||||
PrivateURL: "",
|
||||
}
|
||||
|
||||
// cloud := domain.Folder{
|
||||
// Title: name,
|
||||
// PrivateURL: "",
|
||||
// }
|
||||
|
||||
requestPath := davPath + user + rootDir + name
|
||||
|
||||
cloud.PathTo = parentPath + rootDir + name
|
||||
R.Folder.PathTo = parentPath + rootDir + name
|
||||
|
||||
resp, _ := c.R().
|
||||
var errMessage helpers.ErrorMessage
|
||||
|
||||
resp, err := c.R().
|
||||
SetErrorResult(&errMessage).
|
||||
Send("MKCOL", requestPath)
|
||||
|
||||
if err != nil { // Error handling.
|
||||
log.Println("error:", err)
|
||||
|
||||
// Херовая обработка ошибки:
|
||||
// error while cloud folder creation: bad response, raw content:
|
||||
// <?xml version="1.0" encoding="utf-8"?>
|
||||
// <d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
|
||||
// <s:exception>Sabre\DAV\Exception\MethodNotAllowed</s:exception>
|
||||
// <s:message>The resource you tried to create already exists</s:message>
|
||||
// </d:error>
|
||||
if strings.Contains(err.Error(), "already exists") {
|
||||
R.Folder.PrivateURL = c.BaseURL + R.Folder.PathTo
|
||||
R.ErrMessage = errors.New("guess, that folder already exists")
|
||||
// Try to set short URL to the d entity
|
||||
if err := c.setPrivateURL(requestPath, R.Folder); err != nil {
|
||||
R.ErrMessage = err
|
||||
return R
|
||||
}
|
||||
return R
|
||||
}
|
||||
return R
|
||||
}
|
||||
|
||||
if resp.IsSuccessState() {
|
||||
// Set stupid URL to the d entity
|
||||
cloud.PrivateURL = c.BaseURL + cloud.PathTo
|
||||
R.Folder.PrivateURL = c.BaseURL + R.Folder.PathTo
|
||||
|
||||
// Try to set short URL to the d entity
|
||||
if err := c.setPrivateURL(requestPath, &cloud); err != nil {
|
||||
return &cloud, err
|
||||
if err := c.setPrivateURL(requestPath, R.Folder); err != nil {
|
||||
return R
|
||||
}
|
||||
} else {
|
||||
fmt.Println(resp.Status)
|
||||
}
|
||||
|
||||
return &cloud, nil
|
||||
return R
|
||||
}
|
||||
|
||||
func (c *Cloud) setPrivateURL(requestPath string, cloud *domain.Folder) error {
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ type gitCreateRequest struct {
|
|||
}
|
||||
|
||||
func (gb *Git) newRepo(name string) (*domain.Git, error) {
|
||||
name = helpers.GitNaming(name)
|
||||
name = helpers.ValidNaming(name)
|
||||
|
||||
payload := gitCreateRequest{
|
||||
Name: name,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,307 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.23.0
|
||||
// source: queries.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createTicket = `-- name: CreateTicket :one
|
||||
INSERT INTO tickets (
|
||||
key, channelID
|
||||
) VALUES (
|
||||
$1, $2
|
||||
)
|
||||
RETURNING id, key, channelid, project_git, build_git, folder, created_at, deleted_at, updated_at
|
||||
`
|
||||
|
||||
type CreateTicketParams struct {
|
||||
Key pgtype.Text
|
||||
Channelid pgtype.Text
|
||||
}
|
||||
|
||||
func (q *Queries) CreateTicket(ctx context.Context, arg CreateTicketParams) (Ticket, error) {
|
||||
row := q.db.QueryRow(ctx, createTicket, arg.Key, arg.Channelid)
|
||||
var i Ticket
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Key,
|
||||
&i.Channelid,
|
||||
&i.ProjectGit,
|
||||
&i.BuildGit,
|
||||
&i.Folder,
|
||||
&i.CreatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteTicketByID = `-- name: DeleteTicketByID :exec
|
||||
UPDATE tickets SET deleted_at = current_timestamp WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteTicketByID(ctx context.Context, id int32) error {
|
||||
_, err := q.db.Exec(ctx, deleteTicketByID, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteTicketByKey = `-- name: DeleteTicketByKey :exec
|
||||
UPDATE tickets SET deleted_at = current_timestamp WHERE key = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteTicketByKey(ctx context.Context, key pgtype.Text) error {
|
||||
_, err := q.db.Exec(ctx, deleteTicketByKey, key)
|
||||
return err
|
||||
}
|
||||
|
||||
const getConfig = `-- name: GetConfig :one
|
||||
SELECT ticket_key, ticket_id
|
||||
FROM appconfig
|
||||
`
|
||||
|
||||
func (q *Queries) GetConfig(ctx context.Context) (Appconfig, error) {
|
||||
row := q.db.QueryRow(ctx, getConfig)
|
||||
var i Appconfig
|
||||
err := row.Scan(&i.TicketKey, &i.TicketID)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTicketByChannelID = `-- name: GetTicketByChannelID :one
|
||||
SELECT id, key, channelid, project_git, build_git, folder, created_at, deleted_at, updated_at FROM tickets WHERE channelID = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTicketByChannelID(ctx context.Context, channelid pgtype.Text) (Ticket, error) {
|
||||
row := q.db.QueryRow(ctx, getTicketByChannelID, channelid)
|
||||
var i Ticket
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Key,
|
||||
&i.Channelid,
|
||||
&i.ProjectGit,
|
||||
&i.BuildGit,
|
||||
&i.Folder,
|
||||
&i.CreatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTicketByID = `-- name: GetTicketByID :one
|
||||
SELECT id, key, channelid, project_git, build_git, folder, created_at, deleted_at, updated_at FROM tickets WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTicketByID(ctx context.Context, id int32) (Ticket, error) {
|
||||
row := q.db.QueryRow(ctx, getTicketByID, id)
|
||||
var i Ticket
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Key,
|
||||
&i.Channelid,
|
||||
&i.ProjectGit,
|
||||
&i.BuildGit,
|
||||
&i.Folder,
|
||||
&i.CreatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listTickets = `-- name: ListTickets :many
|
||||
SELECT id, key, channelid, project_git, build_git, folder, created_at, deleted_at, updated_at FROM tickets WHERE deleted_at IS NULL
|
||||
`
|
||||
|
||||
func (q *Queries) ListTickets(ctx context.Context) ([]Ticket, error) {
|
||||
rows, err := q.db.Query(ctx, listTickets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Ticket
|
||||
for rows.Next() {
|
||||
var i Ticket
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Key,
|
||||
&i.Channelid,
|
||||
&i.ProjectGit,
|
||||
&i.BuildGit,
|
||||
&i.Folder,
|
||||
&i.CreatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listTicketsWithDeleted = `-- name: ListTicketsWithDeleted :many
|
||||
SELECT id, key, channelid, project_git, build_git, folder, created_at, deleted_at, updated_at FROM tickets
|
||||
`
|
||||
|
||||
func (q *Queries) ListTicketsWithDeleted(ctx context.Context) ([]Ticket, error) {
|
||||
rows, err := q.db.Query(ctx, listTicketsWithDeleted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Ticket
|
||||
for rows.Next() {
|
||||
var i Ticket
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Key,
|
||||
&i.Channelid,
|
||||
&i.ProjectGit,
|
||||
&i.BuildGit,
|
||||
&i.Folder,
|
||||
&i.CreatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const setNewConfig = `-- name: SetNewConfig :one
|
||||
UPDATE appconfig
|
||||
SET ticket_id = ticket_id + 1
|
||||
RETURNING ticket_key, ticket_id
|
||||
`
|
||||
|
||||
func (q *Queries) SetNewConfig(ctx context.Context) (Appconfig, error) {
|
||||
row := q.db.QueryRow(ctx, setNewConfig)
|
||||
var i Appconfig
|
||||
err := row.Scan(&i.TicketKey, &i.TicketID)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateTicketBuildGit = `-- name: UpdateTicketBuildGit :one
|
||||
UPDATE tickets
|
||||
SET build_git = $1, updated_at = $2
|
||||
WHERE channelID = $3
|
||||
RETURNING id, key, channelid, project_git, build_git, folder, created_at, deleted_at, updated_at
|
||||
`
|
||||
|
||||
type UpdateTicketBuildGitParams struct {
|
||||
BuildGit pgtype.Text
|
||||
UpdatedAt pgtype.Timestamptz
|
||||
Channelid pgtype.Text
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTicketBuildGit(ctx context.Context, arg UpdateTicketBuildGitParams) (Ticket, error) {
|
||||
row := q.db.QueryRow(ctx, updateTicketBuildGit, arg.BuildGit, arg.UpdatedAt, arg.Channelid)
|
||||
var i Ticket
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Key,
|
||||
&i.Channelid,
|
||||
&i.ProjectGit,
|
||||
&i.BuildGit,
|
||||
&i.Folder,
|
||||
&i.CreatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateTicketByID = `-- name: UpdateTicketByID :exec
|
||||
UPDATE tickets SET project_git = $1, build_git = $2, folder = $3 WHERE id = $4
|
||||
`
|
||||
|
||||
type UpdateTicketByIDParams struct {
|
||||
ProjectGit pgtype.Text
|
||||
BuildGit pgtype.Text
|
||||
Folder pgtype.Text
|
||||
ID int32
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTicketByID(ctx context.Context, arg UpdateTicketByIDParams) error {
|
||||
_, err := q.db.Exec(ctx, updateTicketByID,
|
||||
arg.ProjectGit,
|
||||
arg.BuildGit,
|
||||
arg.Folder,
|
||||
arg.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateTicketFolder = `-- name: UpdateTicketFolder :one
|
||||
UPDATE tickets
|
||||
SET folder = $1, updated_at = $2
|
||||
WHERE channelID = $3
|
||||
RETURNING id, key, channelid, project_git, build_git, folder, created_at, deleted_at, updated_at
|
||||
`
|
||||
|
||||
type UpdateTicketFolderParams struct {
|
||||
Folder pgtype.Text
|
||||
UpdatedAt pgtype.Timestamptz
|
||||
Channelid pgtype.Text
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTicketFolder(ctx context.Context, arg UpdateTicketFolderParams) (Ticket, error) {
|
||||
row := q.db.QueryRow(ctx, updateTicketFolder, arg.Folder, arg.UpdatedAt, arg.Channelid)
|
||||
var i Ticket
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Key,
|
||||
&i.Channelid,
|
||||
&i.ProjectGit,
|
||||
&i.BuildGit,
|
||||
&i.Folder,
|
||||
&i.CreatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateTicketProjectGit = `-- name: UpdateTicketProjectGit :one
|
||||
UPDATE tickets
|
||||
SET project_git = $1, updated_at = $2
|
||||
WHERE channelID = $3
|
||||
RETURNING id, key, channelid, project_git, build_git, folder, created_at, deleted_at, updated_at
|
||||
`
|
||||
|
||||
type UpdateTicketProjectGitParams struct {
|
||||
ProjectGit pgtype.Text
|
||||
UpdatedAt pgtype.Timestamptz
|
||||
Channelid pgtype.Text
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTicketProjectGit(ctx context.Context, arg UpdateTicketProjectGitParams) (Ticket, error) {
|
||||
row := q.db.QueryRow(ctx, updateTicketProjectGit, arg.ProjectGit, arg.UpdatedAt, arg.Channelid)
|
||||
var i Ticket
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Key,
|
||||
&i.Channelid,
|
||||
&i.ProjectGit,
|
||||
&i.BuildGit,
|
||||
&i.Folder,
|
||||
&i.CreatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -15,6 +15,24 @@ INSERT INTO tickets (
|
|||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateTicketFolder :one
|
||||
UPDATE tickets
|
||||
SET folder = $1, updated_at = $2
|
||||
WHERE channelID = $3
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateTicketProjectGit :one
|
||||
UPDATE tickets
|
||||
SET project_git = $1, updated_at = $2
|
||||
WHERE channelID = $3
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateTicketBuildGit :one
|
||||
UPDATE tickets
|
||||
SET build_git = $1, updated_at = $2
|
||||
WHERE channelID = $3
|
||||
RETURNING *;
|
||||
|
||||
-- name: ListTickets :many
|
||||
SELECT * FROM tickets WHERE deleted_at IS NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ func (h *Handler) NewFolderHandler(ctx context.Context, mu *tgb.MessageUpdate) e
|
|||
return errors.New("empty command provided")
|
||||
}
|
||||
|
||||
cloud, err := h.cloud.CreateFolder(str)
|
||||
resp := h.cloud.CreateFolder(str)
|
||||
|
||||
if err != nil {
|
||||
answer := errorAnswer(err.Error())
|
||||
if resp.ErrMessage != nil {
|
||||
answer := errorAnswer(resp.ErrMessage.Error())
|
||||
h.LogMessage(ctx, mu, answer)
|
||||
return mu.Answer(answer).ParseMode(tg.HTML).DoVoid(ctx)
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ func (h *Handler) NewFolderHandler(ctx context.Context, mu *tgb.MessageUpdate) e
|
|||
answer := tg.HTML.Text(
|
||||
tg.HTML.Line(
|
||||
"✨ Shiny folder",
|
||||
tg.HTML.Link(cloud.Title, cloud.PrivateURL),
|
||||
tg.HTML.Link(resp.Folder.Title, resp.Folder.PrivateURL),
|
||||
"has been created!",
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ func Run(ctx context.Context, opts TelegramOptions) error {
|
|||
// Message(h.NewFolderHandler, tgb.TextHasPrefix("/folder")).
|
||||
Message(h.FarmTaskHandler, tgb.TextHasPrefix("/task"))
|
||||
|
||||
log.Print("Success init. Start poller.")
|
||||
return tgb.NewPoller(
|
||||
router,
|
||||
client,
|
||||
|
|
|
|||
Loading…
Reference in New Issue