Thread viewer for Bluesky
1import { Post } from '../models/posts.js';
2import * as paginator from '../utils/paginator.js';
3import { BlueskyAPI, accountAPI } from '../api.js';
4
5export type OnPostsLoaded = (data: { posts: Post[], terms: string[] }) => void
6export type OnFinish = () => void
7
8const DEFAULT_LYCAN = "did:web:lycan.feeds.blue#lycan";
9
10export class Lycan {
11 lycanAddress: string;
12
13 constructor(address?: string) {
14 this.lycanAddress = address ?? DEFAULT_LYCAN;
15 }
16
17 get proxyHeaders() {
18 return { 'atproto-proxy': this.lycanAddress };
19 }
20
21 async getImportStatus() {
22 return await accountAPI.getRequest('blue.feeds.lycan.getImportStatus', null, { headers: this.proxyHeaders });
23 }
24
25 async startImport() {
26 await accountAPI.postRequest('blue.feeds.lycan.startImport', null, { headers: this.proxyHeaders });
27 }
28
29 async makeQuery(collection: string, query: string, cursor: string | undefined) {
30 let params: Record<string, string> = { collection, query };
31 if (cursor) params.cursor = cursor;
32
33 return await accountAPI.getRequest('blue.feeds.lycan.searchPosts', params, { headers: this.proxyHeaders });
34 }
35
36 searchPosts(collection: string, query: string, callbacks: { onPostsLoaded: OnPostsLoaded, onFinish: OnFinish }) {
37 let isLoading = false;
38 let finished = false;
39 let cursor: string | undefined;
40
41 paginator.loadInPages(async () => {
42 if (isLoading || finished) { return; }
43 isLoading = true;
44
45 let response = await this.makeQuery(collection, query, cursor);
46 let records = await accountAPI.loadPosts(response.posts);
47 let posts = records.map(x => new Post(x));
48
49 isLoading = false;
50
51 callbacks.onPostsLoaded({ posts: posts, terms: response.terms });
52
53 cursor = response.cursor;
54
55 if (!cursor) {
56 finished = true;
57 callbacks.onFinish?.()
58 }
59 });
60 }
61}
62
63export class DevLycan extends Lycan {
64 localLycan: BlueskyAPI;
65
66 constructor(host: string) {
67 super();
68 this.localLycan = new BlueskyAPI(host);
69 }
70
71 override async getImportStatus() {
72 return await this.localLycan.getRequest('blue.feeds.lycan.getImportStatus', { user: accountAPI.user.did });
73 }
74
75 override async startImport() {
76 await this.localLycan.postRequest('blue.feeds.lycan.startImport', { user: accountAPI.user.did });
77 }
78
79 override async makeQuery(collection: string, query: string, cursor: string | undefined) {
80 let params: Record<string, string> = { collection, query, user: accountAPI.user.did };
81 if (cursor) params.cursor = cursor;
82
83 return await this.localLycan.getRequest('blue.feeds.lycan.searchPosts', params);
84 }
85}