From 55d519713645b928ed98c2cd023ff9281c32ef95 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 11 Sep 2023 17:26:47 -0500 Subject: [PATCH 1/3] timelines: 3 seconds --> 1 second --- src/controllers/api/timelines.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/api/timelines.ts b/src/controllers/api/timelines.ts index a97b747..4b1825f 100644 --- a/src/controllers/api/timelines.ts +++ b/src/controllers/api/timelines.ts @@ -34,7 +34,7 @@ const hashtagTimelineController: AppController = (c) => { /** Render statuses for timelines. */ async function renderStatuses(c: AppContext, filters: DittoFilter<1>[]) { - const events = await mixer.getFilters(filters, { timeout: Time.seconds(3) }); + const events = await mixer.getFilters(filters, { timeout: Time.seconds(1) }); if (!events.length) { return c.json([]); From d2760bc706b9b4d3eda1c518f362a3e64b8ea281 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 11 Sep 2023 17:49:38 -0500 Subject: [PATCH 2/3] media: refactor upload code into a separate module --- src/controllers/api/media.ts | 28 ++++------------------------ src/upload.ts | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 src/upload.ts diff --git a/src/controllers/api/media.ts b/src/controllers/api/media.ts index 1e310e1..a7edef1 100644 --- a/src/controllers/api/media.ts +++ b/src/controllers/api/media.ts @@ -1,19 +1,13 @@ import { AppController } from '@/app.ts'; -import { Conf } from '@/config.ts'; -import { insertUnattachedMedia } from '@/db/unattached-media.ts'; import { z } from '@/deps.ts'; import { fileSchema } from '@/schema.ts'; -import { configUploader as uploader } from '@/uploaders/config.ts'; import { parseBody } from '@/utils/web.ts'; import { renderAttachment } from '@/views/attachment.ts'; - -const uploadSchema = fileSchema - .refine((file) => !!file.type, 'File type is required.') - .refine((file) => file.size <= Conf.maxUploadSize, 'File size is too large.'); +import { uploadFile } from '@/upload.ts'; const mediaBodySchema = z.object({ - file: uploadSchema, - thumbnail: uploadSchema.optional(), + file: fileSchema, + thumbnail: fileSchema.optional(), description: z.string().optional(), focus: z.string().optional(), }); @@ -27,21 +21,7 @@ const mediaController: AppController = async (c) => { try { const { file, description } = result.data; - const { cid } = await uploader.upload(file); - - const url = new URL(`/ipfs/${cid}`, Conf.mediaDomain).toString(); - - const media = await insertUnattachedMedia({ - pubkey: c.get('pubkey')!, - url, - data: { - name: file.name, - mime: file.type, - size: file.size, - description, - }, - }); - + const media = await uploadFile(file, { pubkey: c.get('pubkey')!, description }); return c.json(renderAttachment(media)); } catch (e) { console.error(e); diff --git a/src/upload.ts b/src/upload.ts new file mode 100644 index 0000000..d8ea969 --- /dev/null +++ b/src/upload.ts @@ -0,0 +1,34 @@ +import { Conf } from '@/config.ts'; +import { insertUnattachedMedia } from '@/db/unattached-media.ts'; +import { configUploader as uploader } from '@/uploaders/config.ts'; + +interface FileMeta { + pubkey: string; + description?: string; +} + +/** Upload a file, track it in the database, and return the resulting media object. */ +async function uploadFile(file: File, meta: FileMeta) { + const { name, type, size } = file; + const { pubkey, description } = meta; + + if (file.size > Conf.maxUploadSize) { + throw new Error('File size is too large.'); + } + + const { cid } = await uploader.upload(file); + const url = new URL(`/ipfs/${cid}`, Conf.mediaDomain).toString(); + + return insertUnattachedMedia({ + pubkey, + url, + data: { + name, + size, + description, + mime: type, + }, + }); +} + +export { uploadFile }; From 93d8e0b22bdf877bf3c7beee8344b73cbe006df8 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 11 Sep 2023 18:02:17 -0500 Subject: [PATCH 3/3] accounts: support updating avatar and banner --- src/controllers/api/accounts.ts | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/controllers/api/accounts.ts b/src/controllers/api/accounts.ts index 211eb77..695c707 100644 --- a/src/controllers/api/accounts.ts +++ b/src/controllers/api/accounts.ts @@ -11,6 +11,7 @@ import { paginated, paginationSchema, parseBody } from '@/utils/web.ts'; import { createEvent } from '@/utils/web.ts'; import { renderEventAccounts } from '@/views.ts'; import { insertUser } from '@/db/users.ts'; +import { uploadFile } from '@/upload.ts'; const usernameSchema = z .string().min(1).max(30) @@ -171,13 +172,24 @@ const updateCredentialsController: AppController = async (c) => { } const author = await getAuthor(pubkey); - if (!author) { - return c.json({ error: 'Could not find user.' }, 404); - } + const meta = author ? jsonMetaContentSchema.parse(author.content) : {}; - const meta = jsonMetaContentSchema.parse(author.content); - meta.name = result.data.display_name ?? meta.name; - meta.about = result.data.note ?? meta.about; + const { + avatar: avatarFile, + header: headerFile, + display_name, + note, + } = result.data; + + const [avatar, header] = await Promise.all([ + avatarFile ? uploadFile(avatarFile, { pubkey }) : undefined, + headerFile ? uploadFile(headerFile, { pubkey }) : undefined, + ]); + + meta.name = display_name ?? meta.name; + meta.about = note ?? meta.about; + meta.picture = avatar?.url ?? meta.picture; + meta.banner = header?.url ?? meta.banner; const event = await createEvent({ kind: 0,