From 0bba4393bab753dda9ee097243fbbcf97ff9c5a2 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 11 Nov 2024 19:54:59 -0600 Subject: [PATCH] Remove unused ActivityPub schema --- src/schemas/activitypub.ts | 323 ------------------------------------- 1 file changed, 323 deletions(-) delete mode 100644 src/schemas/activitypub.ts diff --git a/src/schemas/activitypub.ts b/src/schemas/activitypub.ts deleted file mode 100644 index f14c994f..00000000 --- a/src/schemas/activitypub.ts +++ /dev/null @@ -1,323 +0,0 @@ -import { z } from 'zod'; - -const apId = z.string().url(); -const recipients = z.array(z.string()).catch([]); -const published = () => z.string().datetime().catch(new Date().toISOString()); - -/** Validates individual items in an array, dropping any that aren't valid. */ -function filteredArray(schema: T) { - return z.any().array() - .transform((arr) => ( - arr.map((item) => { - const parsed = schema.safeParse(item); - return parsed.success ? parsed.data : undefined; - }).filter((item): item is z.infer => Boolean(item)) - )); -} - -const imageSchema = z.object({ - type: z.literal('Image').catch('Image'), - url: z.string().url(), -}); - -const attachmentSchema = z.object({ - type: z.literal('Document').catch('Document'), - mediaType: z.string().optional().catch(undefined), - url: z.string().url(), -}); - -const mentionSchema = z.object({ - type: z.literal('Mention'), - href: z.string().url(), - name: z.string().optional().catch(undefined), -}); - -const hashtagSchema = z.object({ - type: z.literal('Hashtag'), - href: z.string().url(), - name: z.string(), -}); - -const emojiSchema = z.object({ - type: z.literal('Emoji'), - icon: imageSchema, - name: z.string(), -}); - -const tagSchema = z.discriminatedUnion('type', [ - mentionSchema, - hashtagSchema, - emojiSchema, -]); - -const propertyValueSchema = z.object({ - type: z.literal('PropertyValue'), - name: z.string(), - value: z.string(), - verified_at: z.string().nullish(), -}); - -/** https://codeberg.org/fediverse/fep/src/branch/main/feps/fep-fffd.md */ -const proxySchema = z.object({ - protocol: z.string().url(), - proxied: z.string(), - authoritative: z.boolean().optional().catch(undefined), -}); - -const personSchema = z.object({ - type: z.literal('Person'), - id: apId, - icon: imageSchema.optional().catch(undefined), - image: imageSchema.optional().catch(undefined), - name: z.string().catch(''), - preferredUsername: z.string(), - inbox: apId, - followers: apId.optional().catch(undefined), - following: apId.optional().catch(undefined), - outbox: apId.optional().catch(undefined), - summary: z.string().catch(''), - attachment: filteredArray(propertyValueSchema).catch([]), - tag: filteredArray(emojiSchema).catch([]), - endpoints: z.object({ - sharedInbox: apId.optional(), - }).optional().catch({}), - publicKey: z.object({ - id: apId, - owner: apId, - publicKeyPem: z.string(), - }).optional().catch(undefined), - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const applicationSchema = personSchema.merge(z.object({ type: z.literal('Application') })); -const groupSchema = personSchema.merge(z.object({ type: z.literal('Group') })); -const organizationSchema = personSchema.merge(z.object({ type: z.literal('Organization') })); -const serviceSchema = personSchema.merge(z.object({ type: z.literal('Service') })); - -const actorSchema = z.discriminatedUnion('type', [ - personSchema, - applicationSchema, - groupSchema, - organizationSchema, - serviceSchema, -]); - -const noteSchema = z.object({ - type: z.literal('Note'), - id: apId, - to: recipients, - cc: recipients, - content: z.string(), - attachment: z.array(attachmentSchema).optional().catch(undefined), - tag: filteredArray(tagSchema).catch([]), - inReplyTo: apId.optional().catch(undefined), - attributedTo: apId, - published: published(), - sensitive: z.boolean().optional().catch(undefined), - summary: z.string().nullish().catch(undefined), - quoteUrl: apId.optional().catch(undefined), - source: z.object({ - content: z.string(), - mediaType: z.literal('text/markdown'), - }).optional().catch(undefined), - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const flexibleNoteSchema = noteSchema.extend({ - quoteURL: apId.optional().catch(undefined), - quoteUri: apId.optional().catch(undefined), - _misskey_quote: apId.optional().catch(undefined), -}).transform((note) => { - const { quoteUrl, quoteUri, quoteURL, _misskey_quote, ...rest } = note; - return { - quoteUrl: quoteUrl || quoteUri || quoteURL || _misskey_quote, - ...rest, - }; -}); - -// https://github.com/colinhacks/zod/discussions/2100#discussioncomment-5109781 -const objectSchema = z.union([ - flexibleNoteSchema, - personSchema, - applicationSchema, - groupSchema, - organizationSchema, - serviceSchema, -]).pipe( - z.discriminatedUnion('type', [ - noteSchema, - personSchema, - applicationSchema, - groupSchema, - organizationSchema, - serviceSchema, - ]), -); - -const createNoteSchema = z.object({ - type: z.literal('Create'), - id: apId, - to: recipients, - cc: recipients, - actor: apId, - object: noteSchema, - published: published(), - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const announceNoteSchema = z.object({ - type: z.literal('Announce'), - id: apId, - to: recipients, - cc: recipients, - actor: apId, - object: apId.or(noteSchema), - published: published(), - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const followSchema = z.object({ - type: z.literal('Follow'), - id: apId, - to: recipients, - cc: recipients, - actor: apId, - object: apId, - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const acceptSchema = z.object({ - type: z.literal('Accept'), - id: apId, - actor: apId, - to: recipients, - cc: recipients, - object: apId.or(followSchema), -}); - -const likeSchema = z.object({ - type: z.literal('Like'), - id: apId, - actor: apId, - object: apId, - to: recipients, - cc: recipients, - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const emojiReactSchema = z.object({ - type: z.literal('EmojiReact'), - id: apId, - actor: apId, - object: apId, - content: z.string().refine((v) => /\p{Extended_Pictographic}/u.test(v)), - to: recipients, - cc: recipients, - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const deleteSchema = z.object({ - type: z.literal('Delete'), - id: apId, - actor: apId, - object: apId, - to: recipients, - cc: recipients, - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const updateActorSchema = z.object({ - type: z.literal('Update'), - id: apId, - actor: apId, - to: recipients, - cc: recipients, - object: actorSchema, - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -/** - * A custom Zap activity type we made up, based on: - * https://github.com/nostr-protocol/nips/blob/master/57.md - */ -const zapSchema = z.object({ - type: z.literal('Zap'), - id: apId, - actor: apId, - object: apId, - to: recipients, - cc: recipients, - proxyOf: z.array(proxySchema).optional().catch(undefined), -}); - -const activitySchema = z.discriminatedUnion('type', [ - followSchema, - acceptSchema, - createNoteSchema, - announceNoteSchema, - updateActorSchema, - likeSchema, - emojiReactSchema, - deleteSchema, - zapSchema, -]).refine((activity) => { - const ids: string[] = [activity.id]; - - if (activity.type === 'Create') { - ids.push( - activity.object.id, - activity.object.attributedTo, - ); - } - - if (activity.type === 'Update') { - ids.push(activity.object.id); - } - - const { origin: actorOrigin } = new URL(activity.actor); - - // Object containment - return ids.every((id) => { - const { origin: idOrigin } = new URL(id); - return idOrigin === actorOrigin; - }); -}); - -type Activity = z.infer; -type CreateNote = z.infer; -type Announce = z.infer; -type Update = z.infer; -type Object = z.infer; -type Follow = z.infer; -type Accept = z.infer; -type Actor = z.infer; -type Note = z.infer; -type Mention = z.infer; -type Hashtag = z.infer; -type Emoji = z.infer; -type Like = z.infer; -type EmojiReact = z.infer; -type Delete = z.infer; -type Zap = z.infer; -type Proxy = z.infer; - -export { acceptSchema, activitySchema, actorSchema, emojiSchema, followSchema, imageSchema, noteSchema, objectSchema }; -export type { - Accept, - Activity, - Actor, - Announce, - CreateNote, - Delete, - Emoji, - EmojiReact, - Follow, - Hashtag, - Like, - Mention, - Note, - Object, - Proxy, - Update, - Zap, -};