just...no message

This commit is contained in:
naudachu 2023-06-21 14:07:26 +05:00
parent ad1beb66dd
commit db69ef238e
12 changed files with 231 additions and 88 deletions

5
cmd/fileid.xml Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<a:propfind xmlns:a="DAV:" xmlns:oc="http://owncloud.org/ns">
<!-- retrieve the file's id -->
<a:prop><oc:fileid/></a:prop>
</a:propfind>

View File

@ -3,6 +3,7 @@ package controller
import ( import (
"fmt" "fmt"
"sync" "sync"
d "ticket-pimp/domain"
"ticket-pimp/ext" "ticket-pimp/ext"
) )
@ -15,7 +16,7 @@ type WorkflowController struct {
type IWorkflowController interface { type IWorkflowController interface {
Workflow(name string) (string, error) Workflow(name string) (string, error)
CreateRepo(name string, param uint) (string, error) CreateRepo(name string, param uint) (string, error)
CreateFolder(name string) (string, string, error) CreateFolder(name string) (*d.Cloud, error)
} }
func NewWorkflowController( func NewWorkflowController(
@ -51,7 +52,8 @@ func (wc *WorkflowController) Workflow(name string) (string, error) {
if issue != nil { if issue != nil {
var ( var (
git, gitBuild, folder string git, gitBuild string
cloud *d.Cloud
) )
var wg sync.WaitGroup var wg sync.WaitGroup
@ -67,14 +69,14 @@ func (wc *WorkflowController) Workflow(name string) (string, error) {
gitBuild, _ = wc.CreateRepo(issue.Key+"-build", 1) gitBuild, _ = wc.CreateRepo(issue.Key+"-build", 1)
}() }()
go func() { go func(ref **d.Cloud) {
defer wg.Done() defer wg.Done()
_, folder, _ = wc.CreateFolder(issue.Key + " - " + issue.Summary) *ref, _ = wc.CreateFolder(issue.Key + " - " + issue.Summary)
}() }(&cloud)
wg.Wait() wg.Wait()
yt.UpdateIssue(issue, folder, git, gitBuild) yt.UpdateIssue(issue, cloud.FolderURL, git, gitBuild)
} }
return issue.Key, nil return issue.Key, nil
} }
@ -101,13 +103,17 @@ func (wc *WorkflowController) CreateRepo(name string, param uint) (string, error
return "", err return "", err
} }
func (wc *WorkflowController) CreateFolder(name string) (string, string, error) { func (wc *WorkflowController) CreateFolder(name string) (*d.Cloud, error) {
//Create ownCloud folder w/ iCloud interface; //Create ownCloud folder w/ iCloud interface;
cloud, err := wc.iCloud.CreateFolder(name) cloud, err := wc.iCloud.CreateFolder(name)
if cloud == nil { if cloud == nil {
return "", "", err return cloud, err
} }
return cloud.FolderName, cloud.FolderPath, err /* [ ] Experimental call:
wc.iCloud.ShareToExternals(cloud)
*/
return cloud, err
} }

8
domain/cloud.go Normal file
View File

@ -0,0 +1,8 @@
package domain
type Cloud struct {
FolderName string // "k"
FolderPath string // "/temp/k"
FolderURL string // "http://82.151.222.22:7000/apps/files/?dir=/temp/k"
PublicURL string
}

32
domain/youtrack.go Normal file
View File

@ -0,0 +1,32 @@
package domain
type Project struct {
ID string `json:"id"`
ShortName string `json:"shortName"`
Name string `json:"name"`
}
type ProjectID struct {
ID string `json:"id"`
}
type IssueCreateRequest struct {
ProjectID ProjectID `json:"project"`
Key string `json:"idReadable"`
ID string `json:"id"`
Summary string `json:"summary"`
Description string `json:"description"`
}
// [ ] try `,omitempty` to remove extra struct;
type IssueUpdateRequest struct {
IssueCreateRequest
CustomFields []CustomField `json:"customFields"`
}
type CustomField struct {
Name string `json:"name"`
Type string `json:"$type"`
Value string `json:"value"`
}

View File

@ -1,20 +1,23 @@
package ext package ext
import ( import (
"encoding/xml"
"fmt"
"io/ioutil"
"log"
"os" "os"
"ticket-pimp/domain"
"ticket-pimp/helpers" "ticket-pimp/helpers"
"time" "time"
) )
type Cloud struct { type Cloud struct {
//[ ] out in separate domain struct
FolderName string
FolderPath string
*Client *Client
} }
type ICloud interface { type ICloud interface {
CreateFolder(name string) (*Cloud, error) CreateFolder(name string) (*domain.Cloud, error)
ShareToExternals(cloud *domain.Cloud) (*domain.Cloud, error)
} }
func NewCloud(base, user, pass string) *Cloud { func NewCloud(base, user, pass string) *Cloud {
@ -25,32 +28,88 @@ func NewCloud(base, user, pass string) *Cloud {
SetBaseURL(base) SetBaseURL(base)
return &Cloud{ return &Cloud{
FolderName: "",
FolderPath: "",
Client: &Client{ Client: &Client{
client, client,
}, },
} }
} }
func (c *Cloud) CreateFolder(name string) (*Cloud, error) { func (c *Cloud) CreateFolder(name string) (*domain.Cloud, error) {
rootDir := os.Getenv("ROOTDIR")
name = helpers.GitNaming(name) name = helpers.GitNaming(name)
cloud := Cloud{ cloud := domain.Cloud{
FolderName: name, FolderName: name,
FolderPath: "", FolderURL: "",
} }
pathName := os.Getenv("HOMEPATH") + name requestPath := os.Getenv("HOMEPATH") + rootDir + name
cloud.FolderPath = os.Getenv("FOLDER_PATH") + rootDir + name
resp, err := c.R(). resp, err := c.R().
Send("MKCOL", pathName) Send("MKCOL", requestPath)
if resp.IsSuccessState() { if resp.IsSuccessState() {
cloud.FolderPath = c.BaseURL + os.Getenv("FOLDER_PATH") + name
cloud.FolderURL = c.BaseURL + cloud.FolderPath
/*
type ResponseObj struct {
Multistatus struct {
Response struct {
Href struct {
Propstat struct {
Prop struct {
FileID int `json:"oc:fileid"`
} `json:"d:prop"`
} `json:"d:propstat"`
} `json:"d:href"`
} `json:"d:response"`
} `json:"d:multistatus"`
}*/
type ResponseObj struct {
XMLName xml.Name `xml:"d:multistatus"`
Multistatus struct {
XMLName xml.Name `xml:"d:multistatus"`
Response struct {
Href struct {
Propstat struct {
Prop struct {
FileID string `xml:"oc:fileid"`
} `xml:"d:prop"`
} `xml:"d:propstat"`
} `xml:"d:href"`
} `xml:"d:response"`
} `xml:"d:multistatus"`
}
xmlFile, err := ioutil.ReadFile("./fileid.xml")
if err != nil {
fmt.Println(err)
return nil, err // fix this return;
}
var id ResponseObj
resp, _ := c.R().
SetBody(xmlFile).
Send("PROPFIND", os.Getenv("HOMEPATH")+os.Getenv("ROOTDIR")+cloud.FolderName)
xmlEncodingErr := resp.UnmarshalXml(&id)
if xmlEncodingErr != nil {
log.Print(err)
}
log.Print(resp)
} }
return &cloud, err return &cloud, err
} }
func (c *Cloud) ShareToExternals(cloud *domain.Cloud) (*domain.Cloud, error) {
return nil, nil
}

View File

@ -10,7 +10,6 @@ import (
type Git struct { type Git struct {
*Client *Client
*domain.Git
} }
type IGit interface { type IGit interface {
@ -33,15 +32,6 @@ func NewGit(base, token string) *Git {
return &Git{ return &Git{
Client: &Client{client}, Client: &Client{client},
Git: &domain.Git{
Name: "",
FullName: "",
Private: true,
Url: "",
CloneUrl: "",
HtmlUrl: "",
SshUrl: "",
},
} }
} }
@ -63,6 +53,7 @@ func (gb *Git) NewRepo(name string) (*domain.Git, error) {
} }
var git domain.Git var git domain.Git
git.Private = true
resp, err := gb.R(). resp, err := gb.R().
SetBody(&payload). SetBody(&payload).
@ -77,6 +68,7 @@ func (gb *Git) NewRepo(name string) (*domain.Git, error) {
} }
func (gb *Git) AppsAsCollaboratorTo(git *domain.Git) (*domain.Git, error) { func (gb *Git) AppsAsCollaboratorTo(git *domain.Git) (*domain.Git, error) {
payloadPermission := permissionRequest{ payloadPermission := permissionRequest{
Perm: "admin", Perm: "admin",
} }

View File

@ -5,6 +5,8 @@ import (
"log" "log"
"time" "time"
d "ticket-pimp/domain"
"github.com/imroc/req/v3" "github.com/imroc/req/v3"
) )
@ -13,9 +15,9 @@ type youtrack struct {
} }
type IYouTrack interface { type IYouTrack interface {
GetProjects() ([]Project, error) GetProjects() ([]d.Project, error)
CreateIssue(projectID, name string) (*IssueCreateRequest, error) CreateIssue(projectID, name string) (*d.IssueCreateRequest, error)
UpdateIssue(issue *IssueCreateRequest, folder, git, gitBuild string) (*IssueUpdateRequest, error) UpdateIssue(issue *d.IssueCreateRequest, folder, git, gitBuild string) (*d.IssueUpdateRequest, error)
} }
func NewYT(base, token string) *youtrack { func NewYT(base, token string) *youtrack {
@ -35,17 +37,11 @@ func NewYT(base, token string) *youtrack {
} }
} }
type Project struct {
ID string `json:"id"`
ShortName string `json:"shortName"`
Name string `json:"name"`
}
// GetProjects // GetProjects
// provides an array of existing projects; // provides an array of existing projects;
func (yt *youtrack) GetProjects() ([]Project, error) { func (yt *youtrack) GetProjects() ([]d.Project, error) {
var projects []Project var projects []d.Project
_, err := yt.R(). _, err := yt.R().
EnableDump(). EnableDump().
@ -61,25 +57,13 @@ func (yt *youtrack) GetProjects() ([]Project, error) {
return projects, nil return projects, nil
} }
type ProjectID struct {
ID string `json:"id"`
}
type IssueCreateRequest struct {
ProjectID ProjectID `json:"project"`
Key string `json:"idReadable"`
ID string `json:"id"`
Summary string `json:"summary"`
Description string `json:"description"`
}
// CreateIssue // CreateIssue
// example: newIssue := yt.CreateIssue("0-2", "Summary", "Description"); // example: newIssue := yt.CreateIssue("0-2", "Summary", "Description");
func (yt *youtrack) CreateIssue(projectID, name string) (*IssueCreateRequest, error) { func (yt *youtrack) CreateIssue(projectID, name string) (*d.IssueCreateRequest, error) {
// Create an issue with the provided:, Project ID, Name, Description; // Create an issue with the provided:, Project ID, Name, Description;
issue := IssueCreateRequest{ issue := d.IssueCreateRequest{
ProjectID: ProjectID{ ProjectID: d.ProjectID{
ID: projectID, //"id":"0-2" ID: projectID, //"id":"0-2"
}, },
Summary: name, Summary: name,
@ -101,26 +85,11 @@ func (yt *youtrack) CreateIssue(projectID, name string) (*IssueCreateRequest, er
return &issue, nil return &issue, nil
} }
type IssueUpdateRequest struct { func (yt *youtrack) UpdateIssue(issue *d.IssueCreateRequest, folder, git, gitBuild string) (*d.IssueUpdateRequest, error) {
IssueCreateRequest
CustomFields []CustomField `json:"customFields"`
}
type CustomFields struct {
List []CustomField `json:"customFields"`
}
type CustomField struct {
Name string `json:"name"`
Type string `json:"$type"`
Value string `json:"value"`
}
func (yt *youtrack) UpdateIssue(issue *IssueCreateRequest, folder, git, gitBuild string) (*IssueUpdateRequest, error) {
// Set Folder, Git, GitBuild to the Issue: // Set Folder, Git, GitBuild to the Issue:
update := IssueUpdateRequest{ update := d.IssueUpdateRequest{
IssueCreateRequest: *issue, IssueCreateRequest: *issue,
CustomFields: []CustomField{ CustomFields: []d.CustomField{
{ {
Name: "Директория графики", Name: "Директория графики",
Type: "SimpleIssueCustomField", Type: "SimpleIssueCustomField",

1
go.mod
View File

@ -19,6 +19,7 @@ require (
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
github.com/quic-go/quic-go v0.35.1 // indirect github.com/quic-go/quic-go v0.35.1 // indirect
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2 // indirect
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce // indirect github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce // indirect
golang.org/x/crypto v0.9.0 // indirect golang.org/x/crypto v0.9.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect

2
go.sum
View File

@ -38,6 +38,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2 h1:VsBj3UD2xyAOu7kJw6O/2jjG2UXLFoBzihqDU9Ofg9M=
github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=

View File

@ -17,7 +17,14 @@ type Handler struct {
func NewHandler(gitBaseURL, gitToken, cloudBaseURL, cloudAuthUser, cloudAuthPass, ytBaseURL, ytToken string) *Handler { func NewHandler(gitBaseURL, gitToken, cloudBaseURL, cloudAuthUser, cloudAuthPass, ytBaseURL, ytToken string) *Handler {
return &Handler{ return &Handler{
workflow: controller.NewWorkflowController(gitBaseURL, gitToken, cloudBaseURL, cloudAuthUser, cloudAuthPass, ytBaseURL, ytToken), workflow: controller.NewWorkflowController(
gitBaseURL,
gitToken,
cloudBaseURL,
cloudAuthUser,
cloudAuthPass,
ytBaseURL,
ytToken),
} }
} }
@ -52,15 +59,6 @@ func (h *Handler) NewRepoHandler(ctx context.Context, mu *tgb.MessageUpdate) err
return mu.Answer(newRepoAnswer(repoStr)).ParseMode(tg.HTML).DoVoid(ctx) return mu.Answer(newRepoAnswer(repoStr)).ParseMode(tg.HTML).DoVoid(ctx)
} }
func newFolderAnswer(name string) string {
return tg.HTML.Text(
tg.HTML.Line(
"Folder ",
name,
"has been created!",
),
)
}
func (h *Handler) NewFolderHandler(ctx context.Context, mu *tgb.MessageUpdate) error { func (h *Handler) NewFolderHandler(ctx context.Context, mu *tgb.MessageUpdate) error {
str := strings.Replace(mu.Text, "/folder", "", 1) str := strings.Replace(mu.Text, "/folder", "", 1)
@ -69,13 +67,23 @@ func (h *Handler) NewFolderHandler(ctx context.Context, mu *tgb.MessageUpdate) e
return errors.New("empty command provided") return errors.New("empty command provided")
} }
nameStr, _, err := h.workflow.CreateFolder(str) cloud, err := h.workflow.CreateFolder(str)
if err != nil { if err != nil {
return mu.Answer(errorAnswer(err.Error())).ParseMode(tg.HTML).DoVoid(ctx) return mu.Answer(errorAnswer(err.Error())).ParseMode(tg.HTML).DoVoid(ctx)
} }
return mu.Answer(newFolderAnswer(nameStr)).ParseMode(tg.HTML).DoVoid(ctx) answer := tg.HTML.Text(
tg.HTML.Line(
"✨ Shiny folder",
tg.HTML.Link(cloud.FolderName, cloud.FolderURL),
"has been created!",
),
)
return mu.Answer(answer).
ParseMode(tg.HTML).
DoVoid(ctx)
} }
func errorAnswer(errorMsg string) string { func errorAnswer(errorMsg string) string {

View File

@ -1,6 +1,8 @@
package helpers package helpers
import "testing" import (
"testing"
)
type test struct { type test struct {
arg, expected string arg, expected string

59
helpers/xml_test.go Normal file
View File

@ -0,0 +1,59 @@
package helpers
import (
"encoding/xml"
"fmt"
"log"
"testing"
)
/*
<?xml version=\"1.0\"?>
<d:multistatus xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\" xmlns:oc=\"http://owncloud.org/ns\">
<d:response>
<d:href>/remote.php/dav/files/naudachu/temp/id/</d:href>
<d:propstat>
<d:prop>
<oc:fileid>33225</oc:fileid>
</d:prop>
<d:status>HTTP/1.1 200 OK</d:status>
</d:propstat>
</d:response>
</d:multistatus>
*/
type MultistatusObj struct {
XMLName xml.Name `xml:"multistatus"`
Multistatus struct {
ResponseObj
}
}
type ResponseObj struct {
XMLName xml.Name `xml:"response"`
Response struct {
Content string `xml:",chardata"`
}
}
const (
EXAMPLE = "<?xml version=\"1.0\"?>\n<d:multistatus xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\" xmlns:oc=\"http://owncloud.org/ns\"><d:response><d:href>/remote.php/dav/files/naudachu/temp/id/</d:href><d:propstat><d:prop><oc:fileid>33225</oc:fileid></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>\n"
)
func GetFileID(str string) string {
var multi MultistatusObj
err := xml.Unmarshal([]byte(str), &multi)
if err != nil {
fmt.Print(err)
}
return multi.Multistatus.Response.Content
}
func TestGetFileID(t *testing.T) {
str := GetFileID(EXAMPLE)
log.Print(str)
}