package api
import (
"encoding/json"
"fmt"
"net/url"
"strconv"
)
type Discussion struct {
ID string `json:"id"`
Number int `json:"number"`
Title string `json:"title"`
MdContent string `json:"md_content,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Author *User `json:"author"`
IsLock int `json:"is_lock"`
IsPin int `json:"is_pin"`
IsCategoryPin int `json:"is_category_pin"`
IsClosed int `json:"is_closed"`
IsAnswered int `json:"is_answered"`
CommentTotal int `json:"comment_total"`
Category json.RawMessage `json:"category,omitempty"`
Namespace json.RawMessage `json:"namespace,omitempty"`
Vote json.RawMessage `json:"vote,omitempty"`
VoteOptions json.RawMessage `json:"vote_options,omitempty"`
Labels json.RawMessage `json:"labels,omitempty"`
}
type ListOrgDiscussionsOptions struct {
Page int
PerPage int
Sort string
Direction string
Search string
}
func ListOrgDiscussions(client *Client, org string, opts *ListOrgDiscussionsOptions) ([]*Discussion, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss"
if opts != nil {
endpoint += newQueryBuilder().
SetInt("page", opts.Page).
SetInt("per_page", opts.PerPage).
Set("sort", opts.Sort).
Set("direction", opts.Direction).
Set("search", opts.Search).
String()
}
var discussions []*Discussion
if err := client.Get(endpoint, &discussions); err != nil {
return nil, fmt.Errorf("failed to list org discussions: %w", err)
}
return discussions, nil
}
func GetOrgDiscussion(client *Client, org string, number int) (*Discussion, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number)
var d Discussion
if err := client.Get(endpoint, &d); err != nil {
return nil, fmt.Errorf("failed to get org discussion: %w", err)
}
return &d, nil
}
func ListRepoDiscussions(client *Client, owner, repo string, opts *ListOrgDiscussionsOptions) ([]*Discussion, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss"
if opts != nil {
endpoint += newQueryBuilder().
SetInt("page", opts.Page).
SetInt("per_page", opts.PerPage).
Set("sort", opts.Sort).
Set("direction", opts.Direction).
Set("search", opts.Search).
String()
}
var discussions []*Discussion
if err := client.Get(endpoint, &discussions); err != nil {
return nil, fmt.Errorf("failed to list repo discussions: %w", err)
}
return discussions, nil
}
func GetRepoDiscussion(client *Client, owner, repo string, number int) (*Discussion, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number)
var d Discussion
if err := client.Get(endpoint, &d); err != nil {
return nil, fmt.Errorf("failed to get repo discussion: %w", err)
}
return &d, nil
}
type DiscussionComment struct {
ID string `json:"id"`
CreatedAt string `json:"created_at"`
Author *User `json:"author"`
Content string `json:"content"`
MdContent string `json:"md_content,omitempty"`
IsHide int `json:"is_hide"`
ReplyTotal int `json:"reply_total"`
LikeTotal int `json:"like_total"`
IsLike bool `json:"is_like"`
IsDeleted int `json:"is_deleted"`
IsRemark int `json:"is_remark"`
}
type ListDiscussionCommentsOptions struct {
Page int
PerPage int
Order string
}
func ListOrgDiscussionComments(client *Client, org string, number int, opts *ListDiscussionCommentsOptions) ([]*DiscussionComment, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number) + "/comment"
endpoint = appendDiscussionCommentParams(endpoint, opts)
var comments []*DiscussionComment
if err := client.Get(endpoint, &comments); err != nil {
return nil, fmt.Errorf("failed to list org discussion comments: %w", err)
}
return comments, nil
}
func ListOrgDiscussionCommentReplies(client *Client, org string, number int, commentID string, opts *ListDiscussionCommentsOptions) ([]*DiscussionComment, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number) + "/comment/" + url.PathEscape(commentID) + "/reply"
endpoint = appendDiscussionCommentParams(endpoint, opts)
var replies []*DiscussionComment
if err := client.Get(endpoint, &replies); err != nil {
return nil, fmt.Errorf("failed to list org discussion comment replies: %w", err)
}
return replies, nil
}
func ListRepoDiscussionComments(client *Client, owner, repo string, number int, opts *ListDiscussionCommentsOptions) ([]*DiscussionComment, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number) + "/comment"
endpoint = appendDiscussionCommentParams(endpoint, opts)
var comments []*DiscussionComment
if err := client.Get(endpoint, &comments); err != nil {
return nil, fmt.Errorf("failed to list repo discussion comments: %w", err)
}
return comments, nil
}
func ListRepoDiscussionCommentReplies(client *Client, owner, repo string, number int, commentID string, opts *ListDiscussionCommentsOptions) ([]*DiscussionComment, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number) + "/comment/" + url.PathEscape(commentID) + "/reply"
endpoint = appendDiscussionCommentParams(endpoint, opts)
var replies []*DiscussionComment
if err := client.Get(endpoint, &replies); err != nil {
return nil, fmt.Errorf("failed to list repo discussion comment replies: %w", err)
}
return replies, nil
}
func appendDiscussionCommentParams(endpoint string, opts *ListDiscussionCommentsOptions) string {
if opts == nil {
return endpoint
}
return endpoint + newQueryBuilder().
SetInt("page", opts.Page).
SetInt("per_page", opts.PerPage).
Set("order", opts.Order).
String()
}
type CreateOrgDiscussionOptions struct {
Title string `json:"title"`
MdContent string `json:"md_content,omitempty"`
}
func CreateOrgDiscussion(client *Client, org string, opts *CreateOrgDiscussionOptions) (*Discussion, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss"
var d Discussion
if err := client.Post(endpoint, opts, &d); err != nil {
return nil, fmt.Errorf("failed to create org discussion: %w", err)
}
return &d, nil
}
type UpdateOrgDiscussionOptions struct {
Title string `json:"title,omitempty"`
MdContent string `json:"md_content,omitempty"`
}
func UpdateOrgDiscussion(client *Client, org string, number int, opts *UpdateOrgDiscussionOptions) (*Discussion, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number)
var d Discussion
if err := client.Patch(endpoint, opts, &d); err != nil {
return nil, fmt.Errorf("failed to update org discussion: %w", err)
}
return &d, nil
}
func DeleteOrgDiscussion(client *Client, org string, number int) error {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number)
if err := client.Delete(endpoint); err != nil {
return fmt.Errorf("failed to delete org discussion: %w", err)
}
return nil
}
type CreateOrgDiscussionCommentOptions struct {
MdContent string `json:"md_content"`
}
func CreateOrgDiscussionComment(client *Client, org string, number int, opts *CreateOrgDiscussionCommentOptions) (*DiscussionComment, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number) + "/comment"
var c DiscussionComment
if err := client.Post(endpoint, opts, &c); err != nil {
return nil, fmt.Errorf("failed to create org discussion comment: %w", err)
}
return &c, nil
}
type UpdateOrgDiscussionCommentOptions struct {
MdContent string `json:"md_content"`
}
func UpdateOrgDiscussionComment(client *Client, org string, number int, commentID string, opts *UpdateOrgDiscussionCommentOptions) (*DiscussionComment, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number) + "/comment/" + url.PathEscape(commentID)
var c DiscussionComment
if err := client.Patch(endpoint, opts, &c); err != nil {
return nil, fmt.Errorf("failed to update org discussion comment: %w", err)
}
return &c, nil
}
func DeleteOrgDiscussionComment(client *Client, org string, number int, commentID string) error {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number) + "/comment/" + url.PathEscape(commentID)
if err := client.Delete(endpoint); err != nil {
return fmt.Errorf("failed to delete org discussion comment: %w", err)
}
return nil
}
type ReplyOrgDiscussionCommentOptions struct {
MdContent string `json:"md_content"`
}
func ReplyOrgDiscussionComment(client *Client, org string, number int, commentID string, opts *ReplyOrgDiscussionCommentOptions) (*DiscussionComment, error) {
endpoint := "/orgs/" + url.PathEscape(org) + "/discuss/" + strconv.Itoa(number) + "/comment/" + url.PathEscape(commentID) + "/reply"
var c DiscussionComment
if err := client.Post(endpoint, opts, &c); err != nil {
return nil, fmt.Errorf("failed to reply org discussion comment: %w", err)
}
return &c, nil
}
type CreateRepoDiscussionOptions struct {
Title string `json:"title"`
MdContent string `json:"md_content,omitempty"`
}
func CreateRepoDiscussion(client *Client, owner, repo string, opts *CreateRepoDiscussionOptions) (*Discussion, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss"
var d Discussion
if err := client.Post(endpoint, opts, &d); err != nil {
return nil, fmt.Errorf("failed to create repo discussion: %w", err)
}
return &d, nil
}
type UpdateRepoDiscussionOptions struct {
Title string `json:"title,omitempty"`
MdContent string `json:"md_content,omitempty"`
}
func UpdateRepoDiscussion(client *Client, owner, repo string, number int, opts *UpdateRepoDiscussionOptions) (*Discussion, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number)
var d Discussion
if err := client.Patch(endpoint, opts, &d); err != nil {
return nil, fmt.Errorf("failed to update repo discussion: %w", err)
}
return &d, nil
}
func DeleteRepoDiscussion(client *Client, owner, repo string, number int) error {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number)
if err := client.Delete(endpoint); err != nil {
return fmt.Errorf("failed to delete repo discussion: %w", err)
}
return nil
}
type CreateRepoDiscussionCommentOptions struct {
MdContent string `json:"md_content"`
}
func CreateRepoDiscussionComment(client *Client, owner, repo string, number int, opts *CreateRepoDiscussionCommentOptions) (*DiscussionComment, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number) + "/comment"
var c DiscussionComment
if err := client.Post(endpoint, opts, &c); err != nil {
return nil, fmt.Errorf("failed to create repo discussion comment: %w", err)
}
return &c, nil
}
type UpdateRepoDiscussionCommentOptions struct {
MdContent string `json:"md_content"`
}
func UpdateRepoDiscussionComment(client *Client, owner, repo string, number int, commentID string, opts *UpdateRepoDiscussionCommentOptions) (*DiscussionComment, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number) + "/comment/" + url.PathEscape(commentID)
var c DiscussionComment
if err := client.Patch(endpoint, opts, &c); err != nil {
return nil, fmt.Errorf("failed to update repo discussion comment: %w", err)
}
return &c, nil
}
func DeleteRepoDiscussionComment(client *Client, owner, repo string, number int, commentID string) error {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number) + "/comment/" + url.PathEscape(commentID)
if err := client.Delete(endpoint); err != nil {
return fmt.Errorf("failed to delete repo discussion comment: %w", err)
}
return nil
}
type ReplyRepoDiscussionCommentOptions struct {
MdContent string `json:"md_content"`
}
func ReplyRepoDiscussionComment(client *Client, owner, repo string, number int, commentID string, opts *ReplyRepoDiscussionCommentOptions) (*DiscussionComment, error) {
endpoint := "/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(repo) + "/discuss/" + strconv.Itoa(number) + "/comment/" + url.PathEscape(commentID) + "/reply"
var c DiscussionComment
if err := client.Post(endpoint, opts, &c); err != nil {
return nil, fmt.Errorf("failed to reply repo discussion comment: %w", err)
}
return &c, nil
}