mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1/**
2 * This is a temporary off-spec search endpoint
3 * TODO removeme when we land this in proto!
4 */
5import {AppBskyFeedPost} from '@atproto/api'
6
7const PROFILES_ENDPOINT = 'https://search.bsky.social/search/profiles'
8const POSTS_ENDPOINT = 'https://search.bsky.social/search/posts'
9
10export interface ProfileSearchItem {
11 $type: string
12 avatar: {
13 cid: string
14 mimeType: string
15 }
16 banner: {
17 cid: string
18 mimeType: string
19 }
20 description: string | undefined
21 displayName: string | undefined
22 did: string
23}
24
25export interface PostSearchItem {
26 tid: string
27 cid: string
28 user: {
29 did: string
30 handle: string
31 }
32 post: AppBskyFeedPost.Record
33}
34
35export async function searchProfiles(
36 query: string,
37): Promise<ProfileSearchItem[]> {
38 return await doFetch<ProfileSearchItem[]>(PROFILES_ENDPOINT, query)
39}
40
41export async function searchPosts(query: string): Promise<PostSearchItem[]> {
42 return await doFetch<PostSearchItem[]>(POSTS_ENDPOINT, query)
43}
44
45async function doFetch<T>(endpoint: string, query: string): Promise<T> {
46 const controller = new AbortController()
47 const to = setTimeout(() => controller.abort(), 15e3)
48
49 const uri = new URL(endpoint)
50 uri.searchParams.set('q', query)
51
52 const res = await fetch(String(uri), {
53 method: 'get',
54 headers: {
55 accept: 'application/json',
56 },
57 signal: controller.signal,
58 })
59
60 const resHeaders: Record<string, string> = {}
61 res.headers.forEach((value: string, key: string) => {
62 resHeaders[key] = value
63 })
64 let resBody = await res.json()
65
66 clearTimeout(to)
67
68 return resBody as unknown as T
69}