diff --git a/src/controllers/api/media.ts b/src/controllers/api/media.ts index 955cd75..9988428 100644 --- a/src/controllers/api/media.ts +++ b/src/controllers/api/media.ts @@ -30,8 +30,8 @@ const mediaController: AppController = async (c) => { const url = new URL(`/ipfs/${cid}`, Conf.mediaDomain).toString(); - await insertUnattachedMedia({ - pukey: c.get('pubkey')!, + const media = await insertUnattachedMedia({ + pubkey: c.get('pubkey')!, url, data: { name: file.name, @@ -42,7 +42,7 @@ const mediaController: AppController = async (c) => { }); return c.json({ - id: cid, + id: media.id, type: getAttachmentType(file.type), url, preview_url: url, diff --git a/src/controllers/api/statuses.ts b/src/controllers/api/statuses.ts index 0ae754e..4756df0 100644 --- a/src/controllers/api/statuses.ts +++ b/src/controllers/api/statuses.ts @@ -1,10 +1,10 @@ import { type AppController } from '@/app.ts'; -import { Conf } from '@/config.ts'; import { type Event, ISO6391, z } from '@/deps.ts'; import { getAncestors, getDescendants, getEvent } from '@/queries.ts'; import { toStatus } from '@/transformers/nostr-to-mastoapi.ts'; import { createEvent, paginationSchema, parseBody } from '@/utils/web.ts'; import { renderEventAccounts } from '@/views.ts'; +import { getUnattachedMediaByIds } from '@/db/unattached-media.ts'; const createStatusSchema = z.object({ in_reply_to_id: z.string().regex(/[0-9a-f]{64}/).nullish(), @@ -69,9 +69,12 @@ const createStatusController: AppController = async (c) => { tags.push(['subject', data.spoiler_text]); } - for (const cid of data.media_ids ?? []) { - const url = new URL(`/ipfs/${cid}`, Conf.mediaDomain).toString(); - tags.push(['media', url]); + if (data.media_ids?.length) { + const media = await getUnattachedMediaByIds(data.media_ids) + .then((media) => media.filter(({ pubkey }) => pubkey === c.get('pubkey'))) + .then((media) => media.map(({ url, data }) => ['media', url, data])); + + tags.push(...media); } const event = await createEvent({ diff --git a/src/db.ts b/src/db.ts index cbf4bb1..abbe982 100644 --- a/src/db.ts +++ b/src/db.ts @@ -49,7 +49,7 @@ interface RelayRow { interface UnattachedMediaRow { id: string; - pukey: string; + pubkey: string; url: string; data: string; uploaded_at: Date; diff --git a/src/db/migrations/007_unattached_media.ts b/src/db/migrations/007_unattached_media.ts index 971c5db..a2b36a2 100644 --- a/src/db/migrations/007_unattached_media.ts +++ b/src/db/migrations/007_unattached_media.ts @@ -4,7 +4,7 @@ export async function up(db: Kysely): Promise { await db.schema .createTable('unattached_media') .addColumn('id', 'text', (c) => c.primaryKey()) - .addColumn('pukey', 'text', (c) => c.notNull()) + .addColumn('pubkey', 'text', (c) => c.notNull()) .addColumn('url', 'text', (c) => c.notNull()) .addColumn('data', 'text', (c) => c.notNull()) .addColumn('uploaded_at', 'datetime', (c) => c.notNull().defaultTo(sql`CURRENT_TIMESTAMP`)) @@ -17,9 +17,9 @@ export async function up(db: Kysely): Promise { .execute(); await db.schema - .createIndex('unattached_media_pukey') + .createIndex('unattached_media_pubkey') .on('unattached_media') - .column('pukey') + .column('pubkey') .execute(); await db.schema diff --git a/src/db/unattached-media.ts b/src/db/unattached-media.ts index 409b365..f58931b 100644 --- a/src/db/unattached-media.ts +++ b/src/db/unattached-media.ts @@ -3,7 +3,7 @@ import { uuid62 } from '@/deps.ts'; interface UnattachedMedia { id: string; - pukey: string; + pubkey: string; url: string; data: { name?: string; @@ -16,15 +16,18 @@ interface UnattachedMedia { uploaded_at: Date; } -function insertUnattachedMedia(media: Omit) { - return db.insertInto('unattached_media') - .values({ - id: uuid62.v4(), - uploaded_at: new Date(), - ...media, - data: JSON.stringify(media.data), - }) +async function insertUnattachedMedia(media: Omit) { + const result = { + id: uuid62.v4(), + uploaded_at: new Date(), + ...media, + }; + + await db.insertInto('unattached_media') + .values({ ...result, data: JSON.stringify(media.data) }) .execute(); + + return result; } /** Find attachments that exist but aren't attached to any events. */ @@ -32,7 +35,7 @@ function getUnattachedMedia(until: Date) { return db.selectFrom('unattached_media') .select([ 'unattached_media.id', - 'unattached_media.pukey', + 'unattached_media.pubkey', 'unattached_media.url', 'unattached_media.data', 'unattached_media.uploaded_at', @@ -48,4 +51,17 @@ function deleteUnattachedMediaByUrl(url: string) { .execute(); } -export { deleteUnattachedMediaByUrl, getUnattachedMedia, insertUnattachedMedia }; +function getUnattachedMediaByIds(ids: string[]) { + return db.selectFrom('unattached_media') + .select([ + 'unattached_media.id', + 'unattached_media.pubkey', + 'unattached_media.url', + 'unattached_media.data', + 'unattached_media.uploaded_at', + ]) + .where('id', 'in', ids) + .execute(); +} + +export { deleteUnattachedMediaByUrl, getUnattachedMedia, getUnattachedMediaByIds, insertUnattachedMedia }; diff --git a/src/transformers/nostr-to-mastoapi.ts b/src/transformers/nostr-to-mastoapi.ts index 5a3d3a0..4dd7da5 100644 --- a/src/transformers/nostr-to-mastoapi.ts +++ b/src/transformers/nostr-to-mastoapi.ts @@ -143,7 +143,7 @@ async function toStatus(event: Event<1>, viewerPubkey?: string) { const media = event.tags .filter((tag) => tag[0] === 'media') - .map((tag) => ({ url: tag[1], mimeType: tag[2] || undefined })); + .map(([_, url]) => ({ url })); return { id: event.id,