at main 4.0 kB view raw
1package main 2 3import ( 4 "log" 5 "net/http" 6 "strings" 7 8 bsky "github.com/bluesky-social/indigo/api/bsky" 9) 10 11func handlePost(w http.ResponseWriter, r *http.Request) { 12 c, didStr, err := getClientFromSession(r.Context(), r) 13 if err != nil { 14 http.Redirect(w, r, "/signin", http.StatusFound) 15 return 16 } 17 18 data, err := preparePostPageData(r.Context(), r, c, didStr) 19 if err != nil { 20 http.Error(w, "Failed to prepare post page: "+err.Error(), http.StatusInternalServerError) 21 return 22 } 23 24 executeTemplate(w, "post.html", data) 25} 26 27func handleProfile(w http.ResponseWriter, r *http.Request) { 28 c, myDid, err := getClientFromSession(r.Context(), r) 29 if err != nil { 30 http.Redirect(w, r, "/signin", http.StatusFound) 31 return 32 } 33 34 path := strings.TrimPrefix(r.URL.Path, "/profile/") 35 profileHandle := path 36 if profileHandle == "" { 37 profileHandle = myDid 38 } 39 40 profileView, err := fetchProfile(r.Context(), c, profileHandle) 41 if err != nil { 42 http.Error(w, err.Error(), http.StatusInternalServerError) 43 return 44 } 45 if profileView == nil { 46 http.Error(w, "Profile not found", http.StatusNotFound) 47 return 48 } 49 50 authorFeed, err := bsky.FeedGetAuthorFeed(r.Context(), c, profileView.Did, "", "", false, 50) 51 if err != nil { 52 http.Error(w, err.Error(), http.StatusInternalServerError) 53 return 54 } 55 56 myProfile, err := fetchProfile(r.Context(), c, myDid) 57 if err != nil { 58 http.Error(w, err.Error(), http.StatusInternalServerError) 59 return 60 } 61 62 followsList := fetchFollows(r.Context(), c, profileView.Did, 50) 63 64 postBoxHandle := "" 65 if profileView.Handle != "" { 66 postBoxHandle = profileView.Handle 67 } 68 69 // Collect parent URIs from the author's feed and batch-fetch previews 70 parentURIsSet := map[string]struct{}{} 71 if authorFeed != nil && authorFeed.Feed != nil { 72 for _, fv := range authorFeed.Feed { 73 if fv == nil || fv.Post == nil { 74 continue 75 } 76 if uri := extractReplyParentURI(fv.Post); uri != "" { 77 parentURIsSet[uri] = struct{}{} 78 } 79 chain := GetReplyChainInfos(fv.Post) 80 for _, pi := range chain { 81 if pi.Uri != "" { 82 parentURIsSet[pi.Uri] = struct{}{} 83 } 84 } 85 } 86 } 87 88 var parentURIs []string 89 for u := range parentURIsSet { 90 parentURIs = append(parentURIs, u) 91 } 92 93 parentPreviews := map[string]ParentInfo{} 94 if len(parentURIs) > 0 { 95 const batchSize = 25 96 for i := 0; i < len(parentURIs); i += batchSize { 97 end := i + batchSize 98 if end > len(parentURIs) { 99 end = len(parentURIs) 100 } 101 batch := parentURIs[i:end] 102 postsMap, err := fetchPostsBatch(r.Context(), c, batch) 103 if err != nil { 104 log.Printf("DEBUG: handleProfile - fetchPostsBatch error: %v", err) 105 continue 106 } 107 for uri, pv := range postsMap { 108 if pv == nil { 109 continue 110 } 111 pi := ParentInfo{Uri: uri} 112 if pv.Author != nil { 113 if pv.Author.DisplayName != nil && *pv.Author.DisplayName != "" { 114 pi.AuthorName = *pv.Author.DisplayName 115 } else if pv.Author.Handle != "" { 116 pi.AuthorName = pv.Author.Handle 117 } 118 if pv.Author.Handle != "" { 119 pi.AuthorHandle = pv.Author.Handle 120 } 121 if pv.Author.Avatar != nil { 122 pi.Avatar = *pv.Author.Avatar 123 } 124 } 125 pi.Text = getPostText(pv.Record) 126 if pv.Uri != "" { 127 pi.PostURL = getPostURL(pv) 128 } 129 pi.IndexedAt = pv.IndexedAt 130 // populate media preview if present 131 if m := GetPostMedia(pv); m != nil { 132 pi.Media = m 133 } 134 // like count if available 135 if pv.LikeCount != nil { 136 pi.LikeCount = int(*pv.LikeCount) 137 } 138 pi.IsFav = getIsFav(pv) 139 parentPreviews[uri] = pi 140 } 141 } 142 } 143 144 data := ProfilePageData{ 145 Title: "Profile - Tuiter 2006", 146 Profile: profileView, 147 Feed: authorFeed, 148 Follows: followsList, 149 Posts: PostsList{Items: authorFeed.Feed, Cursor: getCursorFromAuthorFeed(authorFeed), ParentPreviews: parentPreviews}, 150 PostBoxHandle: postBoxHandle, 151 // provide the signed-in profile explicitly 152 SignedIn: myProfile, 153 } 154 155 executeTemplate(w, "profile.html", data) 156}