feat: create atproto oauth login
This commit is contained in:
30
src/modules/atproto/service/atprotoOAuth.ts
Normal file
30
src/modules/atproto/service/atprotoOAuth.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { BrowserOAuthClient } from '@atproto/oauth-client-browser'
|
||||
|
||||
const CLIENT_ID = import.meta.env.DEV
|
||||
? 'http://localhost'
|
||||
: 'https://remanso.space/client-metadata.json'
|
||||
|
||||
let clientPromise: Promise<BrowserOAuthClient> | null = null
|
||||
|
||||
export const getOAuthClient = (): Promise<BrowserOAuthClient> => {
|
||||
if (!clientPromise) {
|
||||
clientPromise = BrowserOAuthClient.load({ clientId: CLIENT_ID })
|
||||
}
|
||||
return clientPromise
|
||||
}
|
||||
|
||||
export const signInWithHandle = async (handle: string): Promise<void> => {
|
||||
const client = await getOAuthClient()
|
||||
await client.signInRedirect(handle, { scope: 'atproto transition:generic' })
|
||||
}
|
||||
|
||||
export const restoreSession = async () => {
|
||||
const client = await getOAuthClient()
|
||||
const result = await client.init()
|
||||
return result?.session ?? null
|
||||
}
|
||||
|
||||
export const sdkSignOut = async (sub: string): Promise<void> => {
|
||||
const client = await getOAuthClient()
|
||||
await client.revoke(sub)
|
||||
}
|
||||
23
src/modules/atproto/service/atprotoSession.ts
Normal file
23
src/modules/atproto/service/atprotoSession.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { data } from '@/data/data'
|
||||
import { DataType } from '@/data/DataType.enum'
|
||||
import { AtprotoSession } from '@/data/models/AtprotoSession'
|
||||
|
||||
const SESSION_ID = `${DataType.AtprotoSession}-current`
|
||||
|
||||
export const loadSession = (): Promise<AtprotoSession | null> => {
|
||||
return data.get<DataType.AtprotoSession, AtprotoSession>(SESSION_ID)
|
||||
}
|
||||
|
||||
export const saveSession = async (did: string, handle: string): Promise<void> => {
|
||||
const session: AtprotoSession = {
|
||||
_id: SESSION_ID,
|
||||
$type: DataType.AtprotoSession,
|
||||
did,
|
||||
handle,
|
||||
}
|
||||
await data.update<DataType.AtprotoSession, AtprotoSession>(session)
|
||||
}
|
||||
|
||||
export const clearSession = (): Promise<boolean> => {
|
||||
return data.remove(SESSION_ID)
|
||||
}
|
||||
24
src/modules/atproto/service/getFollows.ts
Normal file
24
src/modules/atproto/service/getFollows.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export const getFollows = async (did: string): Promise<Set<string>> => {
|
||||
const follows = new Set<string>()
|
||||
let cursor: string | undefined
|
||||
|
||||
do {
|
||||
const url = new URL('https://public.api.bsky.app/xrpc/app.bsky.graph.getFollows')
|
||||
url.searchParams.set('actor', did)
|
||||
url.searchParams.set('limit', '100')
|
||||
if (cursor) {
|
||||
url.searchParams.set('cursor', cursor)
|
||||
}
|
||||
|
||||
const response = await fetch(url)
|
||||
const result: { follows: { did: string }[]; cursor?: string } = await response.json()
|
||||
|
||||
for (const follow of result.follows) {
|
||||
follows.add(follow.did)
|
||||
}
|
||||
|
||||
cursor = result.cursor
|
||||
} while (cursor)
|
||||
|
||||
return follows
|
||||
}
|
||||
Reference in New Issue
Block a user