forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import AtpAgent from '@atproto/api'
2import {jwtDecode} from 'jwt-decode'
3
4import {isJwtExpired} from '#/lib/jwt'
5import {hasProp} from '#/lib/type-guards'
6import * as persisted from '#/state/persisted'
7import {sessionAccountToSession} from './agent'
8import {type SessionAccount} from './types'
9
10export function readLastActiveAccount() {
11 const {currentAccount, accounts} = persisted.get('session')
12 return accounts.find(a => a.did === currentAccount?.did)
13}
14
15export function isSignupQueued(accessJwt: string | undefined) {
16 if (accessJwt) {
17 try {
18 const sessData = jwtDecode(accessJwt)
19 return (
20 hasProp(sessData, 'scope') &&
21 sessData.scope === 'com.atproto.signupQueued'
22 )
23 } catch {
24 return false
25 }
26 }
27 return false
28}
29
30export function canAttemptSessionResume(account: SessionAccount) {
31 return !!(account.isOauthSession || account.refreshJwt || account.accessJwt)
32}
33
34export function isSessionExpired(account: SessionAccount) {
35 if (account.accessJwt) {
36 return isJwtExpired(account.accessJwt)
37 } else {
38 return true
39 }
40}
41
42/**
43 * Creates and attempted to resumeSession for every stored session.
44 * Intended to be used to send push token revokations just before logout.
45 */
46export async function createTemporaryAgentsAndResume(
47 accounts: SessionAccount[],
48) {
49 const agents = await Promise.allSettled(
50 accounts.map(async account => {
51 const agent: AtpAgent = new AtpAgent({service: account.service})
52 if (account.pdsUrl) {
53 agent.sessionManager.pdsUrl = new URL(account.pdsUrl)
54 }
55
56 const session = sessionAccountToSession(account)
57 const res = await agent.resumeSession(session)
58 if (!res.success) throw new Error('Failed to resume session')
59
60 agent.assertAuthenticated() // confirm auth success
61
62 return agent
63 }),
64 )
65
66 return agents
67 .filter(x => x.status === 'fulfilled')
68 .map(promise => promise.value)
69}