[READ ONLY MIRROR] Spark Social AppView Server github.com/sprksocial/server
atproto deno hono lexicon
5
fork

Configure Feed

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

at main 105 lines 2.8 kB view raw
1import { Database } from "../db/index.ts"; 2import { TimeCidKeyset } from "../db/pagination.ts"; 3 4export class Reposts { 5 private db: Database; 6 private timeCidKeyset: TimeCidKeyset; 7 8 constructor(db: Database) { 9 this.db = db; 10 this.timeCidKeyset = new TimeCidKeyset(); 11 } 12 13 async bySubject( 14 subject?: { uri: string; cid?: string }, 15 limit = 50, 16 cursor?: string, 17 ) { 18 if (!subject?.uri) { 19 return { uris: [], cursor: undefined }; 20 } 21 22 // Build query for reposts of this subject 23 const repostsQuery = this.db.models.Repost.find({ 24 subject: subject.uri, 25 }); 26 27 // Apply pagination using TimeCidKeyset 28 const paginatedQuery = this.timeCidKeyset.paginate(repostsQuery, { 29 limit, 30 cursor, 31 direction: "desc", 32 }); 33 34 const reposts = await paginatedQuery.exec(); 35 36 // Generate cursor from the last item if we have a full page 37 let nextCursor: string | undefined; 38 if (reposts.length === limit && reposts.length > 0) { 39 const lastRepost = reposts[reposts.length - 1]; 40 nextCursor = this.timeCidKeyset.pack({ 41 primary: lastRepost.indexedAt, 42 secondary: lastRepost.cid, 43 }); 44 } 45 46 return { 47 uris: reposts.map((r) => r.uri), 48 cursor: nextCursor, 49 }; 50 } 51 52 async byActorAndSubjects( 53 actorDid: string, 54 refs: Array<{ uri: string; cid?: string }>, 55 ) { 56 if (refs.length === 0) { 57 return { uris: [] }; 58 } 59 60 // Get all reposts by this actor for the specified subjects 61 const subjectUris = refs.map(({ uri }) => uri); 62 const reposts = await this.db.models.Repost.find({ 63 authorDid: actorDid, 64 subject: { $in: subjectUris }, 65 }); 66 67 // Create a map for quick lookup 68 const repostMap = new Map(reposts.map((r) => [r.subject, r.uri])); 69 const uris = refs.map(({ uri }) => repostMap.get(uri) || ""); 70 71 return { uris }; 72 } 73 74 async getActor(actorDid: string, limit = 50, cursor?: string) { 75 // Build query for reposts by this actor 76 const repostsQuery = this.db.models.Repost.find({ authorDid: actorDid }); 77 78 // Apply pagination using TimeCidKeyset 79 const paginatedQuery = this.timeCidKeyset.paginate(repostsQuery, { 80 limit, 81 cursor, 82 direction: "desc", 83 }); 84 85 const reposts = await paginatedQuery.exec(); 86 87 // Generate cursor from the last item if we have a full page 88 let nextCursor: string | undefined; 89 if (reposts.length === limit && reposts.length > 0) { 90 const lastRepost = reposts[reposts.length - 1]; 91 nextCursor = this.timeCidKeyset.pack({ 92 primary: lastRepost.indexedAt, 93 secondary: lastRepost.cid, 94 }); 95 } 96 97 return { 98 reposts: reposts.map((r) => ({ 99 uri: r.uri, 100 subject: r.subject, 101 })), 102 cursor: nextCursor, 103 }; 104 } 105}