statuses: enable posting with media attachments

This commit is contained in:
Alex Gleason 2023-09-08 18:45:00 -05:00
parent dcc9d05ee5
commit b5a84627c8
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
3 changed files with 48 additions and 41 deletions

View File

@ -1,4 +1,5 @@
import { type AppController } from '@/app.ts'; import { type AppController } from '@/app.ts';
import { Conf } from '@/config.ts';
import { type Event, ISO6391, z } from '@/deps.ts'; import { type Event, ISO6391, z } from '@/deps.ts';
import { getAncestors, getDescendants, getEvent } from '@/queries.ts'; import { getAncestors, getDescendants, getEvent } from '@/queries.ts';
import { toStatus } from '@/transformers/nostr-to-mastoapi.ts'; import { toStatus } from '@/transformers/nostr-to-mastoapi.ts';
@ -40,7 +41,10 @@ const createStatusController: AppController = async (c) => {
const body = await parseBody(c.req.raw); const body = await parseBody(c.req.raw);
const result = createStatusSchema.safeParse(body); const result = createStatusSchema.safeParse(body);
if (result.success) { if (!result.success) {
return c.json({ error: 'Bad request', schema: result.error }, 400);
}
const { data } = result; const { data } = result;
if (data.visibility !== 'public') { if (data.visibility !== 'public') {
@ -51,10 +55,6 @@ const createStatusController: AppController = async (c) => {
return c.json({ error: 'Polls are not yet supported.' }, 422); return c.json({ error: 'Polls are not yet supported.' }, 422);
} }
if (data.media_ids?.length) {
return c.json({ error: 'Media uploads are not yet supported.' }, 422);
}
const tags: string[][] = []; const tags: string[][] = [];
if (data.in_reply_to_id) { if (data.in_reply_to_id) {
@ -69,6 +69,11 @@ const createStatusController: AppController = async (c) => {
tags.push(['subject', data.spoiler_text]); 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]);
}
const event = await createEvent({ const event = await createEvent({
kind: 1, kind: 1,
content: data.status ?? '', content: data.status ?? '',
@ -76,9 +81,6 @@ const createStatusController: AppController = async (c) => {
}, c); }, c);
return c.json(await toStatus(event, c.get('pubkey'))); return c.json(await toStatus(event, c.get('pubkey')));
} else {
return c.json({ error: 'Bad request', schema: result.error }, 400);
}
}; };
const contextController: AppController = async (c) => { const contextController: AppController = async (c) => {

View File

@ -54,7 +54,7 @@ function parseNoteContent(content: string): ParsedNoteContent {
interface MediaLink { interface MediaLink {
url: string; url: string;
mimeType: string; mimeType?: string;
} }
function getMediaLinks(links: Link[]): MediaLink[] { function getMediaLinks(links: Link[]): MediaLink[] {

View File

@ -118,7 +118,6 @@ async function toStatus(event: Event<1>, viewerPubkey?: string) {
]; ];
const { html, links, firstUrl } = parseNoteContent(event.content); const { html, links, firstUrl } = parseNoteContent(event.content);
const mediaLinks = getMediaLinks(links);
const [mentions, card, repliesCount, reblogsCount, favouritesCount, [repostEvent], [reactionEvent]] = await Promise const [mentions, card, repliesCount, reblogsCount, favouritesCount, [repostEvent], [reactionEvent]] = await Promise
.all([ .all([
@ -140,6 +139,12 @@ async function toStatus(event: Event<1>, viewerPubkey?: string) {
const cw = event.tags.find(isCWTag); const cw = event.tags.find(isCWTag);
const subject = event.tags.find((tag) => tag[0] === 'subject'); const subject = event.tags.find((tag) => tag[0] === 'subject');
const mediaLinks = getMediaLinks(links);
const media = event.tags
.filter((tag) => tag[0] === 'media')
.map((tag) => ({ url: tag[1], mimeType: tag[2] || undefined }));
return { return {
id: event.id, id: event.id,
account, account,
@ -161,7 +166,7 @@ async function toStatus(event: Event<1>, viewerPubkey?: string) {
bookmarked: false, bookmarked: false,
reblog: null, reblog: null,
application: null, application: null,
media_attachments: mediaLinks.map(renderAttachment), media_attachments: mediaLinks.concat(media).map(renderAttachment),
mentions, mentions,
tags: [], tags: [],
emojis: toEmojis(event), emojis: toEmojis(event),
@ -187,7 +192,7 @@ function buildInlineRecipients(mentions: Mention[]): string {
const attachmentTypeSchema = z.enum(['image', 'video', 'gifv', 'audio', 'unknown']).catch('unknown'); const attachmentTypeSchema = z.enum(['image', 'video', 'gifv', 'audio', 'unknown']).catch('unknown');
function renderAttachment({ url, mimeType }: MediaLink) { function renderAttachment({ url, mimeType = '' }: MediaLink) {
const [baseType, _subType] = mimeType.split('/'); const [baseType, _subType] = mimeType.split('/');
const type = attachmentTypeSchema.parse(baseType); const type = attachmentTypeSchema.parse(baseType);