diff --git a/package.json b/package.json index 13d5ab8f905c..54d6872c28cf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "mei23 ", - "version": "10.102.698-m544", + "version": "10.102.699-m544", "codename": "m544", "repository": { "type": "git", @@ -95,7 +95,7 @@ "jsdom": "20.0.3", "json5": "2.2.3", "json5-loader": "4.0.1", - "jsonld": "5.2.0", + "jsonld": "8.3.2", "katex": "0.16.10", "koa": "2.15.2", "koa-bodyparser": "4.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fbcc6d054526..0b6c52f3b3d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -201,8 +201,8 @@ dependencies: specifier: 4.0.1 version: 4.0.1(webpack@5.91.0) jsonld: - specifier: 5.2.0 - version: 5.2.0 + specifier: 8.3.2 + version: 8.3.2 katex: specifier: 0.16.10 version: 0.16.10 @@ -642,10 +642,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /@adobe/css-tools@4.0.1: - resolution: {integrity: sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==} - dev: false - /@adobe/css-tools@4.3.3: resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} dev: false @@ -1563,15 +1559,14 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: false - /@digitalbazaar/http-client@1.2.0: - resolution: {integrity: sha512-W9KQQ5pUJcaR0I4c2HPJC0a7kRbZApIorZgPnEDwMBgj16iQzutGLrCXYaZOmxqVLVNqqlQ4aUJh+HBQZy4W6Q==} - engines: {node: '>=10.0.0'} + /@digitalbazaar/http-client@3.4.1: + resolution: {integrity: sha512-Ahk1N+s7urkgj7WvvUND5f8GiWEPfUw0D41hdElaqLgu8wZScI8gdI0q+qWw5N1d35x7GCRH2uk9mi+Uzo9M3g==} + engines: {node: '>=14.0'} dependencies: - esm: 3.2.25 - ky: 0.25.1 - ky-universal: 0.8.2(ky@0.25.1) + ky: 0.33.3 + ky-universal: 0.11.0(ky@0.33.3) + undici: 5.28.4 transitivePeerDependencies: - - domexception - web-streams-polyfill dev: false @@ -1633,6 +1628,11 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@fastify/busboy@2.1.1: + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + dev: false + /@fortawesome/fontawesome-common-types@0.2.36: resolution: {integrity: sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==} engines: {node: '>=6'} @@ -5464,9 +5464,9 @@ packages: assert-plus: 1.0.0 dev: false - /data-uri-to-buffer@3.0.1: - resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==} - engines: {node: '>= 6'} + /data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} dev: false /data-urls@3.0.2: @@ -6205,11 +6205,6 @@ packages: - supports-color dev: true - /esm@3.2.25: - resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} - engines: {node: '>=6'} - dev: false - /esniff@2.0.1: resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} engines: {node: '>=0.10'} @@ -6396,14 +6391,12 @@ packages: dependencies: reusify: 1.0.4 - /fetch-blob@2.1.2: - resolution: {integrity: sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==} - engines: {node: ^10.17.0 || >=12.3.0} - peerDependencies: - domexception: '*' - peerDependenciesMeta: - domexception: - optional: true + /fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 dev: false /file-entry-cache@6.0.1: @@ -6584,6 +6577,13 @@ packages: mime-types: 2.1.35 dev: false + /formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + dependencies: + fetch-blob: 3.2.0 + dev: false + /fragment-cache@0.2.1: resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} engines: {node: '>=0.10.0'} @@ -7989,7 +7989,7 @@ packages: parse5: 7.1.2 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 4.1.2 + tough-cookie: 4.1.3 w3c-xmlserializer: 4.0.0 webidl-conversions: 7.0.0 whatwg-encoding: 2.0.0 @@ -8056,16 +8056,15 @@ packages: engines: {node: '>=6'} hasBin: true - /jsonld@5.2.0: - resolution: {integrity: sha512-JymgT6Xzk5CHEmHuEyvoTNviEPxv6ihLWSPu1gFdtjSAyM6cFqNrv02yS/SIur3BBIkCf0HjizRc24d8/FfQKw==} - engines: {node: '>=12'} + /jsonld@8.3.2: + resolution: {integrity: sha512-MwBbq95szLwt8eVQ1Bcfwmgju/Y5P2GdtlHE2ncyfuYjIdEhluUVyj1eudacf1mOkWIoS9GpDBTECqhmq7EOaA==} + engines: {node: '>=14'} dependencies: - '@digitalbazaar/http-client': 1.2.0 + '@digitalbazaar/http-client': 3.4.1 canonicalize: 1.0.8 lru-cache: 6.0.0 - rdf-canonize: 3.3.0 + rdf-canonize: 3.4.0 transitivePeerDependencies: - - domexception - web-streams-polyfill dev: false @@ -8315,26 +8314,24 @@ packages: - supports-color dev: false - /ky-universal@0.8.2(ky@0.25.1): - resolution: {integrity: sha512-xe0JaOH9QeYxdyGLnzUOVGK4Z6FGvDVzcXFTdrYA1f33MZdEa45sUDaMBy98xQMcsd2XIBrTXRrRYnegcSdgVQ==} - engines: {node: '>=10.17'} + /ky-universal@0.11.0(ky@0.33.3): + resolution: {integrity: sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==} + engines: {node: '>=14.16'} peerDependencies: - ky: '>=0.17.0' - web-streams-polyfill: '>=2.0.0' + ky: '>=0.31.4' + web-streams-polyfill: '>=3.2.1' peerDependenciesMeta: web-streams-polyfill: optional: true dependencies: abort-controller: 3.0.0 - ky: 0.25.1 - node-fetch: 3.0.0-beta.9 - transitivePeerDependencies: - - domexception + ky: 0.33.3 + node-fetch: 3.3.2 dev: false - /ky@0.25.1: - resolution: {integrity: sha512-PjpCEWlIU7VpiMVrTwssahkYXX1by6NCT0fhTUX34F3DTinARlgMpriuroolugFPcMgpPWrOW4mTb984Qm1RXA==} - engines: {node: '>=10'} + /ky@0.33.3: + resolution: {integrity: sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==} + engines: {node: '>=14.16'} dev: false /last-run@1.1.1: @@ -9164,6 +9161,11 @@ packages: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true + /node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: false + /node-ensure@0.0.0: resolution: {integrity: sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw==} dev: false @@ -9183,14 +9185,13 @@ packages: dependencies: whatwg-url: 5.0.0 - /node-fetch@3.0.0-beta.9: - resolution: {integrity: sha512-RdbZCEynH2tH46+tj0ua9caUHVWrd/RHnRfvly2EVdqGmI3ndS1Vn/xjm5KuGejDt2RNDQsVRLPNd2QPwcewVg==} - engines: {node: ^10.17 || >=12.3} + /node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: - data-uri-to-buffer: 3.0.1 - fetch-blob: 2.1.2 - transitivePeerDependencies: - - domexception + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 dev: false /node-gyp-build-optional-packages@5.0.7: @@ -10441,8 +10442,8 @@ packages: unpipe: 1.0.0 dev: false - /rdf-canonize@3.3.0: - resolution: {integrity: sha512-gfSNkMua/VWC1eYbSkVaL/9LQhFeOh0QULwv7Or0f+po8pMgQ1blYQFe1r9Mv2GJZXw88Cz/drnAnB9UlNnHfQ==} + /rdf-canonize@3.4.0: + resolution: {integrity: sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==} engines: {node: '>=12'} dependencies: setimmediate: 1.0.5 @@ -11476,7 +11477,7 @@ packages: resolution: {integrity: sha512-lQ9w/XIOH5ZHVNuNbWW8D822r+/wBSO/d6XvtyHLF7LW4KaCIDeVbvn5DF8fGCJAUCwVhVi/h6J0NUcnylUEjg==} hasBin: true dependencies: - '@adobe/css-tools': 4.0.1 + '@adobe/css-tools': 4.3.3 debug: 4.3.4(supports-color@8.1.1) glob: 7.2.3 sax: 1.2.4 @@ -11869,8 +11870,8 @@ packages: ieee754: 1.2.1 dev: false - /tough-cookie@4.1.2: - resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} engines: {node: '>=6'} dependencies: psl: 1.9.0 @@ -12098,6 +12099,13 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + /undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + dependencies: + '@fastify/busboy': 2.1.1 + dev: false + /unenv@1.9.0: resolution: {integrity: sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==} dependencies: @@ -12563,6 +12571,11 @@ packages: - supports-color dev: false + /web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + dev: false + /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} diff --git a/src/queue/processors/inbox.ts b/src/queue/processors/inbox.ts index 4a7bf38cb8cd..5e8f2bf2252c 100644 --- a/src/queue/processors/inbox.ts +++ b/src/queue/processors/inbox.ts @@ -22,6 +22,7 @@ import resolveUser from '../../remote/resolve-user'; import config from '../../config'; import { publishInstanceModUpdated } from '../../services/server-event'; import { StatusError } from '../../misc/fetch'; +import { FIXED_CONTEXT } from '../../remote/activitypub/misc/contexts'; const logger = new Logger('inbox'); @@ -37,7 +38,7 @@ type ApContext = { export const tryProcessInbox = async (data: InboxJobData, ctx?: ApContext): Promise => { const signature = data.signature; - const activity = data.activity; + let activity = data.activity; const resolver = ctx?.resolver || new Resolver(); @@ -111,6 +112,11 @@ export const tryProcessInbox = async (data: InboxJobData, ctx?: ApContext): Prom return `skip: LD-Signatureの検証に失敗しました`; } + const activity2 = JSON.parse(JSON.stringify(activity)); + delete activity2.signature; + const compacted = await ldSignature.compact(activity2, FIXED_CONTEXT); + activity = compacted as any; + // もう一度actorチェック if (user.uri !== activity.actor) { return `skip: LD-Signature user(${user.uri}) !== activity.actor(${activity.actor})`; diff --git a/src/remote/activitypub/misc/contexts.ts b/src/remote/activitypub/misc/contexts.ts index 1426ba15f5c6..7bab32e1242f 100644 --- a/src/remote/activitypub/misc/contexts.ts +++ b/src/remote/activitypub/misc/contexts.ts @@ -524,3 +524,38 @@ export const CONTEXTS: Record = { "https://w3id.org/security/v1": security_v1, "https://www.w3.org/ns/activitystreams": activitystreams, }; + +export const FIXED_CONTEXT = [ + 'https://www.w3.org/ns/activitystreams', + 'https://w3id.org/security/v1', + { + Key: 'sec:Key', + // as non-standards + manuallyApprovesFollowers: 'as:manuallyApprovesFollowers', + sensitive: 'as:sensitive', + Hashtag: 'as:Hashtag', + // Mastodon + toot: 'http://joinmastodon.org/ns#', + Emoji: 'toot:Emoji', + featured: 'toot:featured', + discoverable: 'toot:discoverable', + indexable: 'toot:indexable', + // schema + schema: 'http://schema.org#', + PropertyValue: 'schema:PropertyValue', + value: 'schema:value', + // Misskey + misskey: 'https://misskey-hub.net/ns#', + '_misskey_content': 'misskey:_misskey_content', + '_misskey_quote': 'misskey:_misskey_quote', + '_misskey_reaction': 'misskey:_misskey_reaction', + '_misskey_votes': 'misskey:_misskey_votes', + 'isCat': 'misskey:isCat', + // vcard + vcard: 'http://www.w3.org/2006/vcard/ns#', + // Fedibird + fedibird: 'http://fedibird.com/ns#', + quoteUri: 'fedibird:quoteUri', + searchableBy: { '@id': 'fedibird:searchableBy', '@type': '@id' }, + } +]; diff --git a/src/remote/activitypub/misc/ld-signature.ts b/src/remote/activitypub/misc/ld-signature.ts index 15fb4dce66db..ccffc00ed063 100644 --- a/src/remote/activitypub/misc/ld-signature.ts +++ b/src/remote/activitypub/misc/ld-signature.ts @@ -103,6 +103,13 @@ export class LdSignature { }); } + public async compact(data: any, context: any) { + const customLoader = this.getLoader(); + return await jsonld.compact(data, context, { + documentLoader: customLoader + }); + } + private getLoader() { return async (url: string): Promise => { if (!url.match('^https?\:\/\/')) throw `Invalid URL ${url}`; diff --git a/src/remote/activitypub/models/image.ts b/src/remote/activitypub/models/image.ts index 7dc6988c6061..20c25e3decd8 100644 --- a/src/remote/activitypub/models/image.ts +++ b/src/remote/activitypub/models/image.ts @@ -23,7 +23,7 @@ export async function createImage(actor: IRemoteUser, value: IObject): Promise { +export async function resolveImage(actor: IRemoteUser, value: IObject): Promise { // TODO // リモートサーバーからフェッチしてきて登録 diff --git a/src/remote/activitypub/models/note.ts b/src/remote/activitypub/models/note.ts index 18205d3ea4ba..1245f53f0c2f 100644 --- a/src/remote/activitypub/models/note.ts +++ b/src/remote/activitypub/models/note.ts @@ -331,7 +331,7 @@ async function fetchAttachments(note: IPost, actor: IRemoteUser) { let files: IDriveFile[] = []; for (const attach of attachment) { - attach.sensitive ||= note.sensitive + attach.sensitive ??= note.sensitive; const file = await resolveImage(actor, attach); if (file) files.push(file); } diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts index 1d7f5c7464d6..6055f134b7e3 100644 --- a/src/remote/activitypub/models/person.ts +++ b/src/remote/activitypub/models/person.ts @@ -629,7 +629,7 @@ function parseSearchableBy(actor: IActor): 'public' | 'none' | null { // searchableByでpublicならpublic const searchableBy = toArray(actor.searchableBy); - if (searchableBy.includes('https://www.w3.org/ns/activitystreams#Public')) return 'public'; + if (searchableBy.includes('https://www.w3.org/ns/activitystreams#Public') || searchableBy.includes('as:Public')) return 'public'; // indexableで明示的に拒否されていればnone if (actor.indexable === false) return 'none'; diff --git a/src/remote/activitypub/renderer/document.ts b/src/remote/activitypub/renderer/document.ts index 17721e941730..7ddb062390fe 100644 --- a/src/remote/activitypub/renderer/document.ts +++ b/src/remote/activitypub/renderer/document.ts @@ -4,5 +4,6 @@ import getDriveFileUrl from '../../../misc/get-drive-file-url'; export default (file: IDriveFile) => ({ type: 'Document', mediaType: file.contentType, + sensitive: !!file.metadata?.isSensitive, url: getDriveFileUrl(file) }); diff --git a/src/remote/activitypub/renderer/image.ts b/src/remote/activitypub/renderer/image.ts index ec637b9521dd..29aff6027b3c 100644 --- a/src/remote/activitypub/renderer/image.ts +++ b/src/remote/activitypub/renderer/image.ts @@ -4,5 +4,5 @@ import getDriveFileUrl from '../../../misc/get-drive-file-url'; export default (file: IDriveFile) => ({ type: 'Image', url: getDriveFileUrl(file), - sensitive: file.metadata.isSensitive + sensitive: !!file.metadata?.isSensitive }); diff --git a/src/remote/activitypub/renderer/index.ts b/src/remote/activitypub/renderer/index.ts index efce8ebadae3..8705f06cfd86 100644 --- a/src/remote/activitypub/renderer/index.ts +++ b/src/remote/activitypub/renderer/index.ts @@ -3,6 +3,7 @@ import { v4 as uuid } from 'uuid'; import { IActivity } from '../type'; import { LdSignature } from '../misc/ld-signature'; import { ILocalUser } from '../../../models/user'; +import { FIXED_CONTEXT } from '../misc/contexts'; export const renderActivity = (x: any): IActivity | null => { if (x == null) return null; @@ -12,40 +13,7 @@ export const renderActivity = (x: any): IActivity | null => { } return Object.assign({ - '@context': [ - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - { - Key: 'sec:Key', - // as non-standards - manuallyApprovesFollowers: 'as:manuallyApprovesFollowers', - sensitive: 'as:sensitive', - Hashtag: 'as:Hashtag', - // Mastodon - toot: 'http://joinmastodon.org/ns#', - Emoji: 'toot:Emoji', - featured: 'toot:featured', - discoverable: 'toot:discoverable', - indexable: 'toot:indexable', - // schema - schema: 'http://schema.org#', - PropertyValue: 'schema:PropertyValue', - value: 'schema:value', - // Misskey - misskey: 'https://misskey-hub.net/ns#', - '_misskey_content': 'misskey:_misskey_content', - '_misskey_quote': 'misskey:_misskey_quote', - '_misskey_reaction': 'misskey:_misskey_reaction', - '_misskey_votes': 'misskey:_misskey_votes', - 'isCat': 'misskey:isCat', - // vcard - vcard: 'http://www.w3.org/2006/vcard/ns#', - // Fedibird - fedibird: 'http://fedibird.com/ns#', - quoteUri: 'fedibird:quoteUri', - searchableBy: { '@id': 'fedibird:searchableBy', '@type': '@id' }, - } - ] + '@context': FIXED_CONTEXT }, x); }; diff --git a/src/remote/activitypub/renderer/note.ts b/src/remote/activitypub/renderer/note.ts index ce8044ad9bd9..fb22ed7b5aea 100644 --- a/src/remote/activitypub/renderer/note.ts +++ b/src/remote/activitypub/renderer/note.ts @@ -8,6 +8,7 @@ import Note, { INote } from '../../../models/note'; import User from '../../../models/user'; import { getNoteHtml } from '../misc/get-note-html'; import Emoji, { IEmoji } from '../../../models/emoji'; +import { removeNull } from '../../../prelude/array'; export default async function renderNote(note: INote, dive = true): Promise { let inReplyTo; @@ -151,8 +152,8 @@ export default async function renderNote(note: INote, dive = true): Promise to, cc, inReplyTo, - attachment: files.map(renderDocument), - sensitive: note.cw != null || files.some(file => file.metadata.isSensitive), + attachment: removeNull(files).map(renderDocument), + sensitive: note.cw != null || files.some(file => file?.metadata?.isSensitive), likes: `${config.url}/notes/${note._id}/likes`, tag, ...asPoll, diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts index 64738c3cd207..956e7593a62a 100644 --- a/src/remote/activitypub/type.ts +++ b/src/remote/activitypub/type.ts @@ -192,7 +192,7 @@ export interface IApDocument extends IObject { export const isDocument = (object: IObject): object is IApDocument => ['Audio', 'Document', 'Image', 'Page', 'Video'].includes(getApType(object)); -export interface IApImage extends IObject { +export interface IApImage extends IApDocument { type: 'Image'; }