···
···
"github.com/bluesky-social/indigo/atproto/syntax"
lexutil "github.com/bluesky-social/indigo/lex/util"
"github.com/go-chi/chi/v5"
"tangled.sh/tangled.sh/core/api/tangled"
"tangled.sh/tangled.sh/core/appview/db"
"tangled.sh/tangled.sh/core/appview/pages"
···
func (s *State) UpdateProfileBio(w http.ResponseWriter, r *http.Request) {
user := s.oauth.GetUser(r)
···
···
"github.com/bluesky-social/indigo/atproto/syntax"
lexutil "github.com/bluesky-social/indigo/lex/util"
"github.com/go-chi/chi/v5"
+
"github.com/gorilla/feeds"
"tangled.sh/tangled.sh/core/api/tangled"
"tangled.sh/tangled.sh/core/appview/db"
"tangled.sh/tangled.sh/core/appview/pages"
···
+
func (s *State) feedFromRequest(w http.ResponseWriter, r *http.Request) *feeds.Feed {
+
ident, ok := r.Context().Value("resolvedId").(identity.Identity)
+
feed, err := s.GetProfileFeed(r.Context(), ident.Handle.String(), ident.DID.String())
+
func (s *State) AtomFeedPage(w http.ResponseWriter, r *http.Request) {
+
feed := s.feedFromRequest(w, r)
+
atom, err := feed.ToAtom()
+
w.Header().Set("content-type", "application/atom+xml")
+
func (s *State) GetProfileFeed(ctx context.Context, handle string, did string) (*feeds.Feed, error) {
+
timeline, err := db.MakeProfileTimeline(s.db, did)
+
author := &feeds.Author{
+
Name: fmt.Sprintf("@%s", handle),
+
Title: fmt.Sprintf("timeline feed for %s", author.Name),
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s", s.config.Core.AppviewHost, handle), Type: "text/html", Rel: "alternate"},
+
Items: make([]*feeds.Item, 0),
+
Updated: time.UnixMilli(0),
+
for _, byMonth := range timeline.ByMonth {
+
for _, pull := range byMonth.PullEvents.Items {
+
owner, err := s.idResolver.ResolveIdent(ctx, pull.Repo.Did)
+
feed.Items = append(feed.Items, &feeds.Item{
+
Title: fmt.Sprintf("%s created pull request '%s' in @%s/%s", author.Name, pull.Title, owner.Handle, pull.Repo.Name),
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s/%s/pulls/%d", s.config.Core.AppviewHost, owner.Handle, pull.Repo.Name, pull.PullId), Type: "text/html", Rel: "alternate"},
+
for _, submission := range pull.Submissions {
+
feed.Items = append(feed.Items, &feeds.Item{
+
Title: fmt.Sprintf("%s submitted pull request '%s' (round #%d) in @%s/%s", author.Name, pull.Title, submission.RoundNumber, owner.Handle, pull.Repo.Name),
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s/%s/pulls/%d", s.config.Core.AppviewHost, owner.Handle, pull.Repo.Name, pull.PullId), Type: "text/html", Rel: "alternate"},
+
Created: submission.Created,
+
for _, issue := range byMonth.IssueEvents.Items {
+
owner, err := s.idResolver.ResolveIdent(ctx, issue.Metadata.Repo.Did)
+
feed.Items = append(feed.Items, &feeds.Item{
+
Title: fmt.Sprintf("%s created issue '%s' in @%s/%s", author.Name, issue.Title, owner.Handle, issue.Metadata.Repo.Name),
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s/%s/issues/%d", s.config.Core.AppviewHost, owner.Handle, issue.Metadata.Repo.Name, issue.IssueId), Type: "text/html", Rel: "alternate"},
+
Created: issue.Created,
+
for _, repo := range byMonth.RepoEvents {
+
if repo.Source != nil {
+
id, err := s.idResolver.ResolveIdent(ctx, repo.Source.Did)
+
title = fmt.Sprintf("%s forked repository @%s/%s to '%s'", author.Name, id.Handle, repo.Source.Name, repo.Repo.Name)
+
title = fmt.Sprintf("%s created repository '%s'", author.Name, repo.Repo.Name)
+
feed.Items = append(feed.Items, &feeds.Item{
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s/%s", s.config.Core.AppviewHost, handle, repo.Repo.Name), Type: "text/html", Rel: "alternate"},
+
Created: repo.Repo.Created,
+
slices.SortFunc(feed.Items, func(a *feeds.Item, b *feeds.Item) int {
+
return int(b.Created.UnixMilli()) - int(a.Created.UnixMilli())
+
if len(feed.Items) > 0 {
+
feed.Updated = feed.Items[0].Created
func (s *State) UpdateProfileBio(w http.ResponseWriter, r *http.Request) {
user := s.oauth.GetUser(r)