代码拉取完成,页面将自动刷新
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
)
// GiteeClient Gitee API 客户端
type GiteeClient struct {
AccessToken string
Owner string
Repo string
BaseURL string
}
// NewGiteeClient 创建新的 Gitee 客户端
func NewGiteeClient(accessToken, owner, repo string) *GiteeClient {
return &GiteeClient{
AccessToken: accessToken,
Owner: owner,
Repo: repo,
BaseURL: "https://gitee.com/api/v5",
}
}
// User 用户信息
type User struct {
ID int `json:"id"`
Login string `json:"login"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
HTMLURL string `json:"html_url"`
FollowersURL string `json:"followers_url"`
FollowingURL string `json:"following_url"`
Type string `json:"type"`
}
// Issue Issue 结构(帖子)
type Issue struct {
ID int `json:"id"`
URL string `json:"url"`
RepositoryURL string `json:"repository_url"`
LabelsURL string `json:"labels_url"`
CommentsURL string `json:"comments_url"`
HTMLURL string `json:"html_url"`
ParentURL *string `json:"parent_url"`
Number string `json:"number"`
ParentID int `json:"parent_id"`
Depth int `json:"depth"`
State string `json:"state"`
Title string `json:"title"`
Body string `json:"body"`
User User `json:"user"`
Labels []Label `json:"labels"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// Label 标签
type Label struct {
ID int `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
}
// Comment 评论结构(回帖)
type Comment struct {
ID int `json:"id"`
Body string `json:"body"`
User User `json:"user"`
Source *string `json:"source"`
Target Target `json:"target"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// Target 评论目标
type Target struct {
Issue *IssueTarget `json:"issue"`
PullRequest *string `json:"pull_request"`
}
// IssueTarget Issue 目标信息
type IssueTarget struct {
ID int `json:"id"`
Title string `json:"title"`
Number string `json:"number"`
}
// CreateIssueRequest 创建 Issue 请求
type CreateIssueRequest struct {
Title string `json:"title"`
Body string `json:"body,omitempty"`
SecurityHole string `json:"security_hole,omitempty"` // "true" 或 "false"
Labels string `json:"labels,omitempty"` // 逗号分隔的标签
}
// UpdateIssueRequest 更新 Issue 请求
type UpdateIssueRequest struct {
State string `json:"state,omitempty"` // "open" 或 "closed"
Title string `json:"title,omitempty"`
Body string `json:"body,omitempty"`
Labels string `json:"labels,omitempty"` // 逗号分隔的标签
}
// CreateCommentRequest 创建评论请求
type CreateCommentRequest struct {
Body string `json:"body"`
}
// ListIssuesOptions 获取 Issues 列表的选项
type ListIssuesOptions struct {
State string // "open", "closed", "all",默认 "open"
Sort string // "created", "updated", "comments",默认 "created"
Direction string // "asc", "desc",默认 "desc"
Page int // 页码,默认 1
PerPage int // 每页数量,默认 20
}
// ListCommentsOptions 获取评论列表的选项
type ListCommentsOptions struct {
Page int // 页码,默认 1
PerPage int // 每页数量,默认 20
Order string // "asc", "desc",默认 "asc"
}
// CreateIssue 创建 Issue(发帖)
func (c *GiteeClient) CreateIssue(req CreateIssueRequest) (*Issue, error) {
apiURL := fmt.Sprintf("%s/repos/%s/issues", c.BaseURL, c.Owner)
data := map[string]string{
"access_token": c.AccessToken,
"repo": c.Repo,
"title": req.Title,
"security_hole": "false",
}
if req.Body != "" {
data["body"] = req.Body
}
if req.SecurityHole != "" {
data["security_hole"] = req.SecurityHole
}
if req.Labels != "" {
data["labels"] = req.Labels
}
jsonData, err := json.Marshal(data)
if err != nil {
return nil, fmt.Errorf("序列化请求数据失败: %w", err)
}
resp, err := http.Post(apiURL, "application/json;charset=UTF-8", bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("请求失败: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API 返回错误状态码 %d: %s", resp.StatusCode, string(body))
}
var issue Issue
if err := json.Unmarshal(body, &issue); err != nil {
return nil, fmt.Errorf("解析响应失败: %w", err)
}
return &issue, nil
}
// UpdateIssue 更新 Issue(更新帖子)
func (c *GiteeClient) UpdateIssue(number string, req UpdateIssueRequest) (*Issue, error) {
apiURL := fmt.Sprintf("%s/repos/%s/issues/%s", c.BaseURL, c.Owner, number)
data := map[string]string{
"access_token": c.AccessToken,
"repo": c.Repo,
}
if req.State != "" {
data["state"] = req.State
}
if req.Title != "" {
data["title"] = req.Title
}
if req.Body != "" {
data["body"] = req.Body
}
if req.Labels != "" {
data["labels"] = req.Labels
}
jsonData, err := json.Marshal(data)
if err != nil {
return nil, fmt.Errorf("序列化请求数据失败: %w", err)
}
client := &http.Client{}
httpReq, err := http.NewRequest(http.MethodPatch, apiURL, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("创建请求失败: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json;charset=UTF-8")
resp, err := client.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("请求失败: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API 返回错误状态码 %d: %s", resp.StatusCode, string(body))
}
var issue Issue
if err := json.Unmarshal(body, &issue); err != nil {
return nil, fmt.Errorf("解析响应失败: %w", err)
}
return &issue, nil
}
// ListIssues 获取仓库的所有 Issues(获取帖子列表)
func (c *GiteeClient) ListIssues(opts *ListIssuesOptions) ([]Issue, error) {
apiURL := fmt.Sprintf("%s/repos/%s/%s/issues", c.BaseURL, c.Owner, c.Repo)
// 构建查询参数
params := url.Values{}
params.Add("access_token", c.AccessToken)
if opts != nil {
if opts.State != "" {
params.Add("state", opts.State)
} else {
params.Add("state", "open")
}
if opts.Sort != "" {
params.Add("sort", opts.Sort)
} else {
params.Add("sort", "created")
}
if opts.Direction != "" {
params.Add("direction", opts.Direction)
} else {
params.Add("direction", "desc")
}
if opts.Page > 0 {
params.Add("page", fmt.Sprintf("%d", opts.Page))
} else {
params.Add("page", "1")
}
if opts.PerPage > 0 {
params.Add("per_page", fmt.Sprintf("%d", opts.PerPage))
} else {
params.Add("per_page", "20")
}
} else {
// 默认参数
params.Add("state", "open")
params.Add("sort", "created")
params.Add("direction", "desc")
params.Add("page", "1")
params.Add("per_page", "20")
}
fullURL := fmt.Sprintf("%s?%s", apiURL, params.Encode())
resp, err := http.Get(fullURL)
if err != nil {
return nil, fmt.Errorf("请求失败: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API 返回错误状态码 %d: %s", resp.StatusCode, string(body))
}
var issues []Issue
if err := json.Unmarshal(body, &issues); err != nil {
return nil, fmt.Errorf("解析响应失败: %w", err)
}
return issues, nil
}
// CreateComment 创建某个 Issue 的评论(发回帖)
func (c *GiteeClient) CreateComment(issueNumber string, req CreateCommentRequest) (*Comment, error) {
apiURL := fmt.Sprintf("%s/repos/%s/%s/issues/%s/comments", c.BaseURL, c.Owner, c.Repo, issueNumber)
data := map[string]string{
"access_token": c.AccessToken,
"body": req.Body,
}
jsonData, err := json.Marshal(data)
if err != nil {
return nil, fmt.Errorf("序列化请求数据失败: %w", err)
}
resp, err := http.Post(apiURL, "application/json;charset=UTF-8", bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("请求失败: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API 返回错误状态码 %d: %s", resp.StatusCode, string(body))
}
var comment Comment
if err := json.Unmarshal(body, &comment); err != nil {
return nil, fmt.Errorf("解析响应失败: %w", err)
}
return &comment, nil
}
// ListComments 获取仓库某个 Issue 的所有评论(获取帖子详情)
func (c *GiteeClient) ListComments(issueNumber string, opts *ListCommentsOptions) ([]Comment, error) {
apiURL := fmt.Sprintf("%s/repos/%s/%s/issues/%s/comments", c.BaseURL, c.Owner, c.Repo, issueNumber)
// 构建查询参数
params := url.Values{}
params.Add("access_token", c.AccessToken)
if opts != nil {
if opts.Page > 0 {
params.Add("page", fmt.Sprintf("%d", opts.Page))
} else {
params.Add("page", "1")
}
if opts.PerPage > 0 {
params.Add("per_page", fmt.Sprintf("%d", opts.PerPage))
} else {
params.Add("per_page", "20")
}
if opts.Order != "" {
params.Add("order", opts.Order)
} else {
params.Add("order", "asc")
}
} else {
// 默认参数
params.Add("page", "1")
params.Add("per_page", "20")
params.Add("order", "asc")
}
fullURL := fmt.Sprintf("%s?%s", apiURL, params.Encode())
resp, err := http.Get(fullURL)
if err != nil {
return nil, fmt.Errorf("请求失败: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API 返回错误状态码 %d: %s", resp.StatusCode, string(body))
}
var comments []Comment
if err := json.Unmarshal(body, &comments); err != nil {
return nil, fmt.Errorf("解析响应失败: %w", err)
}
return comments, nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。