this repo has no description

feat: add videostream generator

+81 -2
+2 -2
Makefile
··· 3 3 bin/videostream: cmd/videostream/*.go pkg/videostream/*.go 4 4 go build -o $@ ./cmd/videostream 5 5 6 - bin/mostliked: cmd/mostliked/main.go pkg/mostliked/handler.go db/mostliked/*.go pkg/feeds/*.go 6 + bin/mostliked: cmd/mostliked/*.go pkg/mostliked/*.go 7 7 go build -o $@ ./cmd/mostliked 8 8 9 - bin/feedweb: cmd/feedweb/*.go pkg/*/generator.go db/*/*.go pkg/feeds/*.go 9 + bin/feedweb: 10 10 go build -o $@ ./cmd/feedweb 11 11 12 12 .PHONY: clean
+3
cmd/feedweb/main.go
··· 12 12 "github.com/edavis/bsky-feeds/pkg/feeds" 13 13 "github.com/edavis/bsky-feeds/pkg/mostliked" 14 14 "github.com/edavis/bsky-feeds/pkg/popular" 15 + "github.com/edavis/bsky-feeds/pkg/videostream" 15 16 "github.com/labstack/echo/v4" 16 17 "github.com/labstack/echo/v4/middleware" 17 18 sqlite "github.com/mattn/go-sqlite3" ··· 36 37 37 38 "at://did:plc:4nsduwlpivpuur4mqkbfvm6a/app.bsky.feed.generator/popular": popular.Feed, 38 39 "at://did:plc:4nsduwlpivpuur4mqkbfvm6a/app.bsky.feed.generator/popular-dev": popular.Feed, 40 + 41 + "at://did:plc:4nsduwlpivpuur4mqkbfvm6a/app.bsky.feed.generator/videostream": videostream.Feed, 39 42 } 40 43 41 44 func getFeedSkeleton(c echo.Context) error {
+76
pkg/videostream/generator.go
··· 1 1 package videostream 2 + 3 + import ( 4 + "context" 5 + "database/sql" 6 + "log" 7 + "strconv" 8 + 9 + appbsky "github.com/bluesky-social/indigo/api/bsky" 10 + "github.com/edavis/bsky-feeds/pkg/feeds" 11 + _ "github.com/mattn/go-sqlite3" 12 + ) 13 + 14 + type PostRow struct { 15 + Uri string 16 + } 17 + 18 + func getPosts(ctx context.Context, dbCnx *sql.DB, limit, offset int) ([]PostRow, error) { 19 + rows, err := dbCnx.QueryContext(ctx, `select uri from posts where create_ts < unixepoch('now', '-2 minutes') order by create_ts desc limit ? offset ?`, limit, offset) 20 + if err != nil { 21 + return nil, err 22 + } 23 + defer rows.Close() 24 + 25 + var posts []PostRow 26 + for rows.Next() { 27 + var post PostRow 28 + if err := rows.Scan(&post.Uri); err != nil { 29 + return nil, err 30 + } 31 + posts = append(posts, post) 32 + } 33 + return posts, nil 34 + } 35 + 36 + func Feed(params feeds.FeedgenParams) appbsky.FeedGetFeedSkeleton_Output { 37 + ctx := context.Background() 38 + dbCnx, err := sql.Open("sqlite3", "data/videostream.db?_journal=WAL&_fk=on") 39 + if err != nil { 40 + log.Printf("error opening db: %v\n", err) 41 + } 42 + defer dbCnx.Close() 43 + 44 + offset := 0 45 + if params.Cursor != "" { 46 + if parsed, err := strconv.Atoi(params.Cursor); err == nil { 47 + offset = parsed 48 + } else { 49 + log.Printf("error converting cursor: %v\n", err) 50 + } 51 + } 52 + 53 + rows, err := getPosts(ctx, dbCnx, params.Limit, offset) 54 + if err != nil { 55 + log.Printf("error fetching rows: %v\n", err) 56 + } 57 + 58 + var cursor string 59 + posts := make([]*appbsky.FeedDefs_SkeletonFeedPost, 0, params.Limit) 60 + 61 + for _, row := range rows { 62 + posts = append(posts, &appbsky.FeedDefs_SkeletonFeedPost{Post: row.Uri}) 63 + } 64 + 65 + skeleton := appbsky.FeedGetFeedSkeleton_Output{ 66 + Feed: posts, 67 + } 68 + 69 + offset += len(posts) 70 + cursor = strconv.Itoa(offset) 71 + 72 + if len(posts) == params.Limit { 73 + skeleton.Cursor = &cursor 74 + } 75 + 76 + return skeleton 77 + }