+95
-63
appview/state/profile.go
+95
-63
appview/state/profile.go
···
175
175
})
176
176
}
177
177
178
-
func (s *State) feedFromRequest(w http.ResponseWriter, r *http.Request) *feeds.Feed {
178
+
func (s *State) AtomFeedPage(w http.ResponseWriter, r *http.Request) {
179
179
ident, ok := r.Context().Value("resolvedId").(identity.Identity)
180
180
if !ok {
181
181
s.pages.Error404(w)
182
-
return nil
182
+
return
183
183
}
184
184
185
-
feed, err := s.GetProfileFeed(r.Context(), ident.Handle.String(), ident.DID.String())
185
+
feed, err := s.getProfileFeed(r.Context(), &ident)
186
186
if err != nil {
187
187
s.pages.Error500(w)
188
-
return nil
188
+
return
189
189
}
190
190
191
-
return feed
192
-
}
193
-
194
-
func (s *State) AtomFeedPage(w http.ResponseWriter, r *http.Request) {
195
-
feed := s.feedFromRequest(w, r)
196
191
if feed == nil {
197
192
return
198
193
}
···
207
202
w.Write([]byte(atom))
208
203
}
209
204
210
-
func (s *State) GetProfileFeed(ctx context.Context, handle string, did string) (*feeds.Feed, error) {
211
-
timeline, err := db.MakeProfileTimeline(s.db, did)
205
+
func (s *State) getProfileFeed(ctx context.Context, id *identity.Identity) (*feeds.Feed, error) {
206
+
timeline, err := db.MakeProfileTimeline(s.db, id.DID.String())
212
207
if err != nil {
213
208
return nil, err
214
209
}
215
210
216
211
author := &feeds.Author{
217
-
Name: fmt.Sprintf("@%s", handle),
212
+
Name: fmt.Sprintf("@%s", id.Handle),
218
213
}
219
-
feed := &feeds.Feed{
220
-
Title: fmt.Sprintf("timeline feed for %s", author.Name),
221
-
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s", s.config.Core.AppviewHost, handle), Type: "text/html", Rel: "alternate"},
214
+
215
+
feed := feeds.Feed{
216
+
Title: fmt.Sprintf("%s's timeline", author.Name),
217
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s", s.config.Core.AppviewHost, id.Handle), Type: "text/html", Rel: "alternate"},
222
218
Items: make([]*feeds.Item, 0),
223
219
Updated: time.UnixMilli(0),
224
220
Author: author,
225
221
}
222
+
226
223
for _, byMonth := range timeline.ByMonth {
227
-
for _, pull := range byMonth.PullEvents.Items {
228
-
owner, err := s.idResolver.ResolveIdent(ctx, pull.Repo.Did)
229
-
if err != nil {
230
-
return nil, err
231
-
}
232
-
feed.Items = append(feed.Items, &feeds.Item{
233
-
Title: fmt.Sprintf("%s created pull request '%s' in @%s/%s", author.Name, pull.Title, owner.Handle, pull.Repo.Name),
234
-
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"},
235
-
Created: pull.Created,
236
-
Author: author,
237
-
})
238
-
for _, submission := range pull.Submissions {
239
-
feed.Items = append(feed.Items, &feeds.Item{
240
-
Title: fmt.Sprintf("%s submitted pull request '%s' (round #%d) in @%s/%s", author.Name, pull.Title, submission.RoundNumber, owner.Handle, pull.Repo.Name),
241
-
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"},
242
-
Created: submission.Created,
243
-
Author: author,
244
-
})
245
-
}
224
+
if err := s.addPullRequestItems(ctx, &feed, byMonth.PullEvents.Items, author); err != nil {
225
+
return nil, err
246
226
}
247
-
for _, issue := range byMonth.IssueEvents.Items {
248
-
owner, err := s.idResolver.ResolveIdent(ctx, issue.Metadata.Repo.Did)
249
-
if err != nil {
250
-
return nil, err
251
-
}
252
-
feed.Items = append(feed.Items, &feeds.Item{
253
-
Title: fmt.Sprintf("%s created issue '%s' in @%s/%s", author.Name, issue.Title, owner.Handle, issue.Metadata.Repo.Name),
254
-
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"},
255
-
Created: issue.Created,
256
-
Author: author,
257
-
})
227
+
if err := s.addIssueItems(ctx, &feed, byMonth.IssueEvents.Items, author); err != nil {
228
+
return nil, err
258
229
}
259
-
for _, repo := range byMonth.RepoEvents {
260
-
var title string
261
-
if repo.Source != nil {
262
-
id, err := s.idResolver.ResolveIdent(ctx, repo.Source.Did)
263
-
if err != nil {
264
-
return nil, err
265
-
}
266
-
title = fmt.Sprintf("%s forked repository @%s/%s to '%s'", author.Name, id.Handle, repo.Source.Name, repo.Repo.Name)
267
-
} else {
268
-
title = fmt.Sprintf("%s created repository '%s'", author.Name, repo.Repo.Name)
269
-
}
270
-
feed.Items = append(feed.Items, &feeds.Item{
271
-
Title: title,
272
-
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s/%s", s.config.Core.AppviewHost, handle, repo.Repo.Name), Type: "text/html", Rel: "alternate"},
273
-
Created: repo.Repo.Created,
274
-
Author: author,
275
-
})
230
+
if err := s.addRepoItems(ctx, &feed, byMonth.RepoEvents, author); err != nil {
231
+
return nil, err
276
232
}
277
233
}
234
+
278
235
slices.SortFunc(feed.Items, func(a *feeds.Item, b *feeds.Item) int {
279
236
return int(b.Created.UnixMilli()) - int(a.Created.UnixMilli())
280
237
})
238
+
281
239
if len(feed.Items) > 0 {
282
240
feed.Updated = feed.Items[0].Created
283
241
}
284
242
285
-
return feed, nil
243
+
return &feed, nil
244
+
}
245
+
246
+
func (s *State) addPullRequestItems(ctx context.Context, feed *feeds.Feed, pulls []*db.Pull, author *feeds.Author) error {
247
+
for _, pull := range pulls {
248
+
owner, err := s.idResolver.ResolveIdent(ctx, pull.Repo.Did)
249
+
if err != nil {
250
+
return err
251
+
}
252
+
253
+
// Add pull request creation item
254
+
feed.Items = append(feed.Items, s.createPullRequestItem(pull, owner, author))
255
+
}
256
+
return nil
257
+
}
258
+
259
+
func (s *State) addIssueItems(ctx context.Context, feed *feeds.Feed, issues []*db.Issue, author *feeds.Author) error {
260
+
for _, issue := range issues {
261
+
owner, err := s.idResolver.ResolveIdent(ctx, issue.Metadata.Repo.Did)
262
+
if err != nil {
263
+
return err
264
+
}
265
+
266
+
feed.Items = append(feed.Items, s.createIssueItem(issue, owner, author))
267
+
}
268
+
return nil
269
+
}
270
+
271
+
func (s *State) addRepoItems(ctx context.Context, feed *feeds.Feed, repos []db.RepoEvent, author *feeds.Author) error {
272
+
for _, repo := range repos {
273
+
item, err := s.createRepoItem(ctx, repo, author)
274
+
if err != nil {
275
+
return err
276
+
}
277
+
feed.Items = append(feed.Items, item)
278
+
}
279
+
return nil
280
+
}
281
+
282
+
func (s *State) createPullRequestItem(pull *db.Pull, owner *identity.Identity, author *feeds.Author) *feeds.Item {
283
+
return &feeds.Item{
284
+
Title: fmt.Sprintf("%s created pull request '%s' in @%s/%s", author.Name, pull.Title, owner.Handle, pull.Repo.Name),
285
+
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"},
286
+
Created: pull.Created,
287
+
Author: author,
288
+
}
289
+
}
290
+
291
+
func (s *State) createIssueItem(issue *db.Issue, owner *identity.Identity, author *feeds.Author) *feeds.Item {
292
+
return &feeds.Item{
293
+
Title: fmt.Sprintf("%s created issue '%s' in @%s/%s", author.Name, issue.Title, owner.Handle, issue.Metadata.Repo.Name),
294
+
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"},
295
+
Created: issue.Created,
296
+
Author: author,
297
+
}
298
+
}
299
+
300
+
func (s *State) createRepoItem(ctx context.Context, repo db.RepoEvent, author *feeds.Author) (*feeds.Item, error) {
301
+
var title string
302
+
if repo.Source != nil {
303
+
sourceOwner, err := s.idResolver.ResolveIdent(ctx, repo.Source.Did)
304
+
if err != nil {
305
+
return nil, err
306
+
}
307
+
title = fmt.Sprintf("%s forked repository @%s/%s to '%s'", author.Name, sourceOwner.Handle, repo.Source.Name, repo.Repo.Name)
308
+
} else {
309
+
title = fmt.Sprintf("%s created repository '%s'", author.Name, repo.Repo.Name)
310
+
}
311
+
312
+
return &feeds.Item{
313
+
Title: title,
314
+
Link: &feeds.Link{Href: fmt.Sprintf("%s/@%s/%s", s.config.Core.AppviewHost, author.Name[1:], repo.Repo.Name), Type: "text/html", Rel: "alternate"}, // Remove @ prefix
315
+
Created: repo.Repo.Created,
316
+
Author: author,
317
+
}, nil
286
318
}
287
319
288
320
func (s *State) UpdateProfileBio(w http.ResponseWriter, r *http.Request) {