diff --git a/.config/example.yml b/.config/example.yml index 900ac0905..02661b7fb 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -96,6 +96,9 @@ id: 'aid' # Max note length, should be < 8000. #maxNoteLength: 3000 +# Maximum lenght of an image caption or file comment (default 1500, max 8192) +#maxCaptionLength: 1500 + # Whether disable HSTS #disableHsts: true diff --git a/packages/backend/migration/1677935903517-DriveComment.js b/packages/backend/migration/1677935903517-DriveComment.js new file mode 100644 index 000000000..41c7556f0 --- /dev/null +++ b/packages/backend/migration/1677935903517-DriveComment.js @@ -0,0 +1,11 @@ +export class DriveComment1677935903517 { + name = 'DriveComment1677935903517' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "drive_file" ALTER "comment" TYPE character varying(8192)`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "drive_file" ALTER "comment" TYPE character varying(512)`); + } +} diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index e9c42c08f..ed9b0ece0 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -74,6 +74,7 @@ export type Source = { maxUserSignups?: number; isManagedHosting?: boolean; maxNoteLength?: number; + maxCaptionLength?: number; deepl: { managed?: boolean; authKey?: string; diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 82a093100..7e8f96444 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,7 +1,12 @@ import config from "@/config/index.js"; +import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; export const MAX_NOTE_TEXT_LENGTH = config.maxNoteLength != null ? config.maxNoteLength : 3000; // <- should we increase this? +export const MAX_CAPTION_TEXT_LENGTH = Math.min( + config.maxCaptionLength ?? 1500, + DB_MAX_IMAGE_COMMENT_LENGTH, +); export const SECOND = 1000; export const SEC = 1000; // why do we need this duplicate here? diff --git a/packages/backend/src/misc/hard-limits.ts b/packages/backend/src/misc/hard-limits.ts index 4ba90293c..51d2c0f5d 100644 --- a/packages/backend/src/misc/hard-limits.ts +++ b/packages/backend/src/misc/hard-limits.ts @@ -10,4 +10,4 @@ export const DB_MAX_NOTE_TEXT_LENGTH = 8192; * Maximum image description length that can be stored in DB. * Surrogate pairs count as one */ -export const DB_MAX_IMAGE_COMMENT_LENGTH = 512; +export const DB_MAX_IMAGE_COMMENT_LENGTH = 8192; diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index 1fa91b1a9..32e19bc6e 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -9,6 +9,7 @@ import { import { id } from "../id.js"; import { User } from "./user.js"; import { DriveFolder } from "./drive-folder.js"; +import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; @Entity() @Index(['userId', 'folderId', 'id']) @@ -69,7 +70,8 @@ export class DriveFile { public size: number; @Column('varchar', { - length: 512, nullable: true, + length: DB_MAX_IMAGE_COMMENT_LENGTH, + nullable: true, comment: 'The comment of the DriveFile.', }) public comment: string | null; diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 1808de118..c8c639f50 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -1,6 +1,6 @@ import config from "@/config/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; -import { MAX_NOTE_TEXT_LENGTH } from "@/const.js"; +import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js"; import define from "../../define.js"; export const meta = { @@ -86,6 +86,11 @@ export const meta = { optional: false, nullable: false, }, + maxCaptionTextLength: { + type: "number", + optional: false, + nullable: false, + }, emojis: { type: "array", optional: false, @@ -499,6 +504,7 @@ export default define(meta, paramDef, async (ps, me) => { backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため + maxCaptionTextLength: MAX_CAPTION_TEXT_LENGTH, defaultLightTheme: instance.defaultLightTheme, defaultDarkTheme: instance.defaultDarkTheme, enableEmail: instance.enableEmail, diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 476a0c29f..4dc1c941e 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -2,8 +2,7 @@ import { IsNull, MoreThan } from "typeorm"; import config from "@/config/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; import { Ads, Emojis, Users } from "@/models/index.js"; -import { DB_MAX_NOTE_TEXT_LENGTH } from "@/misc/hard-limits.js"; -import { MAX_NOTE_TEXT_LENGTH } from "@/const.js"; +import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js"; import define from "../define.js"; export const meta = { @@ -178,6 +177,11 @@ export const meta = { optional: false, nullable: false, }, + maxCaptionTextLength: { + type: "number", + optional: false, + nullable: false, + }, emojis: { type: "array", optional: false, @@ -456,6 +460,7 @@ export default define(meta, paramDef, async (ps, me) => { backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため + maxCaptionTextLength: MAX_CAPTION_TEXT_LENGTH, emojis: instance.privateMode && !me ? [] : await Emojis.packMany(emojis), defaultLightTheme: instance.defaultLightTheme, defaultDarkTheme: instance.defaultDarkTheme, diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts index a7fa0de4c..8563573d4 100644 --- a/packages/backend/src/server/nodeinfo.ts +++ b/packages/backend/src/server/nodeinfo.ts @@ -3,7 +3,7 @@ import config from "@/config/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; import { Users, Notes } from "@/models/index.js"; import { IsNull, MoreThan } from "typeorm"; -import { MAX_NOTE_TEXT_LENGTH } from "@/const.js"; +import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js"; import { Cache } from "@/misc/cache.js"; const router = new Router(); @@ -85,6 +85,7 @@ const nodeinfo2 = async () => { enableHcaptcha: meta.enableHcaptcha, enableRecaptcha: meta.enableRecaptcha, maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, + maxCaptionTextLength: MAX_CAPTION_TEXT_LENGTH, enableTwitterIntegration: meta.enableTwitterIntegration, enableGithubIntegration: meta.enableGithubIntegration, enableDiscordIntegration: meta.enableDiscordIntegration, diff --git a/packages/client/src/components/MkMediaCaption.vue b/packages/client/src/components/MkMediaCaption.vue index ff195974a..7168d8723 100644 --- a/packages/client/src/components/MkMediaCaption.vue +++ b/packages/client/src/components/MkMediaCaption.vue @@ -39,6 +39,7 @@ import MkButton from '@/components/MkButton.vue'; import bytes from '@/filters/bytes'; import number from '@/filters/number'; import { i18n } from '@/i18n'; +import { instance } from '@/instance'; export default defineComponent({ components: { @@ -87,8 +88,9 @@ export default defineComponent({ computed: { remainingLength(): number { - if (typeof this.inputValue !== "string") return 512; - return 512 - length(this.inputValue); + const maxCaptionLength = instance.maxCaptionTextLength ?? 512; + if (typeof this.inputValue !== "string") return maxCaptionLength; + return maxCaptionLength - length(this.inputValue); } },