diff --git a/cmd/main.go b/cmd/main.go index a063e51..a62db91 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -16,7 +16,7 @@ import ( func main() { log.Print("started") - env(".env") + env(".dev.env") ctx := context.Background() ctx, cancel := signal.NotifyContext(ctx, os.Interrupt, os.Kill, syscall.SIGTERM) @@ -36,12 +36,24 @@ func env(envFilePath string) { } func run(ctx context.Context) error { + client := tg.New(os.Getenv("TG_API")) + h := handler.NewHandler( + os.Getenv("GIT_BASE_URL"), + os.Getenv("GIT_TOKEN"), + os.Getenv("CLOUD_BASE_URL"), + os.Getenv("CLOUD_USER"), + os.Getenv("CLOUD_PASS"), + os.Getenv("YT_URL"), + os.Getenv("YT_TOKEN"), + ) + router := tgb.NewRouter(). - Message(handler.NewTicketHandler, tgb.TextHasPrefix("/new")). - Message(handler.PingHandler, tgb.Command("ping")). - Message(handler.NewRepoHandler, tgb.TextHasPrefix("/repo")) + Message(h.NewTicketHandler, tgb.TextHasPrefix("/new")). + Message(h.PingHandler, tgb.Command("ping")). + Message(h.NewRepoHandler, tgb.TextHasPrefix("/repo")). + Message(h.NewFolderHandler, tgb.TextHasPrefix("/folder")) return tgb.NewPoller( router, diff --git a/controller/controller.go b/controller/controller.go index aabf8bd..9a080ef 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -2,13 +2,41 @@ package controller import ( "fmt" - "os" "sync" + d "ticket-pimp/domain" "ticket-pimp/ext" ) -func Workflow(name string) (string, error) { - yt := ext.NewYT(os.Getenv("YT_URL"), os.Getenv("YT_TOKEN")) +type WorkflowController struct { + iGit ext.IGit + iCloud ext.ICloud + iYouTrack ext.IYouTrack +} + +func NewWorkflowController( + gitBaseURL, + gitToken, + cloudBaseURL, + cloudAuthUser, + cloudAuthPass, + ytBaseURL, + ytToken string, +) *WorkflowController { + return &WorkflowController{ + iGit: ext.NewGit(gitBaseURL, gitToken), + iCloud: ext.NewCloud(cloudBaseURL, cloudAuthUser, cloudAuthPass), + iYouTrack: ext.NewYT(ytBaseURL, ytToken), + } +} + +type IWorkflowController interface { + Workflow(name string) (string, error) + CreateRepo(name string) (*d.Git, error) + CreateFolder(name string) (*d.Folder, error) +} + +func (wc *WorkflowController) Workflow(name string) (string, error) { + yt := wc.iYouTrack projects, err := yt.GetProjects() @@ -16,7 +44,7 @@ func Workflow(name string) (string, error) { return "", err } - issue, err := yt.CreateIssue(projects[0].ID, name) + issue, err := yt.CreateIssue(projects[1].ID, name) if err != nil { return "", err @@ -24,60 +52,66 @@ func Workflow(name string) (string, error) { if issue != nil { var ( - git, gitBuild, folder string + git, gitBuild *d.Git + cloud *d.Folder ) var wg sync.WaitGroup wg.Add(3) - go func() { + go func(ref **d.Git) { defer wg.Done() - git, _ = CreateRepo(issue.Key, 0) - }() + *ref, _ = wc.CreateRepo(issue.Key) + }(&git) - go func() { + go func(ref **d.Git) { defer wg.Done() - gitBuild, _ = CreateRepo(issue.Key+"-build", 1) - }() + *ref, _ = wc.CreateRepo(issue.Key + "-build") + }(&gitBuild) - go func() { + go func(ref **d.Folder) { defer wg.Done() - folder = CreateFolder(issue.Key + " - " + issue.Summary) - }() + *ref, _ = wc.CreateFolder(issue.Key + " - " + issue.Summary) + }(&cloud) wg.Wait() - yt.UpdateIssue(issue, folder, git, gitBuild) + yt.UpdateIssue( + issue, + cloud.PrivateURL, + git.HtmlUrl, + fmt.Sprintf("ssh://%s/%s.git", gitBuild.SshUrl, gitBuild.FullName)) } return issue.Key, nil } -func CreateRepo(name string, param uint) (string, error) { - gb := ext.NewGit(os.Getenv("GIT_BASE_URL"), os.Getenv("GIT_TOKEN")) - repo, err := gb.NewRepo(name) - gb.AppsAsCollaboratorTo(repo) - - // Result string formatting: - if repo != nil { - switch param { - case 0: - return repo.HtmlUrl, err - case 1: - return fmt.Sprintf("ssh://%s/%s.git", repo.SshUrl, repo.FullName), err - default: - return repo.CloneUrl, err - } +func (wc *WorkflowController) CreateRepo(name string) (*d.Git, error) { + //Create git repository with iGit interface; + repo, err := wc.iGit.NewRepo(name) + if err != nil { + return nil, err } - return "", err -} - -func CreateFolder(name string) string { - oc := ext.NewCloud(os.Getenv("CLOUD_BASE_URL"), os.Getenv("CLOUD_USER"), os.Getenv("CLOUD_PASS")) - - cloud, _ := oc.CreateFolder(name) - if cloud != nil { - return cloud.FolderPath + //Set 'apps' as collaborator to created repository; + _, err = wc.iGit.AppsAsCollaboratorTo(repo) + if err != nil { + return nil, err } - return "no-folder" + + return repo, nil +} + +func (wc *WorkflowController) CreateFolder(name string) (*d.Folder, error) { + + //Create ownCloud folder w/ iCloud interface; + cloud, err := wc.iCloud.CreateFolder(name) + if cloud == nil { + return nil, err + } + + /* [ ] Experimental call: + wc.iCloud.ShareToExternals(cloud) + */ + + return cloud, err } diff --git a/domain/cloud.go b/domain/cloud.go new file mode 100644 index 0000000..84c66b2 --- /dev/null +++ b/domain/cloud.go @@ -0,0 +1,7 @@ +package domain + +type Folder struct { + Title string // k + PathTo string // /temp/k + PrivateURL string // http://domain/apps/files/?dir=/temp/k OR http://domain/f/3333 +} diff --git a/domain/git.go b/domain/git.go index 31882a3..083805b 100644 --- a/domain/git.go +++ b/domain/git.go @@ -1,11 +1,11 @@ package domain type Git struct { - Name string `json:"name"` - FullName string `json:"full_name"` + Name string `json:"name"` // "poop" + FullName string `json:"full_name"` // "developer/poop" Private bool `json:"private"` - Url string `json:"url"` - CloneUrl string `json:"clone_url"` - HtmlUrl string `json:"Html_url"` - SshUrl string `json:"ssh_url"` + Url string `json:"url"` // "http://localhost:8081/api/v3/repos/developer/poop" + CloneUrl string `json:"clone_url"` // "http://localhost:8081/git/developer/poop.git" + HtmlUrl string `json:"Html_url"` // "http://localhost:8081/developer/poop" + SshUrl string `json:"ssh_url"` // ?! } diff --git a/domain/youtrack.go b/domain/youtrack.go new file mode 100644 index 0000000..6f47f2a --- /dev/null +++ b/domain/youtrack.go @@ -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"` +} diff --git a/ext/cloud.go b/ext/cloud.go index 54d4add..3d111ff 100644 --- a/ext/cloud.go +++ b/ext/cloud.go @@ -1,42 +1,103 @@ package ext import ( + "fmt" "os" + "strconv" + d "ticket-pimp/domain" + "ticket-pimp/helpers" "time" ) -func NewCloud(base, user, pass string) *Client { +type Cloud struct { + *Client +} + +type ICloud interface { + CreateFolder(name string) (*d.Folder, error) + ShareToExternals(cloud *d.Folder) (*d.Folder, error) +} + +func NewCloud(base, user, pass string) *Cloud { client := NewClient(). SetTimeout(5*time.Second). SetCommonBasicAuth(user, pass). SetBaseURL(base) - return &Client{ - client, + return &Cloud{ + Client: &Client{ + client, + }, } } -type Cloud struct { - FolderName string - FolderPath string -} +func (c *Cloud) CreateFolder(name string) (*d.Folder, error) { + rootDir := os.Getenv("ROOTDIR") + user := os.Getenv("CLOUD_USER") -func (c *Client) CreateFolder(name string) (*Cloud, error) { + davPath := "/remote.php/dav/files/" + parentPath := "/apps/files/?dir=" - cloud := Cloud{ - FolderName: name, - FolderPath: "", + name = helpers.GitNaming(name) + + cloud := d.Folder{ + Title: name, + PrivateURL: "", } - pathName := os.Getenv("HOMEPATH") + name + requestPath := davPath + user + rootDir + name - resp, err := c.R(). - Send("MKCOL", pathName) + cloud.PathTo = parentPath + rootDir + name + + resp, _ := c.R(). + Send("MKCOL", requestPath) if resp.IsSuccessState() { - cloud.FolderPath = c.BaseURL + os.Getenv("FOLDER_PATH") + name + // Set stupid URL to the d entity + cloud.PrivateURL = c.BaseURL + cloud.PathTo + + // Try to set short URL to the d entity + if err := c.setPrivateURL(requestPath, &cloud); err != nil { + return &cloud, err + } } - return &cloud, err + return &cloud, nil +} + +func (c *Cloud) setPrivateURL(requestPath string, cloud *d.Folder) error { + + payload := []byte(``) + + // Deprecated: Read XML file + /* + xmlFile, err := ioutil.ReadFile("./fileid.xml") // moved into this method as a string.. + + if err != nil { + return fmt.Errorf("request xml file error: %v", err) + } + */ + + resp, _ := c.R(). + SetBody(payload). + Send("PROPFIND", requestPath) + + if resp.Err != nil { + return resp.Err + } + + id := helpers.GetFileIDFromRespBody(resp.Bytes()) + + if id == 0 { + return fmt.Errorf("unable to get fileid") + } + + cloud.PrivateURL = c.BaseURL + "/f/" + strconv.Itoa(id) + + return nil +} + +func (c *Cloud) ShareToExternals(cloud *d.Folder) (*d.Folder, error) { + return nil, nil } diff --git a/ext/git.go b/ext/git.go index f6bc9cf..7b47657 100644 --- a/ext/git.go +++ b/ext/git.go @@ -10,7 +10,11 @@ import ( type Git struct { *Client - *domain.Git +} + +type IGit interface { + NewRepo(string) (*domain.Git, error) + AppsAsCollaboratorTo(*domain.Git) (*domain.Git, error) } func NewGit(base, token string) *Git { @@ -28,15 +32,6 @@ func NewGit(base, token string) *Git { return &Git{ Client: &Client{client}, - Git: &domain.Git{ - Name: "", - FullName: "", - Private: true, - Url: "", - CloneUrl: "", - HtmlUrl: "", - SshUrl: "", - }, } } @@ -58,32 +53,37 @@ func (gb *Git) NewRepo(name string) (*domain.Git, error) { } var git domain.Git + git.Private = true - resp, err := gb.R(). + resp, _ := gb.R(). SetBody(&payload). SetSuccessResult(&git). Post("/user/repos") - //Post("/orgs/apps/repos") - if err != nil { - log.Print(resp) + if resp.Err != nil { + log.Print(resp.Err) + return nil, resp.Err } - return &git, err + return &git, nil } -func (gb *Client) AppsAsCollaboratorTo(git *domain.Git) (*domain.Git, error) { - payloadPermission := permissionRequest{ +func (gb *Git) AppsAsCollaboratorTo(git *domain.Git) (*domain.Git, error) { + + payload := permissionRequest{ Perm: "admin", } - resp, err := gb.R(). - SetBody(&payloadPermission). - Put("/repos/" + os.Getenv("GIT_USER") + "/" + git.Name + "/collaborators/apps") + respURL := "/repos/" + os.Getenv("GIT_USER") + "/" + git.Name + "/collaborators/apps" - if err != nil { - log.Print(resp) + resp, _ := gb.R(). + SetBody(&payload). + Put(respURL) + + if resp.Err != nil { + log.Print(resp.Err) + return nil, resp.Err } - return git, err + return git, nil } diff --git a/ext/yt.go b/ext/yt.go index 92e89c3..2d23b2f 100644 --- a/ext/yt.go +++ b/ext/yt.go @@ -5,6 +5,8 @@ import ( "log" "time" + d "ticket-pimp/domain" + "github.com/imroc/req/v3" ) @@ -12,6 +14,12 @@ type youtrack struct { *req.Client } +type IYouTrack interface { + GetProjects() ([]d.Project, error) + CreateIssue(projectID, name string) (*d.IssueCreateRequest, error) + UpdateIssue(issue *d.IssueCreateRequest, folder, git, gitBuild string) (*d.IssueUpdateRequest, error) +} + func NewYT(base, token string) *youtrack { headers := map[string]string{ "Accept": "application/json", @@ -29,51 +37,33 @@ func NewYT(base, token string) *youtrack { } } -type Project struct { - ID string `json:"id"` - ShortName string `json:"shortName"` - Name string `json:"name"` -} - // GetProjects // 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(). + resp, _ := yt.R(). EnableDump(). SetQueryParam("fields", "id,name,shortName"). SetSuccessResult(&projects). Get("/admin/projects") // Check if the request failed; - if err != nil { - return nil, fmt.Errorf("some problem with YT request. error message: %v", err) + if resp.Err != nil { + return nil, fmt.Errorf("some problem with YT request. error message: %v", resp.Err) } 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 // 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; - issue := IssueCreateRequest{ - ProjectID: ProjectID{ + issue := d.IssueCreateRequest{ + ProjectID: d.ProjectID{ ID: projectID, //"id":"0-2" }, Summary: name, @@ -81,40 +71,25 @@ func (yt *youtrack) CreateIssue(projectID, name string) (*IssueCreateRequest, er } // Push issue to the YT; - _, err := yt.R(). + resp, _ := yt.R(). SetQueryParam("fields", "idReadable,id"). SetBody(&issue). SetSuccessResult(&issue). Post("/issues") // Check if the request failed; - if err != nil { - return nil, fmt.Errorf("some problem with YT request. error message: %v", err) + if resp.Err != nil { + return nil, fmt.Errorf("some problem with YT request. error message: %v", resp.Err) } return &issue, nil } -type IssueUpdateRequest struct { - 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) { +func (yt *youtrack) UpdateIssue(issue *d.IssueCreateRequest, folder, git, gitBuild string) (*d.IssueUpdateRequest, error) { // Set Folder, Git, GitBuild to the Issue: - update := IssueUpdateRequest{ + update := d.IssueUpdateRequest{ IssueCreateRequest: *issue, - CustomFields: []CustomField{ + CustomFields: []d.CustomField{ { Name: "Директория графики", Type: "SimpleIssueCustomField", @@ -134,14 +109,14 @@ func (yt *youtrack) UpdateIssue(issue *IssueCreateRequest, folder, git, gitBuild } // Push issue update to YT - resp, err := yt.R(). + resp, _ := yt.R(). SetBody(&update). SetSuccessResult(&issue). Post("/issues/" + issue.Key) // Check if the request failed; - if err != nil { - return nil, fmt.Errorf("some problem with YT request. error message: %v", err) + if resp.Err != nil { + return nil, fmt.Errorf("some problem with YT request. error message: %v", resp.Err) } if !resp.IsSuccessState() { diff --git a/go.mod b/go.mod index 8b44822..9a3ff88 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( 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/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 golang.org/x/crypto v0.9.0 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect diff --git a/go.sum b/go.sum index 9db009a..8242e11 100644 --- a/go.sum +++ b/go.sum @@ -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/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= diff --git a/handler/handler.go b/handler/handler.go index ef86364..efd6528 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -6,11 +6,108 @@ import ( "fmt" "strings" "ticket-pimp/controller" + d "ticket-pimp/domain" "github.com/mr-linch/go-tg" "github.com/mr-linch/go-tg/tgb" ) +type Handler struct { + workflow controller.IWorkflowController +} + +func NewHandler(gitBaseURL, gitToken, cloudBaseURL, cloudAuthUser, cloudAuthPass, ytBaseURL, ytToken string) *Handler { + return &Handler{ + workflow: controller.NewWorkflowController( + gitBaseURL, + gitToken, + cloudBaseURL, + cloudAuthUser, + cloudAuthPass, + ytBaseURL, + ytToken), + } +} + +func (h *Handler) PingHandler(ctx context.Context, mu *tgb.MessageUpdate) error { + return mu.Answer("pong").DoVoid(ctx) +} + +type git struct { + name string + url string + + git string + ssh string +} + +func newGit(d *d.Git) *git { + return &git{ + name: d.Name, + url: d.HtmlUrl, + git: d.CloneUrl, + ssh: fmt.Sprintf("ssh://%s/%s.git", d.SshUrl, d.FullName), + } +} + +// FYI: Telegram doesn't renders this hyperlink, if the url is localhost 🤷‍♂️ +func (g *git) prepareAnswer() string { + return tg.HTML.Text( + tg.HTML.Line( + "Repo ", + tg.HTML.Link(g.name, g.url), + "has been created!", + ), + ) +} + +func (h *Handler) NewRepoHandler(ctx context.Context, mu *tgb.MessageUpdate) error { + + str := strings.Replace(mu.Text, "/repo", "", 1) + + if str == "" { + return errors.New("empty command provided") + } + + var g *d.Git + g, err := h.workflow.CreateRepo(str) + + if err != nil { + return mu.Answer(errorAnswer(err.Error())).ParseMode(tg.HTML).DoVoid(ctx) + } + + resp := newGit(g).prepareAnswer() + + return mu.Answer(resp).ParseMode(tg.HTML).DoVoid(ctx) +} + +func (h *Handler) NewFolderHandler(ctx context.Context, mu *tgb.MessageUpdate) error { + + str := strings.Replace(mu.Text, "/folder", "", 1) + + if str == "" { + return errors.New("empty command provided") + } + + cloud, err := h.workflow.CreateFolder(str) + + if err != nil { + return mu.Answer(errorAnswer(err.Error())).ParseMode(tg.HTML).DoVoid(ctx) + } + + answer := tg.HTML.Text( + tg.HTML.Line( + "✨ Shiny folder", + tg.HTML.Link(cloud.Title, cloud.PrivateURL), + "has been created!", + ), + ) + + return mu.Answer(answer). + ParseMode(tg.HTML). + DoVoid(ctx) +} + func errorAnswer(errorMsg string) string { return tg.HTML.Text( tg.HTML.Line( @@ -19,7 +116,7 @@ func errorAnswer(errorMsg string) string { ) } -func NewTicketHandler(ctx context.Context, mu *tgb.MessageUpdate) error { +func (h *Handler) NewTicketHandler(ctx context.Context, mu *tgb.MessageUpdate) error { str := strings.Replace(mu.Text, "/new", "", 1) @@ -27,7 +124,7 @@ func NewTicketHandler(ctx context.Context, mu *tgb.MessageUpdate) error { return errors.New("empty command provided") } - issueKeyStr, err := controller.Workflow(str) + issueKeyStr, err := h.workflow.Workflow(str) if err != nil { return mu.Answer(errorAnswer(err.Error())).ParseMode(tg.HTML).DoVoid(ctx) @@ -45,34 +142,3 @@ func newTicketAnswer(name string) string { ), ) } - -func NewRepoHandler(ctx context.Context, mu *tgb.MessageUpdate) error { - - str := strings.Replace(mu.Text, "/repo", "", 1) - - if str == "" { - return errors.New("empty command provided") - } - - repoStr, err := controller.CreateRepo(str, 0) - - if err != nil { - return mu.Answer(errorAnswer(err.Error())).ParseMode(tg.HTML).DoVoid(ctx) - } - - return mu.Answer(newRepoAnswer(repoStr)).ParseMode(tg.HTML).DoVoid(ctx) -} - -func newRepoAnswer(name string) string { - return tg.HTML.Text( - tg.HTML.Line( - "Repo ", - name, - "has been created!", - ), - ) -} - -func PingHandler(ctx context.Context, mu *tgb.MessageUpdate) error { - return mu.Answer("pong").DoVoid(ctx) -} diff --git a/helpers/helpers.go b/helpers/helpers.go index 93c17ba..8a12bfd 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -1,7 +1,9 @@ package helpers import ( + "encoding/xml" "regexp" + "strconv" "strings" ) @@ -22,3 +24,37 @@ func GitNaming(input string) string { // Join words and return return strings.Join(words, "-") } + +type MultistatusObj struct { + XMLName xml.Name `xml:"multistatus"` + Multistatus struct { + XMLName xml.Name `xml:"response"` + Propstat struct { + XMLName xml.Name `xml:"propstat"` + Prop struct { + XMLName xml.Name `xml:"prop"` + FileID struct { + XMLName xml.Name `xml:"fileid"` + ID string `xml:",chardata"` + } + } + } + } +} + +func GetFileIDFromRespBody(str []byte) int { + + var multi MultistatusObj + + err := xml.Unmarshal(str, &multi) + if err != nil { + return 0 + } + + id, err := strconv.Atoi(multi.Multistatus.Propstat.Prop.FileID.ID) + if err != nil { + return 0 + } + + return id +} diff --git a/helpers/helpers_test.go b/helpers/helpers_test.go index bf22d06..3e877a4 100644 --- a/helpers/helpers_test.go +++ b/helpers/helpers_test.go @@ -1,6 +1,8 @@ package helpers -import "testing" +import ( + "testing" +) type test struct { arg, expected string diff --git a/helpers/xml_test.go b/helpers/xml_test.go new file mode 100644 index 0000000..30fccee --- /dev/null +++ b/helpers/xml_test.go @@ -0,0 +1,17 @@ +package helpers + +import ( + "testing" +) + +const ( + EXAMPLE = "\n/remote.php/dav/files/naudachu/temp/id/33225HTTP/1.1 200 OK\n" +) + +// [ ] todo normal test... +func TestGetFileID(t *testing.T) { + + if output := GetFileIDFromRespBody([]byte(EXAMPLE)); output != 33225 { + t.Errorf("Output %q not equal to expected %q", output, 33225) + } +}