my fork of the bluesky client

bskyweb: proof-of-concept golang daemon to serve SPA (#275)

* gitignore: /dist/

* bskyweb: initial work-in-progress

* bskyweb: import icons from bluesky-website

* bskyweb: switch to pongo2 templates; iterate on views

* bskyweb: example.env (and docs)

* bskyweb: go fmt

* bskyweb: remove plan file

* bskyweb: README: tweak formatting

* prettier: ignore /dist/, bskyweb templates

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>

authored by bnewbold.net

Paul Frazee and committed by
GitHub
8629e167 528e14fe

+796 -2
+5 -1
.gitignore
··· 65 65 junit.xml 66 66 artifacts 67 67 68 + # Web bundle outputs 69 + /dist/ 70 + 71 + # Expo 68 72 .expo/ 69 73 dist/ 70 74 *.jks ··· 76 80 web-build/ 77 81 78 82 # Temporary files created by Metro to check the health of the file watcher 79 - .metro-health-check* 83 + .metro-health-check*
+4 -1
.prettierignore
··· 2 2 android 3 3 src/third-party 4 4 src/app.json 5 - public 5 + public 6 + /bskyweb/templates 7 + /dist/ 8 + /.watchmanconfig
+3
bskyweb/.gitignore
··· 1 + /static/bundle.web.js 2 + /bskyweb 3 + .env
+39
bskyweb/README.md
··· 1 + ## Build / Develop 2 + 3 + ### SPA Bundle (monolithic static javascript file) 4 + 5 + To build the SPA bundle (`bundle.web.js`), first get a Javascript development 6 + environment set up. Either follow the top-level README, or something quick 7 + like: 8 + 9 + # install nodejs 18 (specifically) 10 + nvm install 18 11 + nvm use 18 12 + npm install --global yarn 13 + 14 + # setup tools and deps (in top level of this repo) 15 + yarn install --frozen-lockfile 16 + 17 + # run yarn web dev server, if you wanted 18 + yarn web 19 + 20 + Then build and copy over the big 'ol `bundle.web.js` file: 21 + 22 + # in the top level of this repo 23 + yarn webpack build --config ./web/webpack.config.js -d inline-source-map --color 24 + cp dist/bundle.web.js bskyweb/static/ 25 + 26 + ### Golang Daemon 27 + 28 + Install golang. We are generally using v1.19+. 29 + 30 + In this directory (`bskyweb/`): 31 + 32 + # re-build and run daemon 33 + go run ./cmd/bskyweb serve 34 + 35 + # build and output a binary 36 + go build -o bskyweb ./cmd/bskyweb/ 37 + 38 + The easiest way to configure the daemon is to copy `example.env` to `.env` and 39 + fill in auth values there.
+68
bskyweb/cmd/bskyweb/main.go
··· 1 + package main 2 + 3 + import ( 4 + "os" 5 + 6 + logging "github.com/ipfs/go-log" 7 + "github.com/joho/godotenv" 8 + "github.com/urfave/cli/v2" 9 + ) 10 + 11 + var log = logging.Logger("bskyweb") 12 + 13 + func init() { 14 + logging.SetAllLoggers(logging.LevelDebug) 15 + //logging.SetAllLoggers(logging.LevelWarn) 16 + } 17 + 18 + func main() { 19 + 20 + // only try dotenv if it exists 21 + if _, err := os.Stat(".env"); err == nil { 22 + err := godotenv.Load() 23 + if err != nil { 24 + log.Fatal("Error loading .env file") 25 + } 26 + } 27 + 28 + run(os.Args) 29 + } 30 + 31 + func run(args []string) { 32 + 33 + app := cli.App{ 34 + Name: "bskyweb", 35 + Usage: "web server for bsky.app web app (SPA)", 36 + } 37 + 38 + app.Flags = []cli.Flag{ 39 + &cli.StringFlag{ 40 + Name: "pds-host", 41 + Usage: "method, hostname, and port of PDS instance", 42 + Value: "http://localhost:4849", 43 + EnvVars: []string{"ATP_PDS_HOST"}, 44 + }, 45 + &cli.StringFlag{ 46 + Name: "handle", 47 + Usage: "for PDS login", 48 + Required: true, 49 + EnvVars: []string{"ATP_AUTH_HANDLE"}, 50 + }, 51 + &cli.StringFlag{ 52 + Name: "password", 53 + Usage: "for PDS login", 54 + Required: true, 55 + EnvVars: []string{"ATP_AUTH_PASSWORD"}, 56 + }, 57 + // TODO: local IP/port to bind on 58 + } 59 + 60 + app.Commands = []*cli.Command{ 61 + &cli.Command{ 62 + Name: "serve", 63 + Usage: "run the server", 64 + Action: serve, 65 + }, 66 + } 67 + app.RunAndExitOnError() 68 + }
+190
bskyweb/cmd/bskyweb/server.go
··· 1 + package main 2 + 3 + import ( 4 + "context" 5 + "errors" 6 + "fmt" 7 + "io" 8 + "net/http" 9 + 10 + comatproto "github.com/bluesky-social/indigo/api/atproto" 11 + appbsky "github.com/bluesky-social/indigo/api/bsky" 12 + cliutil "github.com/bluesky-social/indigo/cmd/gosky/util" 13 + "github.com/bluesky-social/indigo/xrpc" 14 + 15 + "github.com/flosch/pongo2/v6" 16 + "github.com/labstack/echo/v4" 17 + "github.com/labstack/echo/v4/middleware" 18 + "github.com/urfave/cli/v2" 19 + ) 20 + 21 + // TODO: embed templates in executable 22 + 23 + type Renderer struct { 24 + Debug bool 25 + } 26 + 27 + func (r Renderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error { 28 + 29 + var ctx pongo2.Context 30 + 31 + if data != nil { 32 + var ok bool 33 + ctx, ok = data.(pongo2.Context) 34 + 35 + if !ok { 36 + return errors.New("no pongo2.Context data was passed...") 37 + } 38 + } 39 + 40 + var t *pongo2.Template 41 + var err error 42 + 43 + if r.Debug { 44 + t, err = pongo2.FromFile(name) 45 + } else { 46 + t, err = pongo2.FromCache(name) 47 + } 48 + 49 + if err != nil { 50 + return err 51 + } 52 + 53 + return t.ExecuteWriter(ctx, w) 54 + } 55 + 56 + type Server struct { 57 + xrpcc *xrpc.Client 58 + } 59 + 60 + func serve(cctx *cli.Context) error { 61 + 62 + // create a new session 63 + // TODO: does this work with no auth at all? 64 + xrpcc := &xrpc.Client{ 65 + Client: cliutil.NewHttpClient(), 66 + Host: cctx.String("pds-host"), 67 + Auth: &xrpc.AuthInfo{ 68 + Handle: cctx.String("handle"), 69 + }, 70 + } 71 + 72 + auth, err := comatproto.SessionCreate(context.TODO(), xrpcc, &comatproto.SessionCreate_Input{ 73 + Identifier: &xrpcc.Auth.Handle, 74 + Password: cctx.String("password"), 75 + }) 76 + if err != nil { 77 + return err 78 + } 79 + xrpcc.Auth.AccessJwt = auth.AccessJwt 80 + xrpcc.Auth.RefreshJwt = auth.RefreshJwt 81 + xrpcc.Auth.Did = auth.Did 82 + xrpcc.Auth.Handle = auth.Handle 83 + 84 + server := Server{xrpcc} 85 + 86 + e := echo.New() 87 + e.HideBanner = true 88 + e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ 89 + Format: "method=${method} path=${uri} status=${status} latency=${latency_human}\n", 90 + })) 91 + e.Renderer = Renderer{Debug: true} 92 + e.HTTPErrorHandler = customHTTPErrorHandler 93 + 94 + // configure routes 95 + e.File("/robots.txt", "static/robots.txt") 96 + e.Static("/static", "static") 97 + 98 + e.GET("/", server.WebHome) 99 + 100 + // generic routes 101 + e.GET("/contacts", server.WebGeneric) 102 + e.GET("/search", server.WebGeneric) 103 + e.GET("/notifications", server.WebGeneric) 104 + e.GET("/settings", server.WebGeneric) 105 + e.GET("/settings", server.WebGeneric) 106 + 107 + // profile endpoints; only first populates info 108 + e.GET("/profile/:handle", server.WebProfile) 109 + e.GET("/profile/:handle/follows", server.WebGeneric) 110 + e.GET("/profile/:handle/following", server.WebGeneric) 111 + 112 + // post endpoints; only first populates info 113 + e.GET("/profile/:handle/post/:rkey", server.WebPost) 114 + e.GET("/profile/:handle/post/:rkey/upvoted-by", server.WebGeneric) 115 + e.GET("/profile/:handle/post/:rkey/downvoted-by", server.WebGeneric) 116 + e.GET("/profile/:handle/post/:rkey/reposted-by", server.WebGeneric) 117 + 118 + bind := "localhost:8100" 119 + log.Infof("starting server bind=%s", bind) 120 + return e.Start(bind) 121 + } 122 + 123 + func customHTTPErrorHandler(err error, c echo.Context) { 124 + code := http.StatusInternalServerError 125 + if he, ok := err.(*echo.HTTPError); ok { 126 + code = he.Code 127 + } 128 + c.Logger().Error(err) 129 + data := pongo2.Context{ 130 + "statusCode": code, 131 + } 132 + c.Render(code, "templates/error.html", data) 133 + } 134 + 135 + // handler for endpoint that have no specific server-side handling 136 + func (srv *Server) WebGeneric(c echo.Context) error { 137 + data := pongo2.Context{} 138 + return c.Render(http.StatusOK, "templates/base.html", data) 139 + } 140 + 141 + func (srv *Server) WebHome(c echo.Context) error { 142 + data := pongo2.Context{} 143 + return c.Render(http.StatusOK, "templates/home.html", data) 144 + } 145 + 146 + func (srv *Server) WebPost(c echo.Context) error { 147 + data := pongo2.Context{} 148 + handle := c.Param("handle") 149 + rkey := c.Param("rkey") 150 + // sanity check argument 151 + if len(handle) > 4 && len(handle) < 128 && len(rkey) > 0 { 152 + ctx := context.TODO() 153 + // requires two fetches: first fetch profile (!) 154 + pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, handle) 155 + if err != nil { 156 + log.Warnf("failed to fetch handle: %s\t%v", handle, err) 157 + } else { 158 + did := pv.Did 159 + data["did"] = did 160 + 161 + // then fetch the post thread (with extra context) 162 + uri := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", did, rkey) 163 + tpv, err := appbsky.FeedGetPostThread(ctx, srv.xrpcc, 1, uri) 164 + if err != nil { 165 + log.Warnf("failed to fetch post: %s\t%v", uri, err) 166 + } else { 167 + data["postView"] = tpv.Thread.FeedGetPostThread_ThreadViewPost.Post 168 + } 169 + } 170 + 171 + } 172 + return c.Render(http.StatusOK, "templates/post.html", data) 173 + } 174 + 175 + func (srv *Server) WebProfile(c echo.Context) error { 176 + data := pongo2.Context{} 177 + handle := c.Param("handle") 178 + // sanity check argument 179 + if len(handle) > 4 && len(handle) < 128 { 180 + ctx := context.TODO() 181 + pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, handle) 182 + if err != nil { 183 + log.Warnf("failed to fetch handle: %s\t%v", handle, err) 184 + } else { 185 + data["profileView"] = pv 186 + } 187 + } 188 + 189 + return c.Render(http.StatusOK, "templates/profile.html", data) 190 + }
+4
bskyweb/example.env
··· 1 + GOLOG_LOG_LEVEL=info 2 + ATP_PDS_HOST=https://bsky.social 3 + ATP_AUTH_HANDLE=TODO 4 + ATP_AUTH_PASSWORD=TODO
+72
bskyweb/go.mod
··· 1 + module github.com/bluesky-social/social-app/bskyweb 2 + 3 + go 1.19 4 + 5 + require ( 6 + github.com/bluesky-social/indigo v0.0.0-20230307000525-294e33e70185 7 + github.com/ipfs/go-log v1.0.5 8 + github.com/joho/godotenv v1.5.1 9 + github.com/labstack/echo/v4 v4.10.2 10 + github.com/urfave/cli/v2 v2.25.0 11 + ) 12 + 13 + require ( 14 + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect 15 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect 16 + github.com/flosch/pongo2/v6 v6.0.0 // indirect 17 + github.com/go-logr/logr v1.2.3 // indirect 18 + github.com/go-logr/stdr v1.2.2 // indirect 19 + github.com/goccy/go-json v0.10.0 // indirect 20 + github.com/gogo/protobuf v1.3.2 // indirect 21 + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect 22 + github.com/ipfs/go-cid v0.3.2 // indirect 23 + github.com/ipfs/go-log/v2 v2.5.1 // indirect 24 + github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 // indirect 25 + github.com/jackc/pgpassfile v1.0.0 // indirect 26 + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect 27 + github.com/jackc/pgx/v5 v5.2.0 // indirect 28 + github.com/jinzhu/inflection v1.0.0 // indirect 29 + github.com/jinzhu/now v1.1.5 // indirect 30 + github.com/klauspost/cpuid/v2 v2.2.3 // indirect 31 + github.com/labstack/gommon v0.4.0 // indirect 32 + github.com/lestrrat-go/blackmagic v1.0.1 // indirect 33 + github.com/lestrrat-go/httpcc v1.0.1 // indirect 34 + github.com/lestrrat-go/httprc v1.0.4 // indirect 35 + github.com/lestrrat-go/iter v1.0.2 // indirect 36 + github.com/lestrrat-go/jwx/v2 v2.0.8 // indirect 37 + github.com/lestrrat-go/option v1.0.1 // indirect 38 + github.com/mattn/go-colorable v0.1.13 // indirect 39 + github.com/mattn/go-isatty v0.0.17 // indirect 40 + github.com/mattn/go-sqlite3 v1.14.16 // indirect 41 + github.com/minio/sha256-simd v1.0.0 // indirect 42 + github.com/mitchellh/go-homedir v1.1.0 // indirect 43 + github.com/mr-tron/base58 v1.2.0 // indirect 44 + github.com/multiformats/go-base32 v0.1.0 // indirect 45 + github.com/multiformats/go-base36 v0.2.0 // indirect 46 + github.com/multiformats/go-multibase v0.1.1 // indirect 47 + github.com/multiformats/go-multihash v0.2.1 // indirect 48 + github.com/multiformats/go-varint v0.0.7 // indirect 49 + github.com/opentracing/opentracing-go v1.2.0 // indirect 50 + github.com/russross/blackfriday/v2 v2.1.0 // indirect 51 + github.com/spaolacci/murmur3 v1.1.0 // indirect 52 + github.com/valyala/bytebufferpool v1.0.0 // indirect 53 + github.com/valyala/fasttemplate v1.2.2 // indirect 54 + github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // indirect 55 + github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220 // indirect 56 + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect 57 + go.opentelemetry.io/otel v1.11.2 // indirect 58 + go.opentelemetry.io/otel/trace v1.11.2 // indirect 59 + go.uber.org/atomic v1.10.0 // indirect 60 + go.uber.org/multierr v1.9.0 // indirect 61 + go.uber.org/zap v1.24.0 // indirect 62 + golang.org/x/crypto v0.6.0 // indirect 63 + golang.org/x/net v0.7.0 // indirect 64 + golang.org/x/sys v0.5.0 // indirect 65 + golang.org/x/text v0.7.0 // indirect 66 + golang.org/x/time v0.3.0 // indirect 67 + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect 68 + gorm.io/driver/postgres v1.4.6 // indirect 69 + gorm.io/driver/sqlite v1.4.4 // indirect 70 + gorm.io/gorm v1.24.3 // indirect 71 + lukechampine.com/blake3 v1.1.7 // indirect 72 + )
+287
bskyweb/go.sum
··· 1 + github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 2 + github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= 3 + github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 4 + github.com/bluesky-social/indigo v0.0.0-20230306194356-5958f14d5152 h1:7fHM+tQHJN5lsMU8FvV4bNuWpD0Dd+pAUSuoLYdcYIQ= 5 + github.com/bluesky-social/indigo v0.0.0-20230306194356-5958f14d5152/go.mod h1:xy2hI4NMC6fgUefSJcCst6E0yo9Xbfd97aF27lgHyHE= 6 + github.com/bluesky-social/indigo v0.0.0-20230307000525-294e33e70185 h1:WnaOpRFWE8Tmw0IeXEEthsqBZtNG6/niokmWANv/aEU= 7 + github.com/bluesky-social/indigo v0.0.0-20230307000525-294e33e70185/go.mod h1:xy2hI4NMC6fgUefSJcCst6E0yo9Xbfd97aF27lgHyHE= 8 + github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= 9 + github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 10 + github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 11 + github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 12 + github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 13 + github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 14 + github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= 15 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= 16 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= 17 + github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU= 18 + github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU= 19 + github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 20 + github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= 21 + github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 22 + github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 23 + github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 24 + github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 25 + github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= 26 + github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 27 + github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 28 + github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 29 + github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= 30 + github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 31 + github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 32 + github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 33 + github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 34 + github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= 35 + github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= 36 + github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= 37 + github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= 38 + github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= 39 + github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= 40 + github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= 41 + github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= 42 + github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= 43 + github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= 44 + github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= 45 + github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= 46 + github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= 47 + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= 48 + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= 49 + github.com/jackc/pgx/v5 v5.2.0 h1:NdPpngX0Y6z6XDFKqmFQaE+bCtkqzvQIOt1wvBlAqs8= 50 + github.com/jackc/pgx/v5 v5.2.0/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk= 51 + github.com/jackc/puddle/v2 v2.1.2/go.mod h1:2lpufsF5mRHO6SuZkm0fNYxM6SWHfvyFj62KwNzgels= 52 + github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 53 + github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 54 + github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 55 + github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= 56 + github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 57 + github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 58 + github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 59 + github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 60 + github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 61 + github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 62 + github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 63 + github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= 64 + github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 65 + github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 66 + github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 67 + github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 68 + github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 69 + github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 70 + github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 71 + github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= 72 + github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= 73 + github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= 74 + github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= 75 + github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A= 76 + github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= 77 + github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= 78 + github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= 79 + github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= 80 + github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8= 81 + github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= 82 + github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= 83 + github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= 84 + github.com/lestrrat-go/jwx v1.2.25 h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0otA= 85 + github.com/lestrrat-go/jwx/v2 v2.0.8 h1:jCFT8oc0hEDVjgUgsBy1F9cbjsjAVZSXNi7JaU9HR/Q= 86 + github.com/lestrrat-go/jwx/v2 v2.0.8/go.mod h1:zLxnyv9rTlEvOUHbc48FAfIL8iYu2hHvIRaTFGc8mT0= 87 + github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= 88 + github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= 89 + github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= 90 + github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 91 + github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 92 + github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 93 + github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 94 + github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 95 + github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= 96 + github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 97 + github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= 98 + github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= 99 + github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= 100 + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 101 + github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 102 + github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= 103 + github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= 104 + github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 105 + github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 106 + github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 107 + github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 108 + github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= 109 + github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 110 + github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= 111 + github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= 112 + github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= 113 + github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= 114 + github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= 115 + github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= 116 + github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= 117 + github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= 118 + github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= 119 + github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 120 + github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= 121 + github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= 122 + github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 123 + github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= 124 + github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= 125 + github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= 126 + github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= 127 + github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 128 + github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 129 + github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 130 + github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 131 + github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 132 + github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 133 + github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 134 + github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 135 + github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 136 + github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 137 + github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 138 + github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 139 + github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 140 + github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 141 + github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 142 + github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 143 + github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 144 + github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 145 + github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 146 + github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 147 + github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= 148 + github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 149 + github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8= 150 + github.com/urfave/cli/v2 v2.25.0/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= 151 + github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 152 + github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 153 + github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 154 + github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= 155 + github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 156 + github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o= 157 + github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 158 + github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220 h1:EO/9z3yDvx1van1/0esdcqhalZZQGRj3I1BPTWr5k3A= 159 + github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220/go.mod h1:qPtRyexGM5XMHFIfjH+EiA/A/1n2JakWEdMPC53pJAE= 160 + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= 161 + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= 162 + github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 163 + github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 164 + github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 165 + github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 166 + go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0= 167 + go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI= 168 + go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0= 169 + go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA= 170 + go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 171 + go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 172 + go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= 173 + go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 174 + go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 175 + go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= 176 + go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 177 + go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 178 + go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= 179 + go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= 180 + go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 181 + go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= 182 + go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= 183 + go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= 184 + go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 185 + golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 186 + golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 187 + golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 188 + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 189 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 190 + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 191 + golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 192 + golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 193 + golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= 194 + golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= 195 + golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= 196 + golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 197 + golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 198 + golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 199 + golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 200 + golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 201 + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 202 + golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 203 + golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 204 + golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 205 + golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 206 + golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 207 + golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 208 + golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 209 + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 210 + golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 211 + golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= 212 + golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= 213 + golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 214 + golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 215 + golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 216 + golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 217 + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 218 + golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 219 + golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 220 + golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 221 + golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 222 + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 223 + golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 224 + golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 225 + golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 226 + golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 227 + golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 228 + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 229 + golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 230 + golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 231 + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 232 + golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 233 + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 234 + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 235 + golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 236 + golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= 237 + golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 238 + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 239 + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 240 + golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= 241 + golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 242 + golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 243 + golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 244 + golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 245 + golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 246 + golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 247 + golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= 248 + golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 249 + golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= 250 + golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 251 + golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 252 + golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 253 + golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 254 + golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 255 + golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 256 + golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 257 + golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 258 + golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 259 + golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 260 + golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 261 + golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 262 + golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 263 + golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 264 + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 265 + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= 266 + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= 267 + gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 268 + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 269 + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 270 + gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 271 + gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 272 + gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 273 + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 274 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 275 + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 276 + gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 277 + gorm.io/driver/postgres v1.4.6 h1:1FPESNXqIKG5JmraaH2bfCVlMQ7paLoCreFxDtqzwdc= 278 + gorm.io/driver/postgres v1.4.6/go.mod h1:UJChCNLFKeBqQRE+HrkFUbKbq9idPXmTOk2u4Wok8S4= 279 + gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc= 280 + gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= 281 + gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= 282 + gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= 283 + gorm.io/gorm v1.24.3 h1:WL2ifUmzR/SLp85CSURAfybcHnGZ+yLSGSxgYXlFBHg= 284 + gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= 285 + honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 286 + lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= 287 + lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
bskyweb/static/apple-touch-icon.png

This is a binary file and will not be displayed.

bskyweb/static/favicon-16x16.png

This is a binary file and will not be displayed.

bskyweb/static/favicon-32x32.png

This is a binary file and will not be displayed.

bskyweb/static/favicon.ico

This is a binary file and will not be displayed.

bskyweb/static/favicon.png

This is a binary file and will not be displayed.

+1
bskyweb/static/robots.txt
··· 1 + # hello friends!
bskyweb/static/social-card-default.png

This is a binary file and will not be displayed.

+51
bskyweb/templates/base.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 + <meta name="referrer" content="origin-when-cross-origin"> 7 + <title>{%- block head_title -%}Bluesky{%- endblock -%}</title> 8 + <!-- Hello Humans! API docs at https://atproto.com --> 9 + <style> 10 + /* These styles make the body full-height */ 11 + html, body { height: 100%; } 12 + /* These styles disable body scrolling if you are using <ScrollView> */ 13 + body { overflow: hidden; } 14 + /* These styles make the root element full-height */ 15 + #app-root { display:flex; height:100%; } 16 + /* Remove focus state on inputs */ 17 + *:focus { outline: 0; } 18 + </style> 19 + {% block head_bundle -%}<script defer src="/static/bundle.web.js"></script>{%- endblock %} 20 + <link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png"/> 21 + <link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png"/> 22 + <link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png"/> 23 + {% block head_page_meta -%} 24 + <meta property="og:title" content="Bluesky Social"/> 25 + <meta property="og:type" content="article"/> 26 + <meta property="og:image" content="/static/default-social-card.png"/> 27 + <meta name="twitter:title" content="Bluesky Social"/> 28 + <meta name="twitter:description" content="See what&#x27;s next."/> 29 + <meta name="twitter:image" content="/static/default-social-card.png"/> 30 + <meta name="twitter:card" content="summary_large_image"/> 31 + <meta name="twitter:site" content="@bluesky"/> 32 + {%- endblock %} 33 + <!-- TODO: link rel=canonical --> 34 + <!-- TODO: analytics code --> 35 + <!-- TODO: could put <link rel="preload"> tags here --> 36 + <meta name="generator" name="bskyweb"> 37 + {% block head_metadata %}{% endblock %} 38 + </head> 39 + <body> 40 + {%- block body_all %} 41 + <div id="app-root"> 42 + <noscript> 43 + {%- block noscript_extra %}{% endblock -%} 44 + <h1>Javascript Required</h1> 45 + <p>This is a heavily interactive web application, and Javascript is required. Simple HTML interfaces are possible, but that is not what this is. 46 + <p>Learn more about Bluesky at <a href="https://blueskyweb.xyz">blueskyweb.xyz</a> and <a href="https://atproto.com">atproto.com</a>. 47 + </noscript> 48 + </div> 49 + {% endblock -%} 50 + </body> 51 + </html>
+15
bskyweb/templates/error.html
··· 1 + {% extends "base.html" %} 2 + 3 + {% block head_title %}Error {{ statusCode }} - Bluesky{% endblock %} 4 + 5 + {# don't include the bundle on error pages #} 6 + {% block head_bundle %}{% endblock %} 7 + 8 + {% block body_all %} 9 + {% if statusCode == 404 %} 10 + <h1>404: Not Found</h1> 11 + {% else %} 12 + <h1>{{ statusCode }}: Server Error</h1> 13 + <p>Sorry about that! Our <a href="https://bluesky.statuspage.io/">Status Page</a> might have more context. 14 + {% endif %} 15 + {% endblock %}
+7
bskyweb/templates/home.html
··· 1 + {% extends "base.html" %} 2 + 3 + {% block head_title %}Bluesky{% endblock %} 4 + 5 + {% block noscript_extra %} 6 + <p>This is the home page. 7 + {% endblock %}
+25
bskyweb/templates/post.html
··· 1 + {% extends "base.html" %} 2 + 3 + {% block head_page_meta -%} 4 + <!-- TODO: "same as" indication with at:// URI? --> 5 + {%- if postView -%} 6 + <meta property="og:type" content="article"/> 7 + <meta name="twitter:card" content="summary"/> 8 + {%- if postView.Author.DisplayName -%} 9 + <meta property="og:title" content="{{ postView.Author.DisplayName }} / {{ postView.Author.Handle }}"/> 10 + <meta name="twitter:title" content="{{ postView.Author.DisplayName }} / {{ postView.Author.Handle }}"/> 11 + {%- else -%} 12 + <meta property="og:title" content="{{ postView.Author.Handle }}"/> 13 + <meta name="twitter:title" content="{{ postView.Author.Handle }}"/> 14 + {%- endif -%} 15 + {%- if postView.Record.Text -%} 16 + <meta name="twitter:description" content="{{ postView.Record.Text }}"/> 17 + <!-- TODO: could put any images in here, or author avatar --> 18 + {%- endif -%} 19 + {%- endif -%} 20 + {%- endblock %} 21 + 22 + {% block noscript_extra -%} 23 + <p>{{ postView.Author.DisplayName }} / {{ postView.Author.Handle }} 24 + <p>{{ postView.Record.Text }} 25 + {%- endblock %}
+25
bskyweb/templates/profile.html
··· 1 + {% extends "base.html" %} 2 + 3 + {% block head_page_meta -%} 4 + <!-- TODO: "same as" indication with DID? --> 5 + {%- if profileView -%} 6 + <meta property="og:type" content="article"/> 7 + <meta name="twitter:card" content="summary"/> 8 + {%- if profileView.DisplayName -%} 9 + <meta property="og:title" content="{{ profileView.DisplayName }} / {{ profileView.Handle }}"/> 10 + <meta name="twitter:title" content="{{ profileView.DisplayName }} / {{ profileView.Handle }}"/> 11 + {%- else -%} 12 + <meta property="og:title" content="{{ profileView.Handle }}"/> 13 + <meta name="twitter:title" content="{{ profileView.Handle }}"/> 14 + {%- endif -%} 15 + <meta name="twitter:description" content="{{ profileView.Description }}"/> 16 + {%- if profileView.Avatar -%} 17 + <meta name="twitter:image" content="{{ profileView.Avatar }}"/> 18 + {%- endif -%} 19 + {%- endif -%} 20 + {%- endblock %} 21 + 22 + {% block noscript_extra -%} 23 + <p>{{ profileView.DisplayName }} / {{ profileView.Handle }} 24 + <p>{{ profileView.Description }} 25 + {%- endblock %}