Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview: initial posthog events

authored by

Anirudh Oppiliappan and committed by
Tangled
9d303653 3953ee26

+133 -76
+6
appview/config.go
··· 36 36 SharedSecret string `env:"SHARED_SECRET"` 37 37 } 38 38 39 + type PosthogConfig struct { 40 + ApiKey string `env:"API_KEY"` 41 + Endpoint string `env:"ENDPOINT, default=https://eu.i.posthog.com"` 42 + } 43 + 39 44 type Config struct { 40 45 Core CoreConfig `env:",prefix=TANGLED_"` 41 46 Jetstream JetstreamConfig `env:",prefix=TANGLED_JETSTREAM_"` 42 47 Resend ResendConfig `env:",prefix=TANGLED_RESEND_"` 48 + Posthog PosthogConfig `env:",prefix=TANGLED_POSTHOG_"` 43 49 Camo CamoConfig `env:",prefix=TANGLED_CAMO_"` 44 50 Avatar AvatarConfig `env:",prefix=TANGLED_AVATAR_"` 45 51 OAuth OAuthConfig `env:",prefix=TANGLED_OAUTH_"`
+12
appview/oauth/handler/handler.go
··· 12 12 "github.com/gorilla/sessions" 13 13 "github.com/haileyok/atproto-oauth-golang/helpers" 14 14 "github.com/lestrrat-go/jwx/v2/jwk" 15 + "github.com/posthog/posthog-go" 15 16 "tangled.sh/tangled.sh/core/appview" 16 17 "tangled.sh/tangled.sh/core/appview/db" 17 18 "tangled.sh/tangled.sh/core/appview/knotclient" ··· 35 34 Store *sessions.CookieStore 36 35 OAuth *oauth.OAuth 37 36 Enforcer *rbac.Enforcer 37 + Posthog posthog.Client 38 38 } 39 39 40 40 func (o *OAuthHandler) Router() http.Handler { ··· 249 247 250 248 log.Println("session saved successfully") 251 249 go o.addToDefaultKnot(oauthRequest.Did) 250 + 251 + if !o.Config.Core.Dev { 252 + err = o.Posthog.Enqueue(posthog.Capture{ 253 + DistinctId: oauthRequest.Did, 254 + Event: "signin", 255 + }) 256 + if err != nil { 257 + log.Println("failed to enqueue posthog event:", err) 258 + } 259 + } 252 260 253 261 http.Redirect(w, r, "/", http.StatusFound) 254 262 }
+23
appview/state/follow.go
··· 7 7 8 8 comatproto "github.com/bluesky-social/indigo/api/atproto" 9 9 lexutil "github.com/bluesky-social/indigo/lex/util" 10 + "github.com/posthog/posthog-go" 10 11 "tangled.sh/tangled.sh/core/api/tangled" 11 12 "tangled.sh/tangled.sh/core/appview" 12 13 "tangled.sh/tangled.sh/core/appview/db" ··· 71 70 FollowStatus: db.IsFollowing, 72 71 }) 73 72 73 + if !s.config.Core.Dev { 74 + err = s.posthog.Enqueue(posthog.Capture{ 75 + DistinctId: currentUser.Did, 76 + Event: "follow", 77 + Properties: posthog.Properties{"subject": subjectIdent.DID.String()}, 78 + }) 79 + if err != nil { 80 + log.Println("failed to enqueue posthog event:", err) 81 + } 82 + } 83 + 74 84 return 75 85 case http.MethodDelete: 76 86 // find the record in the db ··· 112 100 UserDid: subjectIdent.DID.String(), 113 101 FollowStatus: db.IsNotFollowing, 114 102 }) 103 + 104 + if !s.config.Core.Dev { 105 + err = s.posthog.Enqueue(posthog.Capture{ 106 + DistinctId: currentUser.Did, 107 + Event: "unfollow", 108 + Properties: posthog.Properties{"subject": subjectIdent.DID.String()}, 109 + }) 110 + if err != nil { 111 + log.Println("failed to enqueue posthog event:", err) 112 + } 113 + } 115 114 116 115 return 117 116 }
+11
appview/state/profile.go
··· 15 15 "github.com/bluesky-social/indigo/atproto/syntax" 16 16 lexutil "github.com/bluesky-social/indigo/lex/util" 17 17 "github.com/go-chi/chi/v5" 18 + "github.com/posthog/posthog-go" 18 19 "tangled.sh/tangled.sh/core/api/tangled" 19 20 "tangled.sh/tangled.sh/core/appview/db" 20 21 "tangled.sh/tangled.sh/core/appview/pages" ··· 346 345 log.Println("failed to update profile", err) 347 346 s.pages.Notice(w, "update-profile", "Failed to update profile, try again later.") 348 347 return 348 + } 349 + 350 + if !s.config.Core.Dev { 351 + err = s.posthog.Enqueue(posthog.Capture{ 352 + DistinctId: user.Did, 353 + Event: "edit_profile", 354 + }) 355 + if err != nil { 356 + log.Println("failed to enqueue posthog event:", err) 357 + } 349 358 } 350 359 351 360 s.pages.HxRedirect(w, "/"+user.Did)
+23
appview/state/pull.go
··· 28 28 lexutil "github.com/bluesky-social/indigo/lex/util" 29 29 "github.com/go-chi/chi/v5" 30 30 "github.com/google/uuid" 31 + "github.com/posthog/posthog-go" 31 32 ) 32 33 33 34 // htmx fragment ··· 606 605 return 607 606 } 608 607 608 + if !s.config.Core.Dev { 609 + err = s.posthog.Enqueue(posthog.Capture{ 610 + DistinctId: user.Did, 611 + Event: "new_pull_comment", 612 + Properties: posthog.Properties{"repo_at": f.RepoAt.String(), "pull_id": pull.PullId}, 613 + }) 614 + if err != nil { 615 + log.Println("failed to enqueue posthog event:", err) 616 + } 617 + } 618 + 609 619 s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", f.OwnerSlashRepo(), pull.PullId, commentId)) 610 620 return 611 621 } ··· 992 980 log.Println("failed to create pull request", err) 993 981 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") 994 982 return 983 + } 984 + 985 + if !s.config.Core.Dev { 986 + err = s.posthog.Enqueue(posthog.Capture{ 987 + DistinctId: user.Did, 988 + Event: "new_pull", 989 + Properties: posthog.Properties{"repo_at": f.RepoAt.String(), "pull_id": pullId}, 990 + }) 991 + if err != nil { 992 + log.Println("failed to enqueue posthog event:", err) 993 + } 995 994 } 996 995 997 996 s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pullId))
+12
appview/state/repo.go
··· 33 33 securejoin "github.com/cyphar/filepath-securejoin" 34 34 "github.com/go-chi/chi/v5" 35 35 "github.com/go-git/go-git/v5/plumbing" 36 + "github.com/posthog/posthog-go" 36 37 37 38 comatproto "github.com/bluesky-social/indigo/api/atproto" 38 39 lexutil "github.com/bluesky-social/indigo/lex/util" ··· 1876 1875 log.Println("failed to set issue at", err) 1877 1876 s.pages.Notice(w, "issues", "Failed to create issue.") 1878 1877 return 1878 + } 1879 + 1880 + if !s.config.Core.Dev { 1881 + err = s.posthog.Enqueue(posthog.Capture{ 1882 + DistinctId: user.Did, 1883 + Event: "new_issue", 1884 + Properties: posthog.Properties{"repo_at": f.RepoAt.String(), "issue_id": issueId}, 1885 + }) 1886 + if err != nil { 1887 + log.Println("failed to enqueue posthog event:", err) 1888 + } 1879 1889 } 1880 1890 1881 1891 s.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issueId))
+1
appview/state/router.go
··· 269 269 Store: sessions.NewCookieStore([]byte(s.config.Core.CookieSecret)), 270 270 OAuth: s.oauth, 271 271 Enforcer: s.enforcer, 272 + Posthog: s.posthog, 272 273 } 273 274 274 275 return oauth.Router()
+23
appview/state/star.go
··· 8 8 comatproto "github.com/bluesky-social/indigo/api/atproto" 9 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 10 lexutil "github.com/bluesky-social/indigo/lex/util" 11 + "github.com/posthog/posthog-go" 11 12 "tangled.sh/tangled.sh/core/api/tangled" 12 13 "tangled.sh/tangled.sh/core/appview" 13 14 "tangled.sh/tangled.sh/core/appview/db" ··· 76 75 }, 77 76 }) 78 77 78 + if !s.config.Core.Dev { 79 + err = s.posthog.Enqueue(posthog.Capture{ 80 + DistinctId: currentUser.Did, 81 + Event: "star", 82 + Properties: posthog.Properties{"repo_at": subjectUri.String()}, 83 + }) 84 + if err != nil { 85 + log.Println("failed to enqueue posthog event:", err) 86 + } 87 + } 88 + 79 89 return 80 90 case http.MethodDelete: 81 91 // find the record in the db ··· 126 114 StarCount: starCount, 127 115 }, 128 116 }) 117 + 118 + if !s.config.Core.Dev { 119 + err = s.posthog.Enqueue(posthog.Capture{ 120 + DistinctId: currentUser.Did, 121 + Event: "unstar", 122 + Properties: posthog.Properties{"repo_at": subjectUri.String()}, 123 + }) 124 + if err != nil { 125 + log.Println("failed to enqueue posthog event:", err) 126 + } 127 + } 129 128 130 129 return 131 130 }
+19 -76
appview/state/state.go
··· 17 17 lexutil "github.com/bluesky-social/indigo/lex/util" 18 18 securejoin "github.com/cyphar/filepath-securejoin" 19 19 "github.com/go-chi/chi/v5" 20 + "github.com/posthog/posthog-go" 20 21 "tangled.sh/tangled.sh/core/api/tangled" 21 22 "tangled.sh/tangled.sh/core/appview" 22 23 "tangled.sh/tangled.sh/core/appview/db" ··· 35 34 tidClock syntax.TIDClock 36 35 pages *pages.Pages 37 36 resolver *appview.Resolver 37 + posthog posthog.Client 38 38 jc *jetstream.JetstreamClient 39 39 config *appview.Config 40 40 } ··· 58 56 resolver := appview.NewResolver() 59 57 60 58 oauth := oauth.NewOAuth(d, config) 59 + 60 + posthog, err := posthog.NewWithConfig(config.Posthog.ApiKey, posthog.Config{Endpoint: config.Posthog.Endpoint}) 61 + if err != nil { 62 + return nil, fmt.Errorf("failed to create posthog client: %w", err) 63 + } 61 64 62 65 wrapper := db.DbWrapper{d} 63 66 jc, err := jetstream.NewJetstreamClient( ··· 95 88 clock, 96 89 pgs, 97 90 resolver, 91 + posthog, 98 92 jc, 99 93 config, 100 94 } ··· 106 98 func TID(c *syntax.TIDClock) string { 107 99 return c.Next().String() 108 100 } 109 - 110 - // func (s *State) Login(w http.ResponseWriter, r *http.Request) { 111 - // ctx := r.Context() 112 - 113 - // switch r.Method { 114 - // case http.MethodGet: 115 - // err := s.pages.Login(w, pages.LoginParams{}) 116 - // if err != nil { 117 - // log.Printf("rendering login page: %s", err) 118 - // } 119 - 120 - // return 121 - // case http.MethodPost: 122 - // handle := strings.TrimPrefix(r.FormValue("handle"), "@") 123 - // appPassword := r.FormValue("app_password") 124 - 125 - // resolved, err := s.resolver.ResolveIdent(ctx, handle) 126 - // if err != nil { 127 - // log.Println("failed to resolve handle:", err) 128 - // s.pages.Notice(w, "login-msg", fmt.Sprintf("\"%s\" is an invalid handle.", handle)) 129 - // return 130 - // } 131 - 132 - // atSession, err := s.oauth.CreateInitialSession(ctx, resolved, appPassword) 133 - // if err != nil { 134 - // s.pages.Notice(w, "login-msg", "Invalid handle or password.") 135 - // return 136 - // } 137 - // sessionish := auth.CreateSessionWrapper{ServerCreateSession_Output: atSession} 138 - 139 - // err = s.oauth.StoreSession(r, w, &sessionish, resolved.PDSEndpoint()) 140 - // if err != nil { 141 - // s.pages.Notice(w, "login-msg", "Failed to login, try again later.") 142 - // return 143 - // } 144 - 145 - // log.Printf("successfully saved session for %s (%s)", atSession.Handle, atSession.Did) 146 - 147 - // did := resolved.DID.String() 148 - // defaultKnot := "knot1.tangled.sh" 149 - 150 - // go func() { 151 - // log.Printf("adding %s to default knot", did) 152 - // err = s.enforcer.AddMember(defaultKnot, did) 153 - // if err != nil { 154 - // log.Println("failed to add user to knot1.tangled.sh: ", err) 155 - // return 156 - // } 157 - // err = s.enforcer.E.SavePolicy() 158 - // if err != nil { 159 - // log.Println("failed to add user to knot1.tangled.sh: ", err) 160 - // return 161 - // } 162 - 163 - // secret, err := db.GetRegistrationKey(s.db, defaultKnot) 164 - // if err != nil { 165 - // log.Println("failed to get registration key for knot1.tangled.sh") 166 - // return 167 - // } 168 - // signedClient, err := NewSignedClient(defaultKnot, secret, s.config.Core.Dev) 169 - // resp, err := signedClient.AddMember(did) 170 - // if err != nil { 171 - // log.Println("failed to add user to knot1.tangled.sh: ", err) 172 - // return 173 - // } 174 - 175 - // if resp.StatusCode != http.StatusNoContent { 176 - // log.Println("failed to add user to knot1.tangled.sh: ", resp.StatusCode) 177 - // return 178 - // } 179 - // }() 180 - 181 - // s.pages.HxRedirect(w, "/") 182 - // return 183 - // } 184 - // } 185 101 186 102 func (s *State) Logout(w http.ResponseWriter, r *http.Request) { 187 103 s.oauth.ClearSession(r, w) ··· 705 773 log.Println("failed to update ACLs", err) 706 774 http.Error(w, err.Error(), http.StatusInternalServerError) 707 775 return 776 + } 777 + 778 + if !s.config.Core.Dev { 779 + err = s.posthog.Enqueue(posthog.Capture{ 780 + DistinctId: user.Did, 781 + Event: "new_repo", 782 + Properties: posthog.Properties{"repo": repoName, "repo_at": repo.AtUri}, 783 + }) 784 + if err != nil { 785 + log.Println("failed to enqueue posthog event:", err) 786 + } 708 787 } 709 788 710 789 s.pages.HxLocation(w, fmt.Sprintf("/@%s/%s", user.Handle, repoName))
+1
go.mod
··· 24 24 github.com/lestrrat-go/jwx/v2 v2.0.12 25 25 github.com/mattn/go-sqlite3 v1.14.24 26 26 github.com/microcosm-cc/bluemonday v1.0.27 27 + github.com/posthog/posthog-go v1.5.5 27 28 github.com/resend/resend-go/v2 v2.15.0 28 29 github.com/sethvargo/go-envconfig v1.1.0 29 30 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e
+2
go.sum
··· 224 224 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 225 225 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0= 226 226 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= 227 + github.com/posthog/posthog-go v1.5.5 h1:2o3j7IrHbTIfxRtj4MPaXKeimuTYg49onNzNBZbwksM= 228 + github.com/posthog/posthog-go v1.5.5/go.mod h1:3RqUmSnPuwmeVj/GYrS75wNGqcAKdpODiwc83xZWgdE= 227 229 github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= 228 230 github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= 229 231 github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=