From 498eef8c7639d890f479839d7e17758a7b8146ca Mon Sep 17 00:00:00 2001 From: askmeaboutloom Date: Mon, 22 Jul 2024 13:04:24 +0200 Subject: [PATCH] Fix description length validation and tag limiting The validation functions would get passed the raw description as entered by the user and would make some half-hearted effort to parse them into something sensible, but this completely breaks down in the face of shortcuts like {default}, username shortcuts that get turned into long links etc. Now those functions get the actually parsed description passed to them, the only unresolved shortcut in them being the `{tags}` one, since the length of that is variable and up to the validation function to deal with and tell the user if tags didn't fit. Since #286, tags insertion is also pretty much busted entirely, since it runs at the wrong time, so it may insert too many tags and then cause an error down the line because the resulting description is too long. That insertion logic has now been moved to the end of the description processing, where it belongs. --- .../submission/parser/parser.service.ts | 19 ++++++--- .../section-parsers/description.parser.ts | 34 +++++++++++----- .../server/submission/submission.service.ts | 2 +- .../submission/validator/validator.module.ts | 3 +- .../submission/validator/validator.service.ts | 40 ++++++++++++++----- .../websites/artconomy/artconomy.service.ts | 6 +-- .../server/websites/aryion/aryion.service.ts | 1 + .../websites/bluesky/bluesky.service.ts | 13 +++--- .../server/websites/custom/custom.service.ts | 1 + .../websites/derpibooru/derpibooru.service.ts | 1 + .../deviant-art/deviant-art.service.ts | 1 + .../websites/discord/discord.service.ts | 14 ++----- .../src/server/websites/e621/e621.service.ts | 1 + .../fur-affinity/fur-affinity.service.ts | 1 + .../websites/furbooru/furbooru.service.ts | 1 + .../furry-network/furry-network.service.ts | 2 + .../websites/furtastic/furtastic.service.ts | 1 + .../hentai-foundry/hentai-foundry.service.ts | 1 + .../websites/inkbunny/inkbunny.service.ts | 1 + .../server/websites/itaku/itaku.service.ts | 23 +++-------- .../server/websites/ko-fi/ko-fi.service.ts | 1 + .../websites/manebooru/manebooru.service.ts | 1 + .../websites/megalodon/megalodon.service.ts | 22 +++------- .../websites/misskey/misskey.service.ts | 13 ++---- .../websites/newgrounds/newgrounds.service.ts | 1 + .../websites/patreon/patreon.service.ts | 2 + .../websites/picarto/picarto.service.ts | 1 + .../server/websites/piczel/piczel.service.ts | 1 + .../websites/pillowfort/pillowfort.service.ts | 1 + .../server/websites/pixiv/pixiv.service.ts | 1 + .../websites/so-furry/so-furry.service.ts | 1 + .../subscribe-star-adult.service.ts | 2 + .../subscribe-star/subscribe-star.service.ts | 2 + .../websites/telegram/telegram.service.ts | 9 ++--- .../server/websites/tumblr/tumblr.service.ts | 2 + .../websites/twitter/twitter.service.ts | 16 ++------ .../server/websites/weasyl/weasyl.service.ts | 1 + .../src/server/websites/website.base.ts | 23 ++++++----- 38 files changed, 150 insertions(+), 116 deletions(-) diff --git a/electron-app/src/server/submission/parser/parser.service.ts b/electron-app/src/server/submission/parser/parser.service.ts index c7ebc692..4712ddf2 100644 --- a/electron-app/src/server/submission/parser/parser.service.ts +++ b/electron-app/src/server/submission/parser/parser.service.ts @@ -14,6 +14,7 @@ import { Submission, FileSubmission, FileRecord, + SubmissionPart, } from 'postybirb-commons'; import { ScalingOptions } from 'src/server/websites/interfaces/scaling-options.interface'; import { PostData } from '../post/interfaces/post-data.interface'; @@ -42,7 +43,12 @@ export class ParserService { private readonly fileManipulator: FileManipulationService, websitesService: WebsitesService, ) { - this.descriptionParser = new DescriptionParser(customShortcuts, websitesService, settings, this); + this.descriptionParser = new DescriptionParser( + customShortcuts, + websitesService, + settings, + this, + ); } public async parse( @@ -86,17 +92,18 @@ export class ParserService { public async parseDescription( website: Website, - defaultPart: SubmissionPartEntity, - websitePart: SubmissionPartEntity, + defaultPart: SubmissionPart, + websitePart: SubmissionPart, type: SubmissionType, + generateTags: boolean = true, ): Promise { - return this.descriptionParser.parse(website, defaultPart, websitePart, type); + return this.descriptionParser.parse(website, defaultPart, websitePart, type, generateTags); } public async parseTags( website: Website, - defaultPart: SubmissionPartEntity, - websitePart: SubmissionPartEntity, + defaultPart: SubmissionPart, + websitePart: SubmissionPart, ): Promise { let tags = _.uniq(FormContent.getTags(defaultPart.data.tags, websitePart.data.tags)); if (tags.length) { diff --git a/electron-app/src/server/submission/parser/section-parsers/description.parser.ts b/electron-app/src/server/submission/parser/section-parsers/description.parser.ts index b43562f3..58b733ee 100644 --- a/electron-app/src/server/submission/parser/section-parsers/description.parser.ts +++ b/electron-app/src/server/submission/parser/section-parsers/description.parser.ts @@ -1,4 +1,9 @@ -import { DefaultOptions, SubmissionType, UsernameShortcut } from 'postybirb-commons'; +import { + DefaultOptions, + SubmissionPart, + SubmissionType, + UsernameShortcut, +} from 'postybirb-commons'; import { CustomShortcutService } from 'src/server/custom-shortcut/custom-shortcut.service'; import { HTMLFormatParser } from 'src/server/description-parsing/html/html.parser'; import { AdInsertParser } from 'src/server/description-parsing/miscellaneous/ad.parser'; @@ -43,9 +48,10 @@ export class DescriptionParser { public async parse( website: Website, - defaultPart: SubmissionPartEntity, - websitePart: SubmissionPartEntity, + defaultPart: SubmissionPart, + websitePart: SubmissionPart, type: SubmissionType, + generateTags: boolean = true, ): Promise { let description = FormContent.getDescription( defaultPart.data.description, @@ -53,8 +59,7 @@ export class DescriptionParser { ).trim(); if (description.length) { - // Insert {default}, {title}, {tags}, {cw} shortcuts - let tags = await this.parserService.parseTags(website, defaultPart, websitePart); + // Insert {default}, {title}, {cw} shortcuts description = this.insertDefaultShortcuts(description, [ { name: 'default', @@ -64,10 +69,6 @@ export class DescriptionParser { name: 'title', content: defaultPart.data.title ?? websitePart.data.title ?? '', }, - { - name: 'tags', - content: website.generateTagsString(tags, description, websitePart), - }, { name: 'cw', content: FormContent.getSpoilerText(defaultPart.data, websitePart.data), @@ -108,6 +109,21 @@ export class DescriptionParser { } description = website.postParseDescription(description, type); + + // Insert {tags} shortcut if desired. Happens at the end, since tags will + // get cut off if they're too long instead of failing the submission. In + // case we're validating, we leave the shortcut standing, since the + // validation code will act upon its presence. + if (generateTags) { + const tags = await this.parserService.parseTags(website, defaultPart, websitePart); + description = this.insertDefaultShortcuts(description, [ + { + name: 'tags', + content: website.generateTagsString(tags, description, websitePart), + }, + ]); + } + return description.trim(); } diff --git a/electron-app/src/server/submission/submission.service.ts b/electron-app/src/server/submission/submission.service.ts index a5403db3..8c3f2e23 100644 --- a/electron-app/src/server/submission/submission.service.ts +++ b/electron-app/src/server/submission/submission.service.ts @@ -477,7 +477,7 @@ export class SubmissionService { let hasProblems: boolean = false; const parts = await this.partService.getPartsForSubmission(submission._id, true); const problems: Problems = parts.length - ? this.validatorService.validateParts(submission, parts) + ? await this.validatorService.validateParts(submission, parts) : {}; for (const p of Object.values(problems)) { if (p.problems.length) { diff --git a/electron-app/src/server/submission/validator/validator.module.ts b/electron-app/src/server/submission/validator/validator.module.ts index 5ef7238f..87e5c450 100644 --- a/electron-app/src/server/submission/validator/validator.module.ts +++ b/electron-app/src/server/submission/validator/validator.module.ts @@ -1,9 +1,10 @@ import { Module } from '@nestjs/common'; import { ValidatorService } from './validator.service'; import { WebsitesModule } from 'src/server/websites/websites.module'; +import { ParserModule } from '../parser/parser.module'; @Module({ - imports: [WebsitesModule], + imports: [WebsitesModule, ParserModule], providers: [ValidatorService], exports: [ValidatorService], }) diff --git a/electron-app/src/server/submission/validator/validator.service.ts b/electron-app/src/server/submission/validator/validator.service.ts index 1807c320..97936043 100644 --- a/electron-app/src/server/submission/validator/validator.service.ts +++ b/electron-app/src/server/submission/validator/validator.service.ts @@ -9,23 +9,30 @@ import { SubmissionType } from 'postybirb-commons'; import { ValidationParts } from './interfaces/validation-parts.interface'; import { Website } from 'src/server/websites/website.base'; import FileSubmissionEntity from '../file-submission/models/file-submission.entity'; +import { ParserService } from '../parser/parser.service'; @Injectable() export class ValidatorService { - constructor(private readonly websiteProvider: WebsiteProvider) {} + constructor( + private readonly websiteProvider: WebsiteProvider, + private readonly parserService: ParserService, + ) {} - validateParts(submission: Submission, parts: Array>): Problems { + async validateParts( + submission: Submission, + parts: Array>, + ): Promise { const defaultPart: SubmissionPart = parts.find(p => p.isDefault); const websiteProblems: Problems = {}; - parts - .filter(p => !p.isDefault) - .forEach(p => { + for (const p of parts) { + if (!p.isDefault) { websiteProblems[p.accountId] = { - ...this.validatePart(submission, p, defaultPart), + ...(await this.validatePart(submission, p, defaultPart)), website: p.website, accountId: p.accountId, }; - }); + } + } return { [defaultPart.accountId]: { @@ -37,22 +44,35 @@ export class ValidatorService { }; } - private validatePart( + private async validatePart( submission: Submission, part: SubmissionPart, defaultPart: SubmissionPart, - ): ValidationParts { + ): Promise { const website: Website = this.websiteProvider.getWebsiteModule(part.website); const parsedPart = this.parsePart(part, defaultPart); + const description = await this.parserService.parseDescription( + website, + defaultPart, + part, + submission.type, + false, + ); switch (submission.type) { case SubmissionType.FILE: return website.validateFileSubmission( submission as FileSubmissionEntity, parsedPart, defaultPart, + description, ); case SubmissionType.NOTIFICATION: - return website.validateNotificationSubmission(submission, parsedPart, defaultPart); + return website.validateNotificationSubmission( + submission, + parsedPart, + defaultPart, + description, + ); } } diff --git a/electron-app/src/server/websites/artconomy/artconomy.service.ts b/electron-app/src/server/websites/artconomy/artconomy.service.ts index 60b98af9..3137f150 100644 --- a/electron-app/src/server/websites/artconomy/artconomy.service.ts +++ b/electron-app/src/server/websites/artconomy/artconomy.service.ts @@ -225,6 +225,7 @@ export class Artconomy extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -252,11 +253,8 @@ export class Artconomy extends Website { 'relationships depicted', ); } - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ) - if (description.length > this.MAX_CHARS) { + if (this.stripTagsShortcut(description).length > this.MAX_CHARS) { problems.push('Description must be 2000 characters or fewer.') } diff --git a/electron-app/src/server/websites/aryion/aryion.service.ts b/electron-app/src/server/websites/aryion/aryion.service.ts index 88004c6a..ca0b2edd 100644 --- a/electron-app/src/server/websites/aryion/aryion.service.ts +++ b/electron-app/src/server/websites/aryion/aryion.service.ts @@ -163,6 +163,7 @@ export class Aryion extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/bluesky/bluesky.service.ts b/electron-app/src/server/websites/bluesky/bluesky.service.ts index 770bfdd2..71260d40 100644 --- a/electron-app/src/server/websites/bluesky/bluesky.service.ts +++ b/electron-app/src/server/websites/bluesky/bluesky.service.ts @@ -384,6 +384,7 @@ export class Bluesky extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -404,7 +405,7 @@ export class Bluesky extends Website { this.validateRating(submissionPart, defaultPart, warnings); - this.validateDescription(problems, warnings, submissionPart, defaultPart); + this.validateDescription(problems, warnings, submissionPart, defaultPart, description); files.forEach(file => { const { type, size, name, mimetype } = file; @@ -450,11 +451,12 @@ export class Bluesky extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; - this.validateDescription(problems, warnings, submissionPart, defaultPart); + this.validateDescription(problems, warnings, submissionPart, defaultPart, description); this.validateReplyToUrl(problems, submissionPart.data.replyToUrl); this.validateRating(submissionPart, defaultPart, warnings); @@ -487,12 +489,9 @@ export class Bluesky extends Website { warnings: string[], submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): void { - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); - - const rt = new RichText({ text: description }); + const rt = new RichText({ text: this.stripTagsShortcut(description) }); const agent = new BskyAgent({ service: 'https://bsky.social' }); rt.detectFacets(agent); diff --git a/electron-app/src/server/websites/custom/custom.service.ts b/electron-app/src/server/websites/custom/custom.service.ts index c705691e..fb759a04 100644 --- a/electron-app/src/server/websites/custom/custom.service.ts +++ b/electron-app/src/server/websites/custom/custom.service.ts @@ -151,6 +151,7 @@ export class Custom extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/derpibooru/derpibooru.service.ts b/electron-app/src/server/websites/derpibooru/derpibooru.service.ts index 575fb0d5..093e8779 100644 --- a/electron-app/src/server/websites/derpibooru/derpibooru.service.ts +++ b/electron-app/src/server/websites/derpibooru/derpibooru.service.ts @@ -145,6 +145,7 @@ export class Derpibooru extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/deviant-art/deviant-art.service.ts b/electron-app/src/server/websites/deviant-art/deviant-art.service.ts index 555815ae..4053dc62 100644 --- a/electron-app/src/server/websites/deviant-art/deviant-art.service.ts +++ b/electron-app/src/server/websites/deviant-art/deviant-art.service.ts @@ -343,6 +343,7 @@ export class DeviantArt extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/discord/discord.service.ts b/electron-app/src/server/websites/discord/discord.service.ts index 217fc4fe..4cd92614 100644 --- a/electron-app/src/server/websites/discord/discord.service.ts +++ b/electron-app/src/server/websites/discord/discord.service.ts @@ -138,6 +138,7 @@ export class Discord extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -160,11 +161,7 @@ export class Discord extends Website { } }); - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); - - if (description.length > this.MAX_CHARS) { + if (this.stripTagsShortcut(description).length > this.MAX_CHARS) { warnings.push('Max description length allowed is 2,000 characters.'); } @@ -175,15 +172,12 @@ export class Discord extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); - - if (description.length > this.MAX_CHARS) { + if (this.stripTagsShortcut(description).length > this.MAX_CHARS) { warnings.push('Max description length allowed is 2,000 characters.'); } diff --git a/electron-app/src/server/websites/e621/e621.service.ts b/electron-app/src/server/websites/e621/e621.service.ts index 1cd2c1b6..dc1bcbe1 100644 --- a/electron-app/src/server/websites/e621/e621.service.ts +++ b/electron-app/src/server/websites/e621/e621.service.ts @@ -154,6 +154,7 @@ export class e621 extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/fur-affinity/fur-affinity.service.ts b/electron-app/src/server/websites/fur-affinity/fur-affinity.service.ts index a2faa3d9..fccdcb13 100644 --- a/electron-app/src/server/websites/fur-affinity/fur-affinity.service.ts +++ b/electron-app/src/server/websites/fur-affinity/fur-affinity.service.ts @@ -350,6 +350,7 @@ export class FurAffinity extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/furbooru/furbooru.service.ts b/electron-app/src/server/websites/furbooru/furbooru.service.ts index 0565bd13..0f521583 100644 --- a/electron-app/src/server/websites/furbooru/furbooru.service.ts +++ b/electron-app/src/server/websites/furbooru/furbooru.service.ts @@ -145,6 +145,7 @@ export class Furbooru extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/furry-network/furry-network.service.ts b/electron-app/src/server/websites/furry-network/furry-network.service.ts index f3057bd8..73945106 100644 --- a/electron-app/src/server/websites/furry-network/furry-network.service.ts +++ b/electron-app/src/server/websites/furry-network/furry-network.service.ts @@ -442,6 +442,7 @@ export class FurryNetwork extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -506,6 +507,7 @@ export class FurryNetwork extends Website { submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems = []; const warnings = []; diff --git a/electron-app/src/server/websites/furtastic/furtastic.service.ts b/electron-app/src/server/websites/furtastic/furtastic.service.ts index 81306bbb..79f688b0 100644 --- a/electron-app/src/server/websites/furtastic/furtastic.service.ts +++ b/electron-app/src/server/websites/furtastic/furtastic.service.ts @@ -125,6 +125,7 @@ export class Furtastic extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/hentai-foundry/hentai-foundry.service.ts b/electron-app/src/server/websites/hentai-foundry/hentai-foundry.service.ts index ef5baa9d..02bec5f7 100644 --- a/electron-app/src/server/websites/hentai-foundry/hentai-foundry.service.ts +++ b/electron-app/src/server/websites/hentai-foundry/hentai-foundry.service.ts @@ -160,6 +160,7 @@ export class HentaiFoundry extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/inkbunny/inkbunny.service.ts b/electron-app/src/server/websites/inkbunny/inkbunny.service.ts index a33f1944..20be8fc8 100644 --- a/electron-app/src/server/websites/inkbunny/inkbunny.service.ts +++ b/electron-app/src/server/websites/inkbunny/inkbunny.service.ts @@ -227,6 +227,7 @@ export class Inkbunny extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/itaku/itaku.service.ts b/electron-app/src/server/websites/itaku/itaku.service.ts index b5bcbc55..b4fe60a0 100644 --- a/electron-app/src/server/websites/itaku/itaku.service.ts +++ b/electron-app/src/server/websites/itaku/itaku.service.ts @@ -258,18 +258,13 @@ export class Itaku extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); - - if (description.length > this.MAX_CHARS) { - problems.push( - `Max description length allowed is 5000 characters.`, - ); + if (this.stripTagsShortcut(description).length > this.MAX_CHARS) { + problems.push(`Max description length allowed is 5000 characters.`); } if (FormContent.getTags(defaultPart.data.tags, submissionPart.data.tags).length < 5) { @@ -304,23 +299,17 @@ export class Itaku extends Website { submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; - const description = PlaintextParser.parse( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - 23, - ); - if (!description) { problems.push('Description required'); } - if (description.length > this.MAX_CHARS) { - problems.push( - `Max description length allowed is 5000 characters.`, - ); + if (this.stripTagsShortcut(description).length > this.MAX_CHARS) { + problems.push(`Max description length allowed is 5000 characters.`); } return { problems, warnings }; diff --git a/electron-app/src/server/websites/ko-fi/ko-fi.service.ts b/electron-app/src/server/websites/ko-fi/ko-fi.service.ts index a23fe54e..8b9a06cf 100644 --- a/electron-app/src/server/websites/ko-fi/ko-fi.service.ts +++ b/electron-app/src/server/websites/ko-fi/ko-fi.service.ts @@ -168,6 +168,7 @@ export class KoFi extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/manebooru/manebooru.service.ts b/electron-app/src/server/websites/manebooru/manebooru.service.ts index 22c7380e..c1447ffd 100644 --- a/electron-app/src/server/websites/manebooru/manebooru.service.ts +++ b/electron-app/src/server/websites/manebooru/manebooru.service.ts @@ -145,6 +145,7 @@ export class Manebooru extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/megalodon/megalodon.service.ts b/electron-app/src/server/websites/megalodon/megalodon.service.ts index d7bfcca0..8fa89b01 100644 --- a/electron-app/src/server/websites/megalodon/megalodon.service.ts +++ b/electron-app/src/server/websites/megalodon/megalodon.service.ts @@ -229,6 +229,7 @@ export abstract class Megalodon extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const instanceSettings = this.getInstanceSettings(submissionPart.accountId); @@ -236,14 +237,8 @@ export abstract class Megalodon extends Website { const warnings: string[] = []; const isAutoscaling: boolean = submissionPart.data.autoScale; - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); - - if (description.length > instanceSettings.maxChars) { - warnings.push( - `Max description length allowed is ${instanceSettings.maxChars} characters.`, - ); + if (this.stripTagsShortcut(description).length > instanceSettings.maxChars) { + warnings.push(`Max description length allowed is ${instanceSettings.maxChars} characters.`); } else { if (description.toLowerCase().indexOf('{tags}') > -1) { this.validateInsertTags( @@ -321,20 +316,15 @@ export abstract class Megalodon extends Website { submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const instanceSettings = this.getInstanceSettings(submissionPart.accountId); const problems = []; const warnings = []; - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); - - if (description.length > instanceSettings.maxChars) { - warnings.push( - `Max description length allowed is ${instanceSettings.maxChars} characters.`, - ); + if (this.stripTagsShortcut(description).length > instanceSettings.maxChars) { + warnings.push(`Max description length allowed is ${instanceSettings.maxChars} characters.`); } else { this.validateInsertTags( warnings, diff --git a/electron-app/src/server/websites/misskey/misskey.service.ts b/electron-app/src/server/websites/misskey/misskey.service.ts index fd2c7847..fc29b3ea 100644 --- a/electron-app/src/server/websites/misskey/misskey.service.ts +++ b/electron-app/src/server/websites/misskey/misskey.service.ts @@ -228,19 +228,16 @@ export class MissKey extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; const isAutoscaling: boolean = submissionPart.data.autoScale; - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); - const instanceInfo: MissKeyInstanceInfo = this.getAccountInfo(submissionPart.accountId, INFO_KEY); const maxChars = instanceInfo?.configuration?.statuses?.max_characters ?? 500; - if (description.length > maxChars) { + if (this.stripTagsShortcut(description).length > maxChars) { warnings.push( `Max description length allowed is ${maxChars} characters (for this MissKey client).`, ); @@ -310,15 +307,13 @@ export class MissKey extends Website { submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const warnings = []; - const description = this.defaultDescriptionParser( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); const instanceInfo: MissKeyInstanceInfo = this.getAccountInfo(submissionPart.accountId, INFO_KEY); const maxChars = instanceInfo?.configuration?.statuses?.max_characters ?? 500; - if (description.length > maxChars) { + if (this.stripTagsShortcut(description).length > maxChars) { warnings.push( `Max description length allowed is ${maxChars} characters (for this MissKey client).`, ); diff --git a/electron-app/src/server/websites/newgrounds/newgrounds.service.ts b/electron-app/src/server/websites/newgrounds/newgrounds.service.ts index 5cb9a53d..2ede5524 100644 --- a/electron-app/src/server/websites/newgrounds/newgrounds.service.ts +++ b/electron-app/src/server/websites/newgrounds/newgrounds.service.ts @@ -364,6 +364,7 @@ export class Newgrounds extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/patreon/patreon.service.ts b/electron-app/src/server/websites/patreon/patreon.service.ts index 94b2c42c..5a3998d6 100644 --- a/electron-app/src/server/websites/patreon/patreon.service.ts +++ b/electron-app/src/server/websites/patreon/patreon.service.ts @@ -643,6 +643,7 @@ export class Patreon extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -690,6 +691,7 @@ export class Patreon extends Website { submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems = []; const warnings = []; diff --git a/electron-app/src/server/websites/picarto/picarto.service.ts b/electron-app/src/server/websites/picarto/picarto.service.ts index e08db10b..8345f4f6 100644 --- a/electron-app/src/server/websites/picarto/picarto.service.ts +++ b/electron-app/src/server/websites/picarto/picarto.service.ts @@ -268,6 +268,7 @@ export class Picarto extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/piczel/piczel.service.ts b/electron-app/src/server/websites/piczel/piczel.service.ts index 184cccaf..12d0ac5d 100644 --- a/electron-app/src/server/websites/piczel/piczel.service.ts +++ b/electron-app/src/server/websites/piczel/piczel.service.ts @@ -148,6 +148,7 @@ export class Piczel extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/pillowfort/pillowfort.service.ts b/electron-app/src/server/websites/pillowfort/pillowfort.service.ts index 1030066d..22266fe0 100644 --- a/electron-app/src/server/websites/pillowfort/pillowfort.service.ts +++ b/electron-app/src/server/websites/pillowfort/pillowfort.service.ts @@ -196,6 +196,7 @@ export class Pillowfort extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/pixiv/pixiv.service.ts b/electron-app/src/server/websites/pixiv/pixiv.service.ts index d7074c2e..d3ef04e2 100644 --- a/electron-app/src/server/websites/pixiv/pixiv.service.ts +++ b/electron-app/src/server/websites/pixiv/pixiv.service.ts @@ -310,6 +310,7 @@ export class Pixiv extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/so-furry/so-furry.service.ts b/electron-app/src/server/websites/so-furry/so-furry.service.ts index 9faa1017..cc3a1616 100644 --- a/electron-app/src/server/websites/so-furry/so-furry.service.ts +++ b/electron-app/src/server/websites/so-furry/so-furry.service.ts @@ -211,6 +211,7 @@ export class SoFurry extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/subscribe-star-adult/subscribe-star-adult.service.ts b/electron-app/src/server/websites/subscribe-star-adult/subscribe-star-adult.service.ts index 746397ab..f52df486 100644 --- a/electron-app/src/server/websites/subscribe-star-adult/subscribe-star-adult.service.ts +++ b/electron-app/src/server/websites/subscribe-star-adult/subscribe-star-adult.service.ts @@ -360,6 +360,7 @@ export class SubscribeStarAdult extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -420,6 +421,7 @@ export class SubscribeStarAdult extends Website { submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/subscribe-star/subscribe-star.service.ts b/electron-app/src/server/websites/subscribe-star/subscribe-star.service.ts index 7aeefe33..b7fec76f 100644 --- a/electron-app/src/server/websites/subscribe-star/subscribe-star.service.ts +++ b/electron-app/src/server/websites/subscribe-star/subscribe-star.service.ts @@ -348,6 +348,7 @@ export class SubscribeStar extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -408,6 +409,7 @@ export class SubscribeStar extends Website { submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/telegram/telegram.service.ts b/electron-app/src/server/websites/telegram/telegram.service.ts index 8b516c28..f1851710 100644 --- a/electron-app/src/server/websites/telegram/telegram.service.ts +++ b/electron-app/src/server/websites/telegram/telegram.service.ts @@ -513,6 +513,7 @@ export class Telegram extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -533,11 +534,9 @@ export class Telegram extends Website { problems.push('No channel(s) selected.'); } - const { description } = TelegramDescription.fromHTML( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - ); - - if (description.length > 4096) { + if ( + TelegramDescription.fromHTML(this.stripTagsShortcut(description)).description.length > 4096 + ) { warnings.push('Max description length allowed is 4,096 characters.'); } diff --git a/electron-app/src/server/websites/tumblr/tumblr.service.ts b/electron-app/src/server/websites/tumblr/tumblr.service.ts index f836c812..fa05a418 100644 --- a/electron-app/src/server/websites/tumblr/tumblr.service.ts +++ b/electron-app/src/server/websites/tumblr/tumblr.service.ts @@ -158,6 +158,7 @@ export class Tumblr extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; @@ -211,6 +212,7 @@ export class Tumblr extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/twitter/twitter.service.ts b/electron-app/src/server/websites/twitter/twitter.service.ts index 51918c9b..39acaa2c 100644 --- a/electron-app/src/server/websites/twitter/twitter.service.ts +++ b/electron-app/src/server/websites/twitter/twitter.service.ts @@ -142,17 +142,13 @@ export class Twitter extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; const isAutoscaling: boolean = submissionPart.data.autoScale; - const description = PlaintextParser.parse( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - 23, - ); - - if (description.length > 280) { + if (this.stripTagsShortcut(description).length > 280) { warnings.push( `Approximated description may surpass 280 character limit (${description.length})`, ); @@ -207,15 +203,11 @@ export class Twitter extends Website { submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const warnings = []; - const description = PlaintextParser.parse( - FormContent.getDescription(defaultPart.data.description, submissionPart.data.description), - 23, - ); - - if (description.length > 280) { + if (this.stripTagsShortcut(description).length > 280) { warnings.push( `Approximated description may surpass 280 character limit (${description.length})`, ); diff --git a/electron-app/src/server/websites/weasyl/weasyl.service.ts b/electron-app/src/server/websites/weasyl/weasyl.service.ts index 197b50bb..926fb873 100644 --- a/electron-app/src/server/websites/weasyl/weasyl.service.ts +++ b/electron-app/src/server/websites/weasyl/weasyl.service.ts @@ -320,6 +320,7 @@ export class Weasyl extends Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { const problems: string[] = []; const warnings: string[] = []; diff --git a/electron-app/src/server/websites/website.base.ts b/electron-app/src/server/websites/website.base.ts index c0665683..37ea61f5 100644 --- a/electron-app/src/server/websites/website.base.ts +++ b/electron-app/src/server/websites/website.base.ts @@ -27,6 +27,7 @@ import { LoginResponse } from './interfaces/login-response.interface'; import { ScalingOptions } from './interfaces/scaling-options.interface'; import SubmissionPartEntity from '../submission/submission-part/models/submission-part.entity'; import { HttpResponse as ExperimentalHttpResponse } from 'src/server/utils/http-experimental'; +import { DescriptionParser } from '../submission/parser/section-parsers/description.parser'; interface TagParseOptions { spaceReplacer: string; @@ -166,7 +167,7 @@ export abstract class Website { generateTagsString( tags: string[], description: string, - websitePart: SubmissionPartEntity, + websitePart: SubmissionPart, ): string { const { includedTags } = this.calculateFittingTags(tags, description, this.MAX_CHARS); const formattedTags = this.formatTags(includedTags); @@ -189,17 +190,13 @@ export abstract class Website { ): { includedTags: string[]; skippedTags: string[] } { const includedTags = []; const skippedTags = []; - const appendToDescription = function (tag?: string): string { - const suffix = tag ? [...includedTags, tag] : includedTags; - if (suffix.length === 0) { - return description; - } else { - return description + '\n\n' + suffix.join(' '); - } + const insertIntoDescription = function (tag?: string): string { + const insertion = tag ? [...includedTags, tag] : includedTags; + return description.replace('{tags}', insertion.join(' ')); }; for (const tag of tags) { - if (getLength(appendToDescription(tag)) <= limit) { + if (getLength(insertIntoDescription(tag)) <= limit) { includedTags.push(tag); } else { skippedTags.push(tag); @@ -223,6 +220,12 @@ export abstract class Website { return text || ''; } + protected stripTagsShortcut(description: string): string { + return description.indexOf('{tags}') === -1 + ? description + : description.replace('{tags}', '').trim(); + } + protected storeAccountInformation(profileId: string, key: string, value: any): void { this.accountInformation.set(profileId, { ...this.accountInformation.get(profileId), @@ -238,12 +241,14 @@ export abstract class Website { submission: FileSubmission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts; validateNotificationSubmission( submission: Submission, submissionPart: SubmissionPart, defaultPart: SubmissionPart, + description: string, ): ValidationParts { return { problems: [], warnings: [] }; }