Fix uploading (almost)

This commit is contained in:
Alex Gleason 2024-05-18 14:32:50 -05:00
parent 7d34b9401e
commit 611a94bdcf
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
6 changed files with 38 additions and 28 deletions

View File

@ -5,7 +5,7 @@ import { z } from 'zod';
import { type AppController } from '@/app.ts'; import { type AppController } from '@/app.ts';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { DittoDB } from '@/db/DittoDB.ts'; import { DittoDB } from '@/db/DittoDB.ts';
import { getUnattachedMediaByIds } from '@/db/unattached-media.ts'; import { getUnattachedMediaByUrls } from '@/db/unattached-media.ts';
import { getAncestors, getAuthor, getDescendants, getEvent } from '@/queries.ts'; import { getAncestors, getAuthor, getDescendants, getEvent } from '@/queries.ts';
import { addTag, deleteTag } from '@/tags.ts'; import { addTag, deleteTag } from '@/tags.ts';
import { createEvent, paginationSchema, parseBody, updateListEvent } from '@/utils/api.ts'; import { createEvent, paginationSchema, parseBody, updateListEvent } from '@/utils/api.ts';
@ -94,9 +94,15 @@ const createStatusController: AppController = async (c) => {
const viewerPubkey = await c.get('signer')?.getPublicKey(); const viewerPubkey = await c.get('signer')?.getPublicKey();
if (data.media_ids?.length) { if (data.media_ids?.length) {
const media = await getUnattachedMediaByIds(kysely, data.media_ids) const media = await getUnattachedMediaByUrls(kysely, data.media_ids)
.then((media) => media.filter(({ pubkey }) => pubkey === viewerPubkey)) .then((media) => media.filter(({ pubkey }) => pubkey === viewerPubkey))
.then((media) => media.map(({ data }) => ['imeta', ...data])); .then((media) =>
media.map(({ data }) => {
const tags: string[][] = JSON.parse(data);
const values: string[] = tags.map((tag) => tag.join(' '));
return ['imeta', ...values];
})
);
tags.push(...media); tags.push(...media);
} }

View File

@ -64,6 +64,14 @@ async function getUnattachedMediaByIds(kysely: Kysely<DittoTables>, ids: string[
.execute(); .execute();
} }
/** Get unattached media by URLs. */
async function getUnattachedMediaByUrls(kysely: Kysely<DittoTables>, urls: string[]) {
if (!urls.length) return [];
return await selectUnattachedMediaQuery(kysely)
.where('url', 'in', urls)
.execute();
}
/** Delete rows as an event with media is being created. */ /** Delete rows as an event with media is being created. */
async function deleteAttachedMedia(pubkey: string, urls: string[]): Promise<void> { async function deleteAttachedMedia(pubkey: string, urls: string[]): Promise<void> {
if (!urls.length) return; if (!urls.length) return;
@ -79,6 +87,7 @@ export {
deleteUnattachedMediaByUrl, deleteUnattachedMediaByUrl,
getUnattachedMedia, getUnattachedMedia,
getUnattachedMediaByIds, getUnattachedMediaByIds,
getUnattachedMediaByUrls,
insertUnattachedMedia, insertUnattachedMedia,
type UnattachedMedia, type UnattachedMedia,
}; };

View File

@ -29,6 +29,8 @@ async function createEvent(t: EventStub, c: AppContext): Promise<NostrEvent> {
}); });
} }
console.log(t);
const event = await signer.signEvent({ const event = await signer.signEvent({
content: '', content: '',
created_at: nostrNow(), created_at: nostrNow(),

View File

@ -5,7 +5,6 @@ import { nip19, nip21 } from 'nostr-tools';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { getUrlMediaType, isPermittedMediaType } from '@/utils/media.ts'; import { getUrlMediaType, isPermittedMediaType } from '@/utils/media.ts';
import { type DittoAttachment } from '@/views/mastodon/attachments.ts';
linkify.registerCustomProtocol('nostr', true); linkify.registerCustomProtocol('nostr', true);
linkify.registerCustomProtocol('wss'); linkify.registerCustomProtocol('wss');
@ -58,18 +57,17 @@ function parseNoteContent(content: string): ParsedNoteContent {
}; };
} }
function getMediaLinks(links: Pick<Link, 'href'>[]): DittoAttachment[] { /** Returns a matrix of tags. Each item is a list of NIP-94 tags representing a file. */
return links.reduce<DittoAttachment[]>((acc, link) => { function getMediaLinks(links: Pick<Link, 'href'>[]): string[][][] {
return links.reduce<string[][][]>((acc, link) => {
const mediaType = getUrlMediaType(link.href); const mediaType = getUrlMediaType(link.href);
if (!mediaType) return acc; if (!mediaType) return acc;
if (isPermittedMediaType(mediaType, ['audio', 'image', 'video'])) { if (isPermittedMediaType(mediaType, ['audio', 'image', 'video'])) {
acc.push({ acc.push([
url: link.href, ['url', link.href],
data: { ['m', mediaType],
mime: mediaType, ]);
},
});
} }
return acc; return acc;

View File

@ -4,16 +4,16 @@ import { UnattachedMedia } from '@/db/unattached-media.ts';
type DittoAttachment = TypeFest.SetOptional<UnattachedMedia, 'id' | 'pubkey' | 'uploaded_at'>; type DittoAttachment = TypeFest.SetOptional<UnattachedMedia, 'id' | 'pubkey' | 'uploaded_at'>;
function renderAttachment(media: DittoAttachment) { function renderAttachment(tags: string[][]) {
const { id, data, url } = media; const url = tags.find(([name]) => name === 'url')?.[1];
const m = data.find(([name]) => name === 'm')?.[1]; const m = tags.find(([name]) => name === 'm')?.[1];
const alt = data.find(([name]) => name === 'alt')?.[1]; const alt = tags.find(([name]) => name === 'alt')?.[1];
const cid = data.find(([name]) => name === 'cid')?.[1]; const cid = tags.find(([name]) => name === 'cid')?.[1];
const blurhash = data.find(([name]) => name === 'blurhash')?.[1]; const blurhash = tags.find(([name]) => name === 'blurhash')?.[1];
return { return {
id: id ?? url, id: url,
type: getAttachmentType(m ?? ''), type: getAttachmentType(m ?? ''),
url, url,
preview_url: url, preview_url: url,

View File

@ -10,7 +10,7 @@ import { nostrDate } from '@/utils.ts';
import { getMediaLinks, parseNoteContent } from '@/utils/note.ts'; import { getMediaLinks, parseNoteContent } from '@/utils/note.ts';
import { unfurlCardCached } from '@/utils/unfurl.ts'; import { unfurlCardCached } from '@/utils/unfurl.ts';
import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts'; import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts';
import { DittoAttachment, renderAttachment } from '@/views/mastodon/attachments.ts'; import { renderAttachment } from '@/views/mastodon/attachments.ts';
import { renderEmojis } from '@/views/mastodon/emojis.ts'; import { renderEmojis } from '@/views/mastodon/emojis.ts';
interface RenderStatusOpts { interface RenderStatusOpts {
@ -78,16 +78,11 @@ async function renderStatus(event: DittoEvent, opts: RenderStatusOpts): Promise<
const mediaLinks = getMediaLinks(links); const mediaLinks = getMediaLinks(links);
const mediaTags: DittoAttachment[] = event.tags const imeta: string[][][] = event.tags
.filter(([name]) => name === 'imeta') .filter(([name]) => name === 'imeta')
.map(([_, ...entries]) => { .map(([_, ...entries]) => entries.map((entry) => entry.split(' ')));
const data = entries.map((entry) => entry.split(' '));
const url = data.find(([name]) => name === 'url')?.[1];
return { url, data };
})
.filter((media): media is DittoAttachment => !!media.url);
const media = [...mediaLinks, ...mediaTags]; const media = [...mediaLinks, ...imeta];
return { return {
id: event.id, id: event.id,