diff --git a/package.json b/package.json index 37c7ad2687..825450f192 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "@bull-board/api": "5.2.0", "@bull-board/ui": "5.2.0", - "@napi-rs/cli": "^2.16.1", + "@napi-rs/cli": "^2.16.3", "js-yaml": "4.1.0" }, "devDependencies": { diff --git a/packages/backend/package.json b/packages/backend/package.json index 86f94c41b3..af9fc1501c 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -100,7 +100,7 @@ "rss-parser": "3.13.0", "sanitize-html": "2.10.0", "semver": "7.5.1", - "sharp": "0.32.1", + "sharp": "0.32.6", "sonic-channel": "^1.3.1", "stringz": "2.1.0", "syslog-pro": "1.0.0", diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index 3f0b231b9c..cbc15814d5 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -2,7 +2,7 @@ import {In} from "typeorm"; import * as mfm from "mfm-js"; import {Note} from "@/models/entities/note.js"; import type {User} from "@/models/entities/user.js"; -import {DriveFiles, Followings, NoteReactions, Polls, PollVotes, Users,} from "../index.js"; +import {DriveFiles, Followings, NoteReactions, Notes, Polls, PollVotes, Users,} from "../index.js"; import type {Packed} from "@/misc/schema.js"; import {nyaize} from "@/misc/nyaize.js"; import {awaitAll} from "@/prelude/await-all.js"; @@ -175,6 +175,11 @@ export const NoteRepository = db.getRepository(Note).extend({ .map((x) => decodeReaction(x).reaction) .map((x) => x.replace(/:/g, "")); + const userRenoteExists = meId ? (Notes.createQueryBuilder("note") + .andWhere("note.renoteId = :renoteId", { renoteId: note.id }) + .andWhere("note.userId = :userId", { userId: meId }) + .getExists()) : (async () => false)(); + const noteEmoji = await populateEmojis( note.emojis.concat(reactionEmojiNames), host, @@ -207,6 +212,7 @@ export const NoteRepository = db.getRepository(Note).extend({ uri: note.uri || undefined, url: note.url || undefined, updatedAt: note.updatedAt?.toISOString() || undefined, + hasRenotedBefore: userRenoteExists, poll: note.hasPoll ? populatePoll(note, meId) : undefined, ...(meId ? { diff --git a/packages/backend/src/models/schema/note.ts b/packages/backend/src/models/schema/note.ts index 76ae412fa7..e5f9fca112 100644 --- a/packages/backend/src/models/schema/note.ts +++ b/packages/backend/src/models/schema/note.ts @@ -167,5 +167,11 @@ export const packedNoteSchema = { optional: true, nullable: true, }, + + hasRenotedBefore: { + type: "boolean", + optional: true, + nullable: false, + } }, } as const; diff --git a/packages/backend/src/remote/activitypub/kernel/create/index.ts b/packages/backend/src/remote/activitypub/kernel/create/index.ts index 3dcf648247..af93a58538 100644 --- a/packages/backend/src/remote/activitypub/kernel/create/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/create/index.ts @@ -1,10 +1,10 @@ import Resolver from "../../resolver.js"; -import type { CacheableRemoteUser } from "@/models/entities/user.js"; +import type {CacheableRemoteUser} from "@/models/entities/user.js"; import createNote from "./note.js"; -import type { ICreate } from "../../type.js"; -import { getApId, isPost, getApType } from "../../type.js"; -import { apLogger } from "../../logger.js"; -import { toArray, concat, unique } from "@/prelude/array.js"; +import type {ICreate} from "../../type.js"; +import {getApId, getApType, isPost} from "../../type.js"; +import {apLogger} from "../../logger.js"; +import {concat, toArray, unique} from "@/prelude/array.js"; const logger = apLogger; @@ -44,7 +44,7 @@ export default async ( }); if (isPost(object)) { - createNote(resolver, actor, object, false, activity); + await createNote(resolver, actor, object, false, activity); } else { logger.warn(`Unknown type: ${getApType(object)}`); } diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index 68cb6fa3ad..12e016a514 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -2,55 +2,37 @@ import promiseLimit from "promise-limit"; import * as mfm from "mfm-js"; import config from "@/config/index.js"; import Resolver from "../resolver.js"; -import post from "@/services/note/create.js"; -import { extractMentionedUsers } from "@/services/note/create.js"; -import { resolvePerson } from "./person.js"; -import { resolveImage } from "./image.js"; -import type { - ILocalUser, - CacheableRemoteUser, -} from "@/models/entities/user.js"; -import { htmlToMfm } from "../misc/html-to-mfm.js"; -import { extractApHashtags } from "./tag.js"; -import { unique, toArray, toSingle } from "@/prelude/array.js"; -import { extractPollFromQuestion } from "./question.js"; +import post, {extractMentionedUsers} from "@/services/note/create.js"; +import {resolvePerson} from "./person.js"; +import {resolveImage} from "./image.js"; +import type {CacheableRemoteUser,} from "@/models/entities/user.js"; +import {htmlToMfm} from "../misc/html-to-mfm.js"; +import {extractApHashtags} from "./tag.js"; +import {toArray, toSingle, unique} from "@/prelude/array.js"; +import {extractPollFromQuestion} from "./question.js"; import vote from "@/services/note/polls/vote.js"; -import { apLogger } from "../logger.js"; -import { DriveFile } from "@/models/entities/drive-file.js"; -import { extractDbHost, toPuny } from "@/misc/convert-host.js"; -import { - Emojis, - Polls, - Notes, - NoteEdits, - DriveFiles, -} from "@/models/index.js"; -import type { IMentionedRemoteUsers, Note } from "@/models/entities/note.js"; -import type { IObject, IPost } from "../type.js"; -import { - getOneApId, - getApId, - getOneApHrefNullable, - validPost, - isEmoji, - getApType, -} from "../type.js"; -import type { Emoji } from "@/models/entities/emoji.js"; -import { genId } from "@/misc/gen-id.js"; -import { getApLock } from "@/misc/app-lock.js"; -import { parseAudience } from "../audience.js"; -import { extractApMentions } from "./mention.js"; +import {apLogger} from "../logger.js"; +import {DriveFile} from "@/models/entities/drive-file.js"; +import {extractDbHost, toPuny} from "@/misc/convert-host.js"; +import {DriveFiles, Emojis, NoteEdits, Notes, Polls, UserProfiles,} from "@/models/index.js"; +import type {IMentionedRemoteUsers, Note} from "@/models/entities/note.js"; +import type {IObject, IPost} from "../type.js"; +import {getApId, getApType, getOneApHrefNullable, getOneApId, isEmoji, validPost,} from "../type.js"; +import type {Emoji} from "@/models/entities/emoji.js"; +import {genId} from "@/misc/gen-id.js"; +import {getApLock} from "@/misc/app-lock.js"; +import {parseAudience} from "../audience.js"; +import {extractApMentions} from "./mention.js"; import DbResolver from "../db-resolver.js"; -import { StatusError } from "@/misc/fetch.js"; -import { shouldBlockInstance } from "@/misc/should-block-instance.js"; -import { publishNoteStream } from "@/services/stream.js"; -import { extractHashtags } from "@/misc/extract-hashtags.js"; -import { UserProfiles } from "@/models/index.js"; -import { In } from "typeorm"; -import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; -import { truncate } from "@/misc/truncate.js"; -import { type Size, getEmojiSize } from "@/misc/emoji-meta.js"; -import { fetchMeta } from "@/misc/fetch-meta.js"; +import {StatusError} from "@/misc/fetch.js"; +import {shouldBlockInstance} from "@/misc/should-block-instance.js"; +import {publishNoteStream} from "@/services/stream.js"; +import {extractHashtags} from "@/misc/extract-hashtags.js"; +import {In} from "typeorm"; +import {DB_MAX_IMAGE_COMMENT_LENGTH} from "@/misc/hard-limits.js"; +import {truncate} from "@/misc/truncate.js"; +import {getEmojiSize, type Size} from "@/misc/emoji-meta.js"; +import {fetchMeta} from "@/misc/fetch-meta.js"; const logger = apLogger; @@ -185,7 +167,7 @@ export async function createNote( } const apMentions = await extractApMentions(note.tag); - const apHashtags = await extractApHashtags(note.tag); + const apHashtags = extractApHashtags(note.tag); // Attachments // TODO: attachmentは必ずしもImageではない diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b239ac497e..e0b66126a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: 5.2.0 version: 5.2.0 '@napi-rs/cli': - specifier: ^2.16.1 - version: 2.16.1 + specifier: ^2.16.3 + version: 2.16.3 js-yaml: specifier: 4.1.0 version: 4.1.0 @@ -307,8 +307,8 @@ importers: specifier: 7.5.1 version: 7.5.1 sharp: - specifier: 0.32.1 - version: 0.32.1 + specifier: 0.32.6 + version: 0.32.6 sonic-channel: specifier: ^1.3.1 version: 1.3.1 @@ -1126,8 +1126,8 @@ packages: dev: false optional: true - /@napi-rs/cli@2.16.1: - resolution: {integrity: sha512-L0Gr5iEQIDEbvWdDr1HUaBOxBSHL1VZhWSk1oryawoT8qJIY+KGfLFelU+Qma64ivCPbxYpkfPoKYVG3rcoGIA==} + /@napi-rs/cli@2.16.3: + resolution: {integrity: sha512-3mLNPlbbOhpbIUKicLrJtIearlHXUuXL3UeueYyRRplpVMNkdn8xCyzY6PcYZi3JXR8bmCOiWgkVmLnrSL7DKw==} engines: {node: '>= 10'} hasBin: true dev: false @@ -2382,7 +2382,7 @@ packages: /axios@0.24.0: resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.2 transitivePeerDependencies: - debug dev: false @@ -2390,11 +2390,15 @@ packages: /axios@0.25.0(debug@4.3.4): resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.3(debug@4.3.4) transitivePeerDependencies: - debug dev: true + /b4a@1.6.4: + resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} + dev: false + /babel-eslint@10.1.0(eslint@8.42.0): resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==} engines: {node: '>=6'} @@ -3352,6 +3356,11 @@ packages: engines: {node: '>=8'} dev: false + /detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + dev: false + /dezalgo@1.0.4: resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} dependencies: @@ -3821,6 +3830,10 @@ packages: /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + /fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + dev: false + /fast-glob@3.2.12: resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} engines: {node: '>=8.6.0'} @@ -3958,9 +3971,19 @@ packages: which: 1.3.1 dev: false - /follow-redirects@1.15.2(debug@4.3.4): + /follow-redirects@1.15.2: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /follow-redirects@1.15.3(debug@4.3.4): + resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + engines: {node: '>=4.0'} peerDependencies: debug: '*' peerDependenciesMeta: @@ -3968,6 +3991,7 @@ packages: optional: true dependencies: debug: 4.3.4 + dev: true /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -4727,8 +4751,8 @@ packages: engines: {node: '>= 0.6.0'} dev: false - /joi@17.9.2: - resolution: {integrity: sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==} + /joi@17.10.2: + resolution: {integrity: sha512-hcVhjBxRNW/is3nNLdGLIjkgXetkeGc2wyhydhz8KumG23Aerk4HPjU5zaPAMRqXQFc0xNqXTC7+zQjxr0GlKA==} dependencies: '@hapi/hoek': 9.3.0 '@hapi/topo': 5.1.0 @@ -5624,11 +5648,11 @@ packages: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: false - /node-abi@3.45.0: - resolution: {integrity: sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==} + /node-abi@3.47.0: + resolution: {integrity: sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==} engines: {node: '>=10'} dependencies: - semver: 7.5.1 + semver: 7.5.4 dev: false /node-addon-api@5.1.0: @@ -6149,13 +6173,13 @@ packages: engines: {node: '>=10'} hasBin: true dependencies: - detect-libc: 2.0.1 + detect-libc: 2.0.2 expand-template: 2.0.3 github-from-package: 0.0.0 minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 1.0.2 - node-abi: 3.45.0 + node-abi: 3.47.0 pump: 3.0.0 rc: 1.2.8 simple-get: 4.0.1 @@ -6292,6 +6316,10 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + /queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + dev: false + /quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -6537,7 +6565,7 @@ packages: /rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} dependencies: - tslib: 2.6.0 + tslib: 2.6.2 dev: true /safe-buffer@5.1.2: @@ -6625,6 +6653,14 @@ packages: dependencies: lru-cache: 6.0.0 + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + /serialize-javascript@6.0.1: resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} dependencies: @@ -6653,18 +6689,18 @@ packages: safe-buffer: 5.2.1 dev: false - /sharp@0.32.1: - resolution: {integrity: sha512-kQTFtj7ldpUqSe8kDxoGLZc1rnMFU0AO2pqbX6pLy3b7Oj8ivJIdoKNwxHVQG2HN6XpHPJqCSM2nsma2gOXvOg==} + /sharp@0.32.6: + resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} engines: {node: '>=14.15.0'} requiresBuild: true dependencies: color: 4.2.3 - detect-libc: 2.0.1 + detect-libc: 2.0.2 node-addon-api: 6.1.0 prebuild-install: 7.1.1 - semver: 7.5.1 + semver: 7.5.4 simple-get: 4.0.1 - tar-fs: 2.1.1 + tar-fs: 3.0.4 tunnel-agent: 0.6.0 dev: false @@ -6882,6 +6918,13 @@ packages: engines: {node: '>=10.0.0'} dev: false + /streamx@2.15.1: + resolution: {integrity: sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==} + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + dev: false + /strict-event-emitter-types@2.0.0: resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==} dev: true @@ -7046,6 +7089,14 @@ packages: tar-stream: 2.2.0 dev: false + /tar-fs@3.0.4: + resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} + dependencies: + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 3.1.6 + dev: false + /tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} @@ -7057,6 +7108,14 @@ packages: readable-stream: 3.6.2 dev: false + /tar-stream@3.1.6: + resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==} + dependencies: + b4a: 1.6.4 + fast-fifo: 1.3.2 + streamx: 2.15.1 + dev: false + /tar@6.1.15: resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} engines: {node: '>=10'} @@ -7270,8 +7329,8 @@ packages: resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} dev: false - /tslib@2.6.0: - resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: true /tsscmp@1.0.6: @@ -7574,7 +7633,7 @@ packages: hasBin: true dependencies: axios: 0.25.0(debug@4.3.4) - joi: 17.9.2 + joi: 17.10.2 lodash: 4.17.21 minimist: 1.2.8 rxjs: 7.8.1