package bitbucket import ( "encoding/json" "fmt" "net/url" "strings" ) type Issues struct { c *Client } func (p *Issues) Gets(io *IssuesOptions) (interface{}, error) { url, err := url.Parse(p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/") if err != nil { return nil, err } if io.States != nil && len(io.States) != 0 { query := url.Query() for _, state := range io.States { query.Set("state", state) } url.RawQuery = query.Encode() } if io.Query != "" { query := url.Query() query.Set("q", io.Query) url.RawQuery = query.Encode() } if io.Sort != "" { query := url.Query() query.Set("sort", io.Sort) url.RawQuery = query.Encode() } return p.c.executePaginated("GET", url.String(), "", nil) } func (p *Issues) Get(io *IssuesOptions) (interface{}, error) { urlStr := p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/" + io.ID return p.c.execute("GET", urlStr, "") } func (p *Issues) Delete(io *IssuesOptions) (interface{}, error) { urlStr := p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/" + io.ID return p.c.execute("DELETE", urlStr, "") } func (p *Issues) Update(io *IssuesOptions) (interface{}, error) { data, err := p.buildIssueBody(io) if err != nil { return nil, err } urlStr := p.c.requestUrl("/repositories/%s/%s/issues/%s", io.Owner, io.RepoSlug, io.ID) return p.c.execute("PUT", urlStr, data) } func (p *Issues) Create(io *IssuesOptions) (interface{}, error) { data, err := p.buildIssueBody(io) if err != nil { return nil, err } urlStr := p.c.requestUrl("/repositories/%s/%s/issues", io.Owner, io.RepoSlug) return p.c.executeWithContext("POST", urlStr, data, io.ctx) } func (p *Issues) GetVote(io *IssuesOptions) (bool, interface{}, error) { // A 404 indicates that the user hasn't voted urlStr := p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/" + io.ID + "/vote" data, err := p.c.execute("GET", urlStr, "") if err != nil && strings.HasPrefix(err.Error(), "404") { return false, data, nil } return true, nil, err } func (p *Issues) PutVote(io *IssuesOptions) error { urlStr := p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/" + io.ID + "/vote" _, err := p.c.execute("PUT", urlStr, "") return err } func (p *Issues) DeleteVote(io *IssuesOptions) error { urlStr := p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/" + io.ID + "/vote" _, err := p.c.execute("DELETE", urlStr, "") return err } func (p *Issues) GetWatch(io *IssuesOptions) (bool, interface{}, error) { // A 404 indicates that the user hasn't watchd urlStr := p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/" + io.ID + "/watch" data, err := p.c.execute("GET", urlStr, "") if err != nil && strings.HasPrefix(err.Error(), "404") { return false, data, nil } return true, nil, err } func (p *Issues) PutWatch(io *IssuesOptions) error { urlStr := p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/" + io.ID + "/watch" _, err := p.c.execute("PUT", urlStr, "") return err } func (p *Issues) DeleteWatch(io *IssuesOptions) error { urlStr := p.c.GetApiBaseURL() + "/repositories/" + io.Owner + "/" + io.RepoSlug + "/issues/" + io.ID + "/watch" _, err := p.c.execute("DELETE", urlStr, "") return err } func (p *Issues) buildIssueBody(io *IssuesOptions) (string, error) { body := map[string]interface{}{} // This feld is required if io.Title != "" { body["title"] = io.Title } if io.Content != "" { body["content"] = map[string]interface{}{ "raw": io.Content, } } if io.State != "" { body["state"] = io.State } if io.Kind != "" { body["kind"] = io.Kind } if io.Priority != "" { body["priority"] = io.Priority } if io.Milestone != "" { body["milestone"] = map[string]interface{}{ "name": io.Milestone, } } if io.Component != "" { body["component"] = map[string]interface{}{ "name": io.Component, } } if io.Version != "" { body["version"] = map[string]interface{}{ "name": io.Version, } } if io.Assignee != "" { body["assignee"] = map[string]interface{}{ "uuid": io.Assignee, } } data, err := json.Marshal(body) if err != nil { return "", err } return string(data), nil } func (p *Issues) GetComments(ico *IssueCommentsOptions) (interface{}, error) { url, err := url.Parse(p.c.GetApiBaseURL() + "/repositories/" + ico.Owner + "/" + ico.RepoSlug + "/issues/" + ico.ID + "/comments") if err != nil { return nil, err } if ico.Query != "" { query := url.Query() query.Set("q", ico.Query) url.RawQuery = query.Encode() } if ico.Sort != "" { query := url.Query() query.Set("sort", ico.Sort) url.RawQuery = query.Encode() } return p.c.execute("GET", url.String(), "") } func (p *Issues) CreateComment(ico *IssueCommentsOptions) (interface{}, error) { urlStr := p.c.requestUrl("/repositories/%s/%s/issues/%s/comments", ico.Owner, ico.RepoSlug, ico.ID) // as the body/map only takes a single value, I do not think it's useful to create a seperate method here data, err := p.buildCommentBody(ico) if err != nil { return nil, err } return p.c.executeWithContext("POST", urlStr, data, ico.ctx) } func (p *Issues) GetComment(ico *IssueCommentsOptions) (interface{}, error) { urlStr := p.c.GetApiBaseURL() + "/repositories/" + ico.Owner + "/" + ico.RepoSlug + "/issues/" + ico.ID + "/comments/" + ico.CommentID return p.c.execute("GET", urlStr, "") } func (p *Issues) UpdateComment(ico *IssueCommentsOptions) (interface{}, error) { urlStr := p.c.requestUrl("/repositories/%s/%s/issues/%s/comments/%s", ico.Owner, ico.RepoSlug, ico.ID, ico.CommentID) // as the body/map only takes a single value, I do not think it's useful to create a seperate method here data, err := p.buildCommentBody(ico) if err != nil { return nil, err } return p.c.execute("PUT", urlStr, data) } func (p *Issues) DeleteComment(ico *IssueCommentsOptions) (interface{}, error) { urlStr := p.c.GetApiBaseURL() + "/repositories/" + ico.Owner + "/" + ico.RepoSlug + "/issues/" + ico.ID + "/comments/" + ico.CommentID return p.c.execute("DELETE", urlStr, "") } func (p *Issues) buildCommentBody(ico *IssueCommentsOptions) (string, error) { body := map[string]interface{}{} body["content"] = map[string]interface{}{ "raw": ico.CommentContent, } data, err := json.Marshal(body) if err != nil { return "", err } return string(data), nil } func (p *Issues) GetChanges(ico *IssueChangesOptions) (interface{}, error) { url, err := url.Parse(p.c.GetApiBaseURL() + "/repositories/" + ico.Owner + "/" + ico.RepoSlug + "/issues/" + ico.ID + "/changes") if err != nil { return nil, err } if ico.Query != "" { query := url.Query() query.Set("q", ico.Query) url.RawQuery = query.Encode() } if ico.Sort != "" { query := url.Query() query.Set("sort", ico.Sort) url.RawQuery = query.Encode() } return p.c.execute("GET", url.String(), "") } func (p *Issues) CreateChange(ico *IssueChangesOptions) (interface{}, error) { url, err := url.Parse(p.c.GetApiBaseURL() + "/repositories/" + ico.Owner + "/" + ico.RepoSlug + "/issues/" + ico.ID + "/changes") if err != nil { return nil, err } body := map[string]interface{}{} if ico.Message != "" { body["message"] = map[string]interface{}{ "raw": ico.Message, } } changes := map[string]interface{}{} for _, change := range ico.Changes { changes[change.Type] = map[string]interface{}{ "new": change.NewValue, } } if len(changes) > 0 { body["changes"] = changes } data, err := json.Marshal(body) if err != nil { return "", err } fmt.Printf("data %s", data) return p.c.executeWithContext("POST", url.String(), string(data), ico.ctx) } func (p *Issues) GetChange(ico *IssueChangesOptions) (interface{}, error) { urlStr := p.c.GetApiBaseURL() + "/repositories/" + ico.Owner + "/" + ico.RepoSlug + "/issues/" + ico.ID + "/changes/" + ico.ChangeID return p.c.execute("GET", urlStr, "") }