- start implementing onion arch;

This commit is contained in:
naudachu 2023-11-22 11:07:36 +05:00
parent f7dd74ffff
commit 47cae1e99d
15 changed files with 665 additions and 76 deletions

18
adapters/adapters.go Normal file
View File

@ -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)
}

View File

@ -6,7 +6,7 @@ import (
"log" "log"
"os" "os"
"os/signal" "os/signal"
"ticket-pimp/client/discord/handler" "ticket-pimp/client/discord/router"
"ticket-pimp/internal/controller" "ticket-pimp/internal/controller"
"ticket-pimp/internal/domain" "ticket-pimp/internal/domain"
@ -51,7 +51,7 @@ func Run(conf domain.Config, opts DiscordOptions) error {
s := initBotWith(token) 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){} commandHandlers := map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){}
for _, handler := range router.Commands { for _, handler := range router.Commands {
@ -89,18 +89,35 @@ func Run(conf domain.Config, opts DiscordOptions) error {
// UPDATE FORUM IF NEEDED: // UPDATE FORUM IF NEEDED:
forum, err := s.Channel(conf.Discord.IsProjectChannel) forum, err := s.Channel(conf.Discord.IsTaskForum)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
} }
_, err = s.ChannelEditComplex(forum.ID, &discordgo.ChannelEdit{ tagsAvailable := []discordgo.ForumTag{
AvailableTags: &router.Tags, {
Name: "В работе",
Moderated: true,
EmojiName: "👩‍🍳",
},
{
Name: "Готово",
Moderated: true,
EmojiName: "✅",
},
}
dchan, err := s.ChannelEditComplex(forum.ID, &discordgo.ChannelEdit{
AvailableTags: &tagsAvailable,
}) })
if err != nil { if err != nil {
log.Fatal(err) 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...") log.Println("Adding commands...")
var cmds []*discordgo.ApplicationCommand var cmds []*discordgo.ApplicationCommand
var logString []string var logString []string

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -1,4 +1,4 @@
package handler package router
import ( import (
"context" "context"
@ -198,10 +198,10 @@ func (c *client) handleTaskButton(s *discordgo.Session, i *discordgo.Interaction
} }
// Устанавливаем тэги статуса на тред --------------------------------------------------------------------- // Устанавливаем тэги статуса на тред ---------------------------------------------------------------------
err = c.setFlag(s, i, &c.Tags[opt]) // err = c.setFlag(s, i, &c.Tags[opt])
if err != nil { // if err != nil {
log.Printf("error while `start` tag setting: %v", err) // log.Printf("error while `start` tag setting: %v", err)
} // }
} }
type TelegramMessage struct { type TelegramMessage struct {
@ -212,6 +212,7 @@ type TelegramMessage struct {
DisablePreview bool `json:"disable_web_page_preview"` DisablePreview bool `json:"disable_web_page_preview"`
} }
// [ ] As a separate service?
func (c *client) sendTelegramMessageToCreator(tgChatID string, text string) { func (c *client) sendTelegramMessageToCreator(tgChatID string, text string) {
http := req.C() http := req.C()
@ -224,26 +225,4 @@ func (c *client) sendTelegramMessageToCreator(tgChatID string, text string) {
DisablePreview: true, DisablePreview: true,
}). }).
Post("https://api.telegram.org/bot" + c.tgConf.Token + "/sendMessage") 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
// )
// )
} }

View File

@ -1,4 +1,4 @@
package handler package router
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package handler package router
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package handler package router
import ( import (
"log" "log"

View File

@ -1,4 +1,4 @@
package handler package router
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package handler package router
import ( import (
"fmt" "fmt"
@ -12,7 +12,7 @@ type client struct {
Commands []Command Commands []Command
Components []Component Components []Component
Tags []discordgo.ForumTag // Tags []discordgo.ForumTag
controller controller.WorkflowController controller controller.WorkflowController
conf *domain.DiscordConfig conf *domain.DiscordConfig
@ -27,30 +27,16 @@ func InitRouter(wc controller.WorkflowController, conf *domain.DiscordConfig, tg
r.conf = conf r.conf = conf
r.Commands = append(r.Commands, r.Commands = append(r.Commands,
r.CreateRepoHandler(3), // r.CreateRepoHandler(3),
r.CreateFolderHandler(3), // r.CreateFolderHandler(3),
r.Ping(), r.Ping(),
r.CreateTicketHandler(3), // r.CreateTicketHandler(3),
r.InitProjectFromChannel(3), // r.InitProjectFromChannel(3),
r.GetInfo(), // r.GetInfo(),
) )
r.Components = append(r.Components, r.Components = append(r.Components,
r.HandleTaskButtons(), r.HandleTaskButtons(),
) )
r.Tags = append(
r.Tags,
discordgo.ForumTag{
Name: "В работе",
Moderated: true,
EmojiName: "👩‍🍳",
},
discordgo.ForumTag{
Name: "Готово",
Moderated: true,
EmojiName: "✅",
})
r.tgConf = tgConf r.tgConf = tgConf
return &r return &r

View File

@ -1,14 +1,15 @@
package handler package handler
import ( import (
"ticket-pimp/adapters"
"ticket-pimp/internal/controller" "ticket-pimp/internal/controller"
"ticket-pimp/internal/services" "ticket-pimp/internal/services"
) )
type Handler struct { type Handler struct {
git services.IGit git services.IGit
cloud services.ICloud cloud adapters.ICloud
coda services.ICoda coda adapters.ICoda
key string key string
id string id string
controller *controller.WorkflowController controller *controller.WorkflowController
@ -16,8 +17,8 @@ type Handler struct {
func NewHandler( func NewHandler(
git services.IGit, git services.IGit,
cloud services.ICloud, cloud adapters.ICloud,
coda services.ICoda, coda adapters.ICoda,
controller *controller.WorkflowController, controller *controller.WorkflowController,
) *Handler { ) *Handler {

View File

@ -1,6 +1,7 @@
package controller package controller
import ( import (
"ticket-pimp/adapters"
"ticket-pimp/internal/domain" "ticket-pimp/internal/domain"
"ticket-pimp/internal/services" "ticket-pimp/internal/services"
"ticket-pimp/internal/storage/db" "ticket-pimp/internal/storage/db"
@ -11,8 +12,8 @@ import (
type WorkflowController struct { type WorkflowController struct {
IGit services.IGit IGit services.IGit
ICloud services.ICloud ICloud adapters.ICloud
ICoda services.ICoda ICoda adapters.ICoda
pool *pgxpool.Pool pool *pgxpool.Pool
q *db.Queries q *db.Queries
ATags []discordgo.ForumTag ATags []discordgo.ForumTag
@ -20,8 +21,8 @@ type WorkflowController struct {
func NewWorkflowController( func NewWorkflowController(
git services.IGit, git services.IGit,
cloud services.ICloud, cloud adapters.ICloud,
coda services.ICoda, coda adapters.ICoda,
pool *pgxpool.Pool, pool *pgxpool.Pool,
) *WorkflowController { ) *WorkflowController {
return &WorkflowController{ return &WorkflowController{

View File

@ -11,6 +11,11 @@ type Folder struct {
PrivateURL string // http://domain/apps/files/?dir=/temp/k OR http://domain/f/3333 PrivateURL string // http://domain/apps/files/?dir=/temp/k OR http://domain/f/3333
} }
type Response struct {
Folder *Folder
ErrMessage error
}
type CodaApplication struct { type CodaApplication struct {
ID string `json:"id"` ID string `json:"id"`
Summary string `json:"summary"` Summary string `json:"summary"`

View File

@ -16,10 +16,6 @@ type Cloud struct {
Config domain.CloudConfig Config domain.CloudConfig
} }
type ICloud interface {
CreateFolder(name string) Response
}
func NewCloud(conf domain.CloudConfig) *Cloud { func NewCloud(conf domain.CloudConfig) *Cloud {
client := NewClient(). client := NewClient().
@ -35,13 +31,8 @@ func NewCloud(conf domain.CloudConfig) *Cloud {
} }
} }
type Response struct { func (c *Cloud) CreateFolder(name string) domain.Response {
Folder *domain.Folder var R domain.Response
ErrMessage error
}
func (c *Cloud) CreateFolder(name string) Response {
var R Response
rootDir := c.Config.RootDir rootDir := c.Config.RootDir
user := c.Config.User user := c.Config.User

View File

@ -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")
}