1package state
2
3import (
4 "fmt"
5 "log"
6 "net/http"
7
8 "github.com/bluesky-social/indigo/atproto/identity"
9 "github.com/go-chi/chi/v5"
10 "tangled.sh/tangled.sh/core/appview/db"
11 "tangled.sh/tangled.sh/core/appview/pages"
12)
13
14func (s *State) ProfilePage(w http.ResponseWriter, r *http.Request) {
15 didOrHandle := chi.URLParam(r, "user")
16 if didOrHandle == "" {
17 http.Error(w, "Bad request", http.StatusBadRequest)
18 return
19 }
20
21 ident, ok := r.Context().Value("resolvedId").(identity.Identity)
22 if !ok {
23 s.pages.Error404(w)
24 return
25 }
26
27 repos, err := db.GetAllReposByDid(s.db, ident.DID.String())
28 if err != nil {
29 log.Printf("getting repos for %s: %s", ident.DID.String(), err)
30 }
31
32 collaboratingRepos, err := db.CollaboratingIn(s.db, ident.DID.String())
33 if err != nil {
34 log.Printf("getting collaborating repos for %s: %s", ident.DID.String(), err)
35 }
36
37 timeline, err := db.MakeProfileTimeline(s.db, ident.DID.String())
38 if err != nil {
39 log.Printf("failed to create profile timeline for %s: %s", ident.DID.String(), err)
40 }
41
42 var didsToResolve []string
43 for _, r := range collaboratingRepos {
44 didsToResolve = append(didsToResolve, r.Did)
45 }
46 for _, byMonth := range timeline.ByMonth {
47 for _, pe := range byMonth.PullEvents.Items {
48 didsToResolve = append(didsToResolve, pe.Repo.Did)
49 }
50 for _, ie := range byMonth.IssueEvents.Items {
51 didsToResolve = append(didsToResolve, ie.Metadata.Repo.Did)
52 }
53 for _, re := range byMonth.RepoEvents {
54 didsToResolve = append(didsToResolve, re.Repo.Did)
55 if re.Source != nil {
56 didsToResolve = append(didsToResolve, re.Source.Did)
57 }
58 }
59 }
60
61 resolvedIds := s.resolver.ResolveIdents(r.Context(), didsToResolve)
62 didHandleMap := make(map[string]string)
63 for _, identity := range resolvedIds {
64 if !identity.Handle.IsInvalidHandle() {
65 didHandleMap[identity.DID.String()] = fmt.Sprintf("@%s", identity.Handle.String())
66 } else {
67 didHandleMap[identity.DID.String()] = identity.DID.String()
68 }
69 }
70
71 followers, following, err := db.GetFollowerFollowing(s.db, ident.DID.String())
72 if err != nil {
73 log.Printf("getting follow stats repos for %s: %s", ident.DID.String(), err)
74 }
75
76 loggedInUser := s.auth.GetUser(r)
77 followStatus := db.IsNotFollowing
78 if loggedInUser != nil {
79 followStatus = db.GetFollowStatus(s.db, loggedInUser.Did, ident.DID.String())
80 }
81
82 profileAvatarUri, err := GetAvatarUri(ident.Handle.String())
83 if err != nil {
84 log.Println("failed to fetch bsky avatar", err)
85 }
86
87 s.pages.ProfilePage(w, pages.ProfilePageParams{
88 LoggedInUser: loggedInUser,
89 UserDid: ident.DID.String(),
90 UserHandle: ident.Handle.String(),
91 Repos: repos,
92 CollaboratingRepos: collaboratingRepos,
93 ProfileStats: pages.ProfileStats{
94 Followers: followers,
95 Following: following,
96 },
97 FollowStatus: db.FollowStatus(followStatus),
98 DidHandleMap: didHandleMap,
99 AvatarUri: profileAvatarUri,
100 ProfileTimeline: timeline,
101 })
102}