···
-
func GetIssueAt(e Execer, repoAt syntax.ATURI, issueId int) (string, error) {
-
err := e.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt)
-
func GetIssueOwnerDid(e Execer, repoAt syntax.ATURI, issueId int) (string, error) {
-
err := e.QueryRow(`select owner_did from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&ownerDid)
-
func GetIssuesPaginated(e Execer, repoAt syntax.ATURI, isOpen bool, page pagination.Page) ([]Issue, error) {
-
with numbered_issue as (
-
count(c.id) as comment_count,
-
row_number() over (order by i.created desc) as row_num
-
comments c on i.repo_at = c.repo_at and i.issue_id = c.issue_id
-
i.repo_at = ? and i.open = ?
-
i.id, i.owner_did, i.issue_id, i.created, i.title, i.body, i.open
-
row_num between ? and ?`,
-
repoAt, openValue, page.Offset+1, page.Offset+page.Limit)
-
var metadata IssueMetadata
-
err := rows.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open, &metadata.CommentCount)
-
createdTime, err := time.Parse(time.RFC3339, createdAt)
-
issue.Created = createdTime
-
issue.Metadata = &metadata
-
issues = append(issues, issue)
-
if err := rows.Err(); err != nil {
···
var issueCreatedAt string
···
func GetIssues(e Execer, filters ...filter) ([]Issue, error) {
-
return GetIssuesWithLimit(e, 0, filters...)
// timeframe here is directly passed into the sql query filter, and any
···
var issueCreatedAt, repoCreatedAt string
···
repo.Created = repoCreatedTime
-
issue.Metadata = &IssueMetadata{
issues = append(issues, issue)
···
-
err := row.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &createdAt, &issue.Title, &issue.Body, &issue.Open)
···
-
func GetIssueWithComments(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, []Comment, error) {
-
query := `select id, owner_did, rkey, issue_id, created, title, body, open from issues where repo_at = ? and issue_id = ?`
-
row := e.QueryRow(query, repoAt, issueId)
-
err := row.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open)
-
createdTime, err := time.Parse(time.RFC3339, createdAt)
-
issue.Created = createdTime
-
comments, err := GetComments(e, repoAt, issueId)
-
return &issue, comments, nil
-
func NewIssueComment(e Execer, comment *Comment) error {
-
query := `insert into comments (owner_did, repo_at, rkey, issue_id, comment_id, body) values (?, ?, ?, ?, ?, ?)`
-
func GetComments(e Execer, repoAt syntax.ATURI, issueId int) ([]Comment, error) {
-
repo_at = ? and issue_id = ?
-
if err == sql.ErrNoRows {
-
return []Comment{}, nil
-
var deletedAt, editedAt, rkey sql.NullString
-
err := rows.Scan(&comment.OwnerDid, &comment.Issue, &comment.CommentId, &rkey, &comment.Body, &createdAt, &editedAt, &deletedAt)
-
createdAtTime, err := time.Parse(time.RFC3339, createdAt)
-
comment.Created = &createdAtTime
-
deletedTime, err := time.Parse(time.RFC3339, deletedAt.String)
-
comment.Deleted = &deletedTime
-
editedTime, err := time.Parse(time.RFC3339, editedAt.String)
-
comment.Edited = &editedTime
-
comment.Rkey = rkey.String
comments = append(comments, comment)
-
if err := rows.Err(); err != nil {
-
func GetComment(e Execer, repoAt syntax.ATURI, issueId, commentId int) (*Comment, error) {
-
owner_did, body, rkey, created, deleted, edited
-
comments where repo_at = ? and issue_id = ? and comment_id = ?
-
row := e.QueryRow(query, repoAt, issueId, commentId)
-
var deletedAt, editedAt, rkey sql.NullString
-
err := row.Scan(&comment.OwnerDid, &comment.Body, &rkey, &createdAt, &deletedAt, &editedAt)
-
createdTime, err := time.Parse(time.RFC3339, createdAt)
-
comment.Created = &createdTime
-
deletedTime, err := time.Parse(time.RFC3339, deletedAt.String)
-
comment.Deleted = &deletedTime
-
editedTime, err := time.Parse(time.RFC3339, editedAt.String)
-
comment.Edited = &editedTime
-
comment.Rkey = rkey.String
-
comment.RepoAt = repoAt
-
comment.Issue = issueId
-
comment.CommentId = commentId
-
func EditComment(e Execer, repoAt syntax.ATURI, issueId, commentId int, newBody string) error {
-
edited = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
-
where repo_at = ? and issue_id = ? and comment_id = ?
-
`, newBody, repoAt, issueId, commentId)
-
func DeleteComment(e Execer, repoAt syntax.ATURI, issueId, commentId int) error {
-
deleted = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
-
where repo_at = ? and issue_id = ? and comment_id = ?
-
`, repoAt, issueId, commentId)
-
func UpdateCommentByRkey(e Execer, ownerDid, rkey, newBody string) error {
-
edited = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
-
where owner_did = ? and rkey = ?
-
`, newBody, ownerDid, rkey)
-
func DeleteCommentByRkey(e Execer, ownerDid, rkey string) error {
-
deleted = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
-
where owner_did = ? and rkey = ?
-
func UpdateIssueByRkey(e Execer, ownerDid, rkey, title, body string) error {
-
_, err := e.Exec(`update issues set title = ?, body = ? where owner_did = ? and rkey = ?`, title, body, ownerDid, rkey)
-
func DeleteIssueByRkey(e Execer, ownerDid, rkey string) error {
-
_, err := e.Exec(`delete from issues where owner_did = ? and rkey = ?`, ownerDid, rkey)
-
func CloseIssue(e Execer, repoAt syntax.ATURI, issueId int) error {
-
_, err := e.Exec(`update issues set open = 0 where repo_at = ? and issue_id = ?`, repoAt, issueId)
-
func ReopenIssue(e Execer, repoAt syntax.ATURI, issueId int) error {
-
_, err := e.Exec(`update issues set open = 1 where repo_at = ? and issue_id = ?`, repoAt, issueId)
···
+
func GetIssuesPaginated(e Execer, page pagination.Page, filters ...filter) ([]Issue, error) {
+
issueMap := make(map[string]*Issue) // at-uri -> issue
+
var conditions []string
+
for _, filter := range filters {
+
conditions = append(conditions, filter.Condition())
+
args = append(args, filter.Arg()...)
+
whereClause = " where " + strings.Join(conditions, " and ")
+
pLower := FilterGte("row_num", page.Offset+1)
+
pUpper := FilterLte("row_num", page.Offset+page.Limit)
+
args = append(args, pLower.Arg()...)
+
args = append(args, pUpper.Arg()...)
+
pagination := " where " + pLower.Condition() + " and " + pUpper.Condition()
+
row_number() over (order by created desc) as row_num
+
rows, err := e.Query(query, args...)
+
return nil, fmt.Errorf("failed to query issues table: %w", err)
+
var editedAt, deletedAt sql.Null[string]
+
return nil, fmt.Errorf("failed to scan issue: %w", err)
+
if t, err := time.Parse(time.RFC3339, createdAt); err == nil {
+
if t, err := time.Parse(time.RFC3339, editedAt.V); err == nil {
+
if t, err := time.Parse(time.RFC3339, deletedAt.V); err == nil {
+
atUri := issue.AtUri().String()
+
issueMap[atUri] = &issue
+
// collect reverse repos
+
repoAts := make([]string, 0, len(issueMap)) // or just []string{}
+
for _, issue := range issueMap {
+
repoAts = append(repoAts, string(issue.RepoAt))
+
repos, err := GetRepos(e, 0, FilterIn("at_uri", repoAts))
+
return nil, fmt.Errorf("failed to build repo mappings: %w", err)
+
repoMap := make(map[string]*Repo)
+
repoMap[string(repos[i].RepoAt())] = &repos[i]
+
for issueAt := range issueMap {
+
r := repoMap[string(i.RepoAt)]
+
issueAts := slices.Collect(maps.Keys(issueMap))
+
comments, err := GetIssueComments(e, FilterIn("issue_at", issueAts))
+
return nil, fmt.Errorf("failed to query comments: %w", err)
+
for i := range comments {
+
issueAt := comments[i].IssueAt
+
if issue, ok := issueMap[issueAt]; ok {
+
issue.Comments = append(issue.Comments, comments[i])
+
for _, i := range issueMap {
+
issues = append(issues, *i)
+
sort.Slice(issues, func(i, j int) bool {
+
return issues[i].Created.After(issues[j].Created)
···
var issueCreatedAt string
···
func GetIssues(e Execer, filters ...filter) ([]Issue, error) {
+
return GetIssuesPaginated(e, pagination.FirstPage(), filters...)
// timeframe here is directly passed into the sql query filter, and any
···
var issueCreatedAt, repoCreatedAt string
···
repo.Created = repoCreatedTime
issues = append(issues, issue)
···
+
err := row.Scan(&issue.Id, &issue.Did, &issue.Rkey, &createdAt, &issue.Title, &issue.Body, &issue.Open)
···
+
func AddIssueComment(e Execer, c IssueComment) (int64, error) {
+
`insert into issue_comments (
+
values (?, ?, ?, ?, ?, ?, null)
+
on conflict(did, rkey) do update set
+
issue_at = excluded.issue_at,
+
issue_comments.issue_at != excluded.issue_at
+
or issue_comments.body != excluded.body
+
or issue_comments.reply_to != excluded.reply_to
+
else issue_comments.edited
+
c.Created.Format(time.RFC3339),
+
time.Now().Format(time.RFC3339),
+
id, err := result.LastInsertId()
+
func DeleteIssueComments(e Execer, filters ...filter) error {
+
var conditions []string
+
for _, filter := range filters {
+
conditions = append(conditions, filter.Condition())
+
args = append(args, filter.Arg()...)
+
whereClause = " where " + strings.Join(conditions, " and ")
+
query := fmt.Sprintf(`update issue_comments set body = "", deleted = strftime('%%Y-%%m-%%dT%%H:%%M:%%SZ', 'now') %s`, whereClause)
+
_, err := e.Exec(query, args...)
+
func GetIssueComments(e Execer, filters ...filter) ([]IssueComment, error) {
+
var comments []IssueComment
+
var conditions []string
+
for _, filter := range filters {
+
conditions = append(conditions, filter.Condition())
+
args = append(args, filter.Arg()...)
+
whereClause = " where " + strings.Join(conditions, " and ")
+
rows, err := e.Query(query, args...)
+
var comment IssueComment
+
var rkey, edited, deleted, replyTo sql.Null[string]
+
// this is a remnant from old times, newer comments always have rkey
+
if t, err := time.Parse(time.RFC3339, created); err == nil {
+
if t, err := time.Parse(time.RFC3339, edited.V); err == nil {
+
if t, err := time.Parse(time.RFC3339, deleted.V); err == nil {
+
comment.ReplyTo = &replyTo.V
comments = append(comments, comment)
+
if err = rows.Err(); err != nil {
+
func DeleteIssues(e Execer, filters ...filter) error {
+
var conditions []string
+
for _, filter := range filters {
+
conditions = append(conditions, filter.Condition())
+
args = append(args, filter.Arg()...)
+
whereClause = " where " + strings.Join(conditions, " and ")
+
query := fmt.Sprintf(`delete from issues %s`, whereClause)
+
_, err := e.Exec(query, args...)
+
func CloseIssues(e Execer, filters ...filter) error {
+
var conditions []string
+
for _, filter := range filters {
+
conditions = append(conditions, filter.Condition())
+
args = append(args, filter.Arg()...)
+
whereClause = " where " + strings.Join(conditions, " and ")
+
query := fmt.Sprintf(`update issues set open = 0 %s`, whereClause)
+
_, err := e.Exec(query, args...)
+
func ReopenIssues(e Execer, filters ...filter) error {
+
var conditions []string
+
for _, filter := range filters {
+
conditions = append(conditions, filter.Condition())
+
args = append(args, filter.Arg()...)
+
whereClause = " where " + strings.Join(conditions, " and ")
+
query := fmt.Sprintf(`update issues set open = 1 %s`, whereClause)
+
_, err := e.Exec(query, args...)