Signed-off-by: dusk y.bera003.06@protonmail.com
+101
appview/repo/repo.go
+101
appview/repo/repo.go
···
37
37
securejoin "github.com/cyphar/filepath-securejoin"
38
38
"github.com/go-chi/chi/v5"
39
39
"github.com/go-git/go-git/v5/plumbing"
40
+
"github.com/gorilla/feeds"
40
41
41
42
comatproto "github.com/bluesky-social/indigo/api/atproto"
42
43
"github.com/bluesky-social/indigo/atproto/syntax"
···
288
289
}
289
290
}
290
291
292
+
func (rp *Repo) getRepoFeed(ctx context.Context, f *reporesolver.ResolvedRepo) (*feeds.Feed, error) {
293
+
const feedLimitPerType = 100
294
+
295
+
pulls, err := db.GetPullsWithLimit(rp.db, feedLimitPerType, db.FilterEq("repo_at", f.RepoAt()))
296
+
if err != nil {
297
+
return nil, err
298
+
}
299
+
300
+
issues, err := db.GetIssuesWithLimit(rp.db, feedLimitPerType, db.FilterEq("repo_at", f.RepoAt()))
301
+
if err != nil {
302
+
return nil, err
303
+
}
304
+
305
+
feed := &feeds.Feed{
306
+
Title: fmt.Sprintf("activity feed for %s", f.OwnerSlashRepo()),
307
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/%s", rp.config.Core.AppviewHost, f.OwnerSlashRepo()), Type: "text/html", Rel: "alternate"},
308
+
Items: make([]*feeds.Item, 0),
309
+
Updated: time.UnixMilli(0),
310
+
}
311
+
312
+
for _, pull := range pulls {
313
+
owner, err := rp.idResolver.ResolveIdent(ctx, pull.OwnerDid)
314
+
if err != nil {
315
+
return nil, err
316
+
}
317
+
var state string
318
+
if pull.State == db.PullOpen {
319
+
state = "opened"
320
+
} else {
321
+
state = pull.State.String()
322
+
}
323
+
item := &feeds.Item{
324
+
Title: fmt.Sprintf("[PR] %s", pull.Title),
325
+
Description: fmt.Sprintf("@%s %s pull request on %s", owner.Handle, state, f.OwnerSlashRepo()),
326
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/pulls/%d", rp.config.Core.AppviewHost, f.OwnerSlashRepo(), pull.PullId)},
327
+
Created: pull.Created,
328
+
Author: &feeds.Author{
329
+
Name: fmt.Sprintf("@%s", owner.Handle),
330
+
},
331
+
}
332
+
feed.Items = append(feed.Items, item)
333
+
}
334
+
335
+
for _, issue := range issues {
336
+
owner, err := rp.idResolver.ResolveIdent(ctx, issue.OwnerDid)
337
+
if err != nil {
338
+
return nil, err
339
+
}
340
+
var state string
341
+
if issue.Open {
342
+
state = "opened"
343
+
} else {
344
+
state = "closed"
345
+
}
346
+
item := &feeds.Item{
347
+
Title: fmt.Sprintf("[Issue] %s", issue.Title),
348
+
Description: fmt.Sprintf("@%s %s issue on %s", owner.Handle, state, f.OwnerSlashRepo()),
349
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/issues/%d", rp.config.Core.AppviewHost, f.OwnerSlashRepo(), issue.IssueId)},
350
+
Created: issue.Created,
351
+
Author: &feeds.Author{
352
+
Name: fmt.Sprintf("@%s", owner.Handle),
353
+
},
354
+
}
355
+
feed.Items = append(feed.Items, item)
356
+
}
357
+
358
+
slices.SortFunc(feed.Items, func(a *feeds.Item, b *feeds.Item) int {
359
+
return int(b.Created.UnixMilli()) - int(a.Created.UnixMilli())
360
+
})
361
+
if len(feed.Items) > 0 {
362
+
feed.Updated = feed.Items[0].Created
363
+
}
364
+
365
+
return feed, nil
366
+
}
367
+
368
+
func (rp *Repo) RepoAtomFeed(w http.ResponseWriter, r *http.Request) {
369
+
f, err := rp.repoResolver.Resolve(r)
370
+
if err != nil {
371
+
log.Println("failed to fully resolve repo:", err)
372
+
return
373
+
}
374
+
375
+
feed, err := rp.getRepoFeed(r.Context(), f)
376
+
if err != nil {
377
+
log.Println("failed to get repo feed:", err)
378
+
rp.pages.Error500(w)
379
+
return
380
+
}
381
+
382
+
atom, err := feed.ToAtom()
383
+
if err != nil {
384
+
rp.pages.Error500(w)
385
+
return
386
+
}
387
+
388
+
w.Header().Set("content-type", "application/atom+xml")
389
+
w.Write([]byte(atom))
390
+
}
391
+
291
392
func (rp *Repo) RepoCommit(w http.ResponseWriter, r *http.Request) {
292
393
f, err := rp.repoResolver.Resolve(r)
293
394
if err != nil {
+1
appview/repo/router.go
+1
appview/repo/router.go