@@ -52,30 +52,50 @@ export function getRedirectURI(origin: string, server: string) {
5252export const defaultUserAgent = `${ APP_NAME } /${ version } `
5353
5454async function fetchAppInfo ( origin : string , server : string ) {
55- const app : AppInfo = await $fetch ( `https://${ server } /api/v1/apps` , {
56- method : 'POST' ,
57- headers : {
58- 'user-agent' : defaultUserAgent ,
59- } ,
60- body : {
61- client_name : APP_NAME + ( env !== 'release' ? ` (${ env } )` : '' ) ,
62- website : 'https://elk.zone' ,
63- redirect_uris : getRedirectURI ( origin , server ) ,
64- scopes : 'read write follow push' ,
65- } ,
66- } )
55+ const [ apps , v2Instance ] = await Promise . all ( [
56+ $fetch ( `https://${ server } /api/v1/apps` , {
57+ method : 'POST' ,
58+ headers : {
59+ 'user-agent' : defaultUserAgent ,
60+ } ,
61+ body : {
62+ client_name : APP_NAME + ( env !== 'release' ? ` (${ env } )` : '' ) ,
63+ website : 'https://elk.zone' ,
64+ redirect_uris : getRedirectURI ( origin , server ) ,
65+ scopes : 'read write follow push' ,
66+ } ,
67+ } ) ,
68+ $fetch ( `https://${ server } /api/v2/instance` , {
69+ headers : {
70+ 'user-agent' : defaultUserAgent ,
71+ } ,
72+ } )
73+ . catch ( ( ) => null ) ,
74+ ] )
75+
76+ const app : AppInfo = {
77+ ...apps ,
78+ // prefer vapid key from `/api/v2/instance` if available
79+ // since `vapid_key` from `/api/v1/apps` was deprecated on Mastodon v4.3.0+
80+ // ref. apps API methods - Mastodon documentation
81+ // - https://docs.joinmastodon.org/methods/apps/#create
82+ ...v2Instance ? { vapid_key : v2Instance . configuration . vapid . public_key } : { } ,
83+ }
84+
6785 return app
6886}
6987
7088export async function getApp ( origin : string , server : string ) {
7189 const host = origin . replace ( / ^ h t t p s ? : \/ \/ / , '' ) . replace ( / \W / g, '-' ) . replace ( / \? .* $ / , '' )
72- const key = `servers:v3 :${ server } :${ host } .json` . toLowerCase ( )
90+ const key = `servers:v4 :${ server } :${ host } .json` . toLowerCase ( )
7391
7492 try {
7593 if ( await storage . hasItem ( key ) )
7694 return ( storage . getItem ( key , { } ) as Promise < AppInfo > )
7795 const appInfo = await fetchAppInfo ( origin , server )
78- await storage . setItem ( key , appInfo )
96+ // cache `appInfo` for 1 week to prevent permanent lockout
97+ // note that `unstorage` supports `ttl` only for some storage drivers like cloudflare
98+ await storage . setItem ( key , appInfo , { ttl : 60 * 60 * 24 * 7 /* 1 week */ } )
7999 return appInfo
80100 }
81101 catch {
@@ -84,13 +104,13 @@ export async function getApp(origin: string, server: string) {
84104}
85105
86106export async function deleteApp ( server : string ) {
87- const keys = ( await storage . getKeys ( `servers:v3 :${ server } :` ) )
107+ const keys = ( await storage . getKeys ( `servers:v4 :${ server } :` ) )
88108 for ( const key of keys )
89109 await storage . removeItem ( key )
90110}
91111
92112export async function listServers ( ) {
93- const keys = await storage . getKeys ( 'servers:v3 :' )
113+ const keys = await storage . getKeys ( 'servers:v4 :' )
94114 const servers = new Set < string > ( )
95115 for ( const key of keys ) {
96116 const id = key . split ( ':' ) [ 2 ]
0 commit comments