Files
gitea-tea/internal/services/comments.go
T
bircni c1d51c386d fix(pr): refuse pr comment and pr attachment on issues
Gitea serves pull request comments and attachments through issue
endpoints, so tea pr comment create 1 posted on issue #1. pr comment and
pr attachment commands now check that the number is a pull request, and
comment IDs that the comment is on one, and point at the issue command
otherwise: "#1 in alice/project is an issue, not a pull request; use tea
issue comment create 1". Issues gain a kind field (issue or pull) in JSON.

Signed-off-by: bircni <bircni@icloud.com>
2026-10-12 00:14:30 +02:00

85 lines
3.2 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package services
import (
"context"
gitea "gitea.dev/sdk"
"gitea.dev/tea/internal/transport"
)
// Comment is the public representation shared by issue and pull request comments.
type Comment struct {
ID int64 `json:"id"`
Body string `json:"body"`
URL string `json:"url"`
Author string `json:"author"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
// Pull reports a comment on a pull request rather than an issue.
Pull bool `json:"-"`
}
func commentFrom(comment *gitea.Comment) Comment {
return Comment{
ID: comment.ID, Body: comment.Body, URL: comment.HTMLURL, Author: login(comment.Poster),
CreatedAt: timestamp(comment.Created), UpdatedAt: timestamp(comment.Updated), Pull: comment.PRURL != "",
}
}
// Comments implements discussion comments under their owning repository resource.
type Comments struct {
Client *transport.Client
Repository string
}
// List returns every discussion comment; the API does not paginate this collection.
func (s Comments) List(ctx context.Context, n int64) ([]Comment, error) {
comments, err := repoCall(ctx, s.Client, s.Repository, func(ctx context.Context, c *gitea.Client, owner, repo string) ([]*gitea.Comment, *gitea.Response, error) {
return c.Issues.ListIssueComments(ctx, owner, repo, n, gitea.ListIssueCommentOptions{Page: -1})
})
if err != nil {
return nil, err
}
return convertAll(comments, commentFrom), nil
}
// Page applies CLI pagination to the unpaginated comment collection.
func (s Comments) Page(ctx context.Context, n int64, limit, page int) ([]Comment, error) {
items, err := s.List(ctx, n)
if err != nil {
return nil, err
}
return pageOf(items, limit, page)
}
// View retrieves a comment by its repository-scoped ID.
func (s Comments) View(ctx context.Context, id int64) (Comment, error) {
return repoConvert(ctx, s.Client, s.Repository, commentFrom, func(ctx context.Context, c *gitea.Client, owner, repo string) (*gitea.Comment, *gitea.Response, error) {
return c.Issues.GetIssueComment(ctx, owner, repo, id)
})
}
// Create adds a comment to an issue or pull request.
func (s Comments) Create(ctx context.Context, n int64, body string) (Comment, error) {
return repoConvert(ctx, s.Client, s.Repository, commentFrom, func(ctx context.Context, c *gitea.Client, owner, repo string) (*gitea.Comment, *gitea.Response, error) {
return c.Issues.CreateIssueComment(ctx, owner, repo, n, gitea.CreateIssueCommentOption{Body: body})
})
}
// Edit replaces the body of a repository comment.
func (s Comments) Edit(ctx context.Context, id int64, body string) (Comment, error) {
return repoConvert(ctx, s.Client, s.Repository, commentFrom, func(ctx context.Context, c *gitea.Client, owner, repo string) (*gitea.Comment, *gitea.Response, error) {
return c.Issues.EditIssueComment(ctx, owner, repo, id, gitea.EditIssueCommentOption{Body: body})
})
}
// Delete removes a repository comment.
func (s Comments) Delete(ctx context.Context, id int64) error {
return repoDo(ctx, s.Client, s.Repository, func(ctx context.Context, c *gitea.Client, owner, repo string) (*gitea.Response, error) {
return c.Issues.DeleteIssueComment(ctx, owner, repo, id)
})
}