fix: do not use service worker for avatar
All checks were successful
Docs / build (push) Successful in 2m27s
All checks were successful
Docs / build (push) Successful in 2m27s
This commit is contained in:
parent
e3bbb0c061
commit
a3daff891f
3 changed files with 36 additions and 77 deletions
|
@ -1,55 +0,0 @@
|
||||||
import type { BaseTelegramClient } from '@mtcute/web'
|
|
||||||
import { downloadAsBuffer, getMe } from '@mtcute/web/methods.js'
|
|
||||||
import { createInternalClient } from '../utils/telegram.ts'
|
|
||||||
import { timeout } from '../utils/timeout.ts'
|
|
||||||
import { getCacheStorage } from './cache.ts'
|
|
||||||
|
|
||||||
const clients = new Map<string, BaseTelegramClient>()
|
|
||||||
|
|
||||||
export async function clearAvatarCache(accountId: string) {
|
|
||||||
const cacheKey = new URL(`/sw/avatar/${accountId}`, location.origin)
|
|
||||||
await (await getCacheStorage()).delete(cacheKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function handleAvatarRequest(accountId: string) {
|
|
||||||
const cacheKey = new URL(`/sw/avatar/${accountId}`, location.origin)
|
|
||||||
|
|
||||||
const cache = await getCacheStorage()
|
|
||||||
try {
|
|
||||||
const cachedRes = await timeout(cache.match(cacheKey), 10000)
|
|
||||||
if (cachedRes) {
|
|
||||||
return cachedRes
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
let client = clients.get(accountId)
|
|
||||||
if (!client) {
|
|
||||||
client = createInternalClient(accountId)
|
|
||||||
await client.prepare()
|
|
||||||
clients.set(accountId, client)
|
|
||||||
}
|
|
||||||
|
|
||||||
const self = await getMe(client)
|
|
||||||
|
|
||||||
if (!self.photo) {
|
|
||||||
const res = new Response('No photo', { status: 404 })
|
|
||||||
await client.close()
|
|
||||||
await cache.put(cacheKey, res.clone())
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
const buf = await downloadAsBuffer(client, self.photo.big)
|
|
||||||
await client.close()
|
|
||||||
|
|
||||||
const res = new Response(buf, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'image/jpeg',
|
|
||||||
'Cache-Control': 'public, max-age=86400',
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
await cache.put(cacheKey, res.clone())
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { unknownToError } from '@fuman/utils'
|
import { unknownToError } from '@fuman/utils'
|
||||||
import { IS_SAFARI } from '../utils/env.ts'
|
import { IS_SAFARI } from '../utils/env.ts'
|
||||||
import { clearAvatarCache, handleAvatarRequest } from './avatar.ts'
|
|
||||||
import { requestCache } from './cache.ts'
|
import { requestCache } from './cache.ts'
|
||||||
import { type DownloadFileParams, handleDownload, handlePort } from './download/handler.ts'
|
import { type DownloadFileParams, handleDownload, handlePort } from './download/handler.ts'
|
||||||
import { clearCache, handleRuntimeRequest } from './runtime.ts'
|
import { clearCache, handleRuntimeRequest } from './runtime.ts'
|
||||||
|
@ -9,11 +8,6 @@ import { forgetAllScripts, forgetScript, uploadScript } from './scripts.ts'
|
||||||
declare const self: ServiceWorkerGlobalScope
|
declare const self: ServiceWorkerGlobalScope
|
||||||
|
|
||||||
async function handleSwRequest(_req: Request, url: URL): Promise<Response> {
|
async function handleSwRequest(_req: Request, url: URL): Promise<Response> {
|
||||||
if (url.pathname.startsWith('/sw/avatar/')) {
|
|
||||||
const accountId = url.pathname.split('/')[3]
|
|
||||||
return handleAvatarRequest(accountId)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.pathname.startsWith('/sw/runtime/')) {
|
if (url.pathname.startsWith('/sw/runtime/')) {
|
||||||
return handleRuntimeRequest(url)
|
return handleRuntimeRequest(url)
|
||||||
}
|
}
|
||||||
|
@ -62,7 +56,6 @@ self.onoffline = self.ononline = () => {
|
||||||
export type SwMessage =
|
export type SwMessage =
|
||||||
| { event: 'UPLOAD_SCRIPT', name: string, files: Record<string, string> }
|
| { event: 'UPLOAD_SCRIPT', name: string, files: Record<string, string> }
|
||||||
| { event: 'FORGET_SCRIPT', name: string }
|
| { event: 'FORGET_SCRIPT', name: string }
|
||||||
| { event: 'CLEAR_AVATAR_CACHE', accountId: string }
|
|
||||||
| { event: 'CLEAR_CACHE' }
|
| { event: 'CLEAR_CACHE' }
|
||||||
| { event: 'DOWNLOAD_FILE', id: string, params: DownloadFileParams, port: MessagePort }
|
| { event: 'DOWNLOAD_FILE', id: string, params: DownloadFileParams, port: MessagePort }
|
||||||
|
|
||||||
|
@ -81,10 +74,6 @@ async function handleMessage(msg: SwMessage) {
|
||||||
await forgetAllScripts()
|
await forgetAllScripts()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'CLEAR_AVATAR_CACHE': {
|
|
||||||
clearAvatarCache(msg.accountId)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,11 @@ import type { CustomApiFields, TelegramAccount } from '../store/accounts.ts'
|
||||||
import { assert, hex } from '@fuman/utils'
|
import { assert, hex } from '@fuman/utils'
|
||||||
import { DC_MAPPING_PROD, DC_MAPPING_TEST } from '@mtcute/convert'
|
import { DC_MAPPING_PROD, DC_MAPPING_TEST } from '@mtcute/convert'
|
||||||
import { tl } from '@mtcute/web'
|
import { tl } from '@mtcute/web'
|
||||||
import { checkPassword, getMe, resendCode, sendCode, signIn, signInBot, signInQr } from '@mtcute/web/methods.js'
|
import { checkPassword, downloadAsBuffer, getMe, resendCode, sendCode, signIn, signInBot, signInQr } from '@mtcute/web/methods.js'
|
||||||
import { readStringSession } from '@mtcute/web/utils.js'
|
import { readStringSession } from '@mtcute/web/utils.js'
|
||||||
import { nanoid } from 'nanoid'
|
import { nanoid } from 'nanoid'
|
||||||
import { renderSVG } from 'uqr'
|
import { renderSVG } from 'uqr'
|
||||||
import { $accounts, $activeAccountId } from '../store/accounts.ts'
|
import { $accounts, $activeAccountId } from '../store/accounts.ts'
|
||||||
import { swInvokeMethod } from '../sw/client.ts'
|
|
||||||
import { waitForServiceWorkerInit } from '../sw/register.ts'
|
|
||||||
import { createInternalClient, deleteAccount, importAccount } from '../utils/telegram.ts'
|
import { createInternalClient, deleteAccount, importAccount } from '../utils/telegram.ts'
|
||||||
import { emitEvent } from './utils.ts'
|
import { emitEvent } from './utils.ts'
|
||||||
|
|
||||||
|
@ -40,6 +38,8 @@ function getTmpClient(accountId: string): [BaseTelegramClient, () => Promise<voi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let avatarCache: Cache | undefined
|
||||||
|
|
||||||
async function handleAuthSuccess(accountId: string, user: User) {
|
async function handleAuthSuccess(accountId: string, user: User) {
|
||||||
const client = getClient(accountId)
|
const client = getClient(accountId)
|
||||||
const dcs = await client.mt.storage.dcs.fetch()
|
const dcs = await client.mt.storage.dcs.fetch()
|
||||||
|
@ -221,13 +221,34 @@ export class ReplWorkerTelegram {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchAvatar(accountId: string) {
|
async fetchAvatar(accountId: string) {
|
||||||
await waitForServiceWorkerInit()
|
if (!avatarCache) {
|
||||||
const res = await fetch(`/sw/avatar/${accountId}/avatar.jpg`)
|
avatarCache = await caches.open('mtcute-repl-avatars')
|
||||||
if (!res.ok) {
|
|
||||||
return null
|
|
||||||
} else {
|
|
||||||
return new Uint8Array(await res.arrayBuffer())
|
|
||||||
}
|
}
|
||||||
|
const req = new Request(`/${accountId}.jpg`)
|
||||||
|
const cached = await avatarCache.match(req)
|
||||||
|
|
||||||
|
if (cached) {
|
||||||
|
if (!cached.ok) return null
|
||||||
|
return new Uint8Array(await cached.arrayBuffer())
|
||||||
|
}
|
||||||
|
|
||||||
|
const [client, cleanup] = getTmpClient(accountId)
|
||||||
|
const self = await getMe(client)
|
||||||
|
|
||||||
|
let response: Response
|
||||||
|
let result: Uint8Array | null = null
|
||||||
|
if (!self.photo) {
|
||||||
|
response = new Response('No photo', { status: 404 })
|
||||||
|
result = null
|
||||||
|
} else {
|
||||||
|
const buf = await downloadAsBuffer(client, self.photo.big)
|
||||||
|
response = new Response(buf)
|
||||||
|
result = buf
|
||||||
|
}
|
||||||
|
|
||||||
|
await cleanup()
|
||||||
|
await avatarCache.put(req, response)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async importAuthKey(params: {
|
async importAuthKey(params: {
|
||||||
|
@ -400,12 +421,16 @@ export class ReplWorkerTelegram {
|
||||||
}) {
|
}) {
|
||||||
const { accountId } = params
|
const { accountId } = params
|
||||||
|
|
||||||
|
if (!avatarCache) {
|
||||||
|
avatarCache = await caches.open('mtcute-repl-avatars')
|
||||||
|
}
|
||||||
|
|
||||||
|
await avatarCache.delete(new Request(`/${accountId}.jpg`))
|
||||||
|
|
||||||
const [client, cleanup] = getTmpClient(accountId)
|
const [client, cleanup] = getTmpClient(accountId)
|
||||||
const self = await getMe(client)
|
const self = await getMe(client)
|
||||||
await cleanup()
|
await cleanup()
|
||||||
|
|
||||||
await swInvokeMethod({ event: 'CLEAR_AVATAR_CACHE', accountId })
|
|
||||||
|
|
||||||
$accounts.set($accounts.get().map((it) => {
|
$accounts.set($accounts.get().map((it) => {
|
||||||
if (it.id === accountId) {
|
if (it.id === accountId) {
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue