From a62e4f1cf2c99150d345917c290f13e5a48ab92e Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Thu, 14 Nov 2024 19:32:08 -0500 Subject: [PATCH 1/4] ignore `isNSFW` for pure renotes --- packages/backend/src/core/NoteCreateService.ts | 9 ++++++++- packages/backend/src/core/NoteEditService.ts | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 1bc4599a60..ccc5bc0214 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -146,6 +146,8 @@ type Option = { app?: MiApp | null; }; +type PureRenoteOption = Option & { renote: MiNote } & ({ text?: null } | { cw?: null } | { reply?: null } | { poll?: null } | { files?: null | [] }); + @Injectable() export class NoteCreateService implements OnApplicationShutdown { #shutdownController = new AbortController(); @@ -412,7 +414,7 @@ export class NoteCreateService implements OnApplicationShutdown { if (user.host && !data.cw) { await this.federatedInstanceService.fetch(user.host).then(async i => { - if (i.isNSFW) { + if (i.isNSFW && !this.isPureRenote(data)) { data.cw = 'Instance is marked as NSFW'; } }); @@ -821,6 +823,11 @@ export class NoteCreateService implements OnApplicationShutdown { if (!user.noindex) this.index(note); } + @bindThis + private isPureRenote(note: Option): note is PureRenoteOption { + return this.isRenote(note) && !this.isQuote(note); + } + @bindThis private isRenote(note: Option): note is Option & { renote: MiNote } { return note.renote != null; diff --git a/packages/backend/src/core/NoteEditService.ts b/packages/backend/src/core/NoteEditService.ts index d31958e5d4..6c456fb4a3 100644 --- a/packages/backend/src/core/NoteEditService.ts +++ b/packages/backend/src/core/NoteEditService.ts @@ -142,6 +142,8 @@ type Option = { editcount?: boolean | null; }; +type PureRenoteOption = Option & { renote: MiNote } & ({ text?: null } | { cw?: null } | { reply?: null } | { poll?: null } | { files?: null | [] }); + @Injectable() export class NoteEditService implements OnApplicationShutdown { #shutdownController = new AbortController(); @@ -442,7 +444,7 @@ export class NoteEditService implements OnApplicationShutdown { if (user.host && !data.cw) { await this.federatedInstanceService.fetch(user.host).then(async i => { - if (i.isNSFW) { + if (i.isNSFW && !this.isPureRenote(data)) { data.cw = 'Instance is marked as NSFW'; } }); @@ -787,6 +789,11 @@ export class NoteEditService implements OnApplicationShutdown { if (!user.noindex) this.index(note); } + @bindThis + private isPureRenote(note: Option): note is PureRenoteOption { + return this.isRenote(note) && !this.isQuote(note); + } + @bindThis private isRenote(note: Option): note is Option & { renote: MiNote } { return note.renote != null; From eb1e32681345aaa6184a540c7dba9ae4fd5a6e77 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Thu, 14 Nov 2024 19:50:34 -0500 Subject: [PATCH 2/4] add script to fix hellspawns --- UPGRADE_NOTES.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/UPGRADE_NOTES.md b/UPGRADE_NOTES.md index 8bebd4eb34..fb81a611b7 100644 --- a/UPGRADE_NOTES.md +++ b/UPGRADE_NOTES.md @@ -1,5 +1,38 @@ # Upgrade Notes +## 2024.10.0 + +### Hellspawns + +Sharkey versions before 2024.10 suffered from a bug in the "Mark instance as NSFW" feature. +When a user from such an instance boosted a note, the boost would be converted to a hellspawn (pure renote with Content Warning). +Hellspawns are buggy and do not properly federate, so it may be desirable to correct any that already exist in the database. +The following script will correct any local or remote hellspawns in the database. + +```postgresql +/* Remove "instance is marked as NSFW" hellspawns */ +UPDATE note +SET cw = null +WHERE + "renoteId" IS NOT NULL + AND "text" IS NULL + AND cw = 'Instance is marked as NSFW' + AND "replyId" IS NULL + AND "hasPoll" = false + AND "fileIds" = '{}'; + +/* Fix legacy / user-created hellspawns */ +UPDATE note +SET text = '.' +WHERE + "renoteId" IS NOT NULL + AND "text" IS NULL + AND cw IS NOT NULL + AND "replyId" IS NULL + AND "hasPoll" = false + AND "fileIds" = '{}'; +``` + ## 2024.9.0 ### Following Feed From c9934c379fcaaf02511f7d3ba63be44306feb722 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sun, 17 Nov 2024 09:31:17 -0500 Subject: [PATCH 3/4] remove duplicate `isPureRenote` method --- packages/backend/src/core/NoteCreateService.ts | 4 ++-- packages/backend/src/core/NoteEditService.ts | 9 +-------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index ccc5bc0214..892a929c41 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -146,7 +146,7 @@ type Option = { app?: MiApp | null; }; -type PureRenoteOption = Option & { renote: MiNote } & ({ text?: null } | { cw?: null } | { reply?: null } | { poll?: null } | { files?: null | [] }); +export type PureRenoteOption = Option & { renote: MiNote } & ({ text?: null } | { cw?: null } | { reply?: null } | { poll?: null } | { files?: null | [] }); @Injectable() export class NoteCreateService implements OnApplicationShutdown { @@ -824,7 +824,7 @@ export class NoteCreateService implements OnApplicationShutdown { } @bindThis - private isPureRenote(note: Option): note is PureRenoteOption { + public isPureRenote(note: Option): note is PureRenoteOption { return this.isRenote(note) && !this.isQuote(note); } diff --git a/packages/backend/src/core/NoteEditService.ts b/packages/backend/src/core/NoteEditService.ts index 6c456fb4a3..e5e3c38cd3 100644 --- a/packages/backend/src/core/NoteEditService.ts +++ b/packages/backend/src/core/NoteEditService.ts @@ -142,8 +142,6 @@ type Option = { editcount?: boolean | null; }; -type PureRenoteOption = Option & { renote: MiNote } & ({ text?: null } | { cw?: null } | { reply?: null } | { poll?: null } | { files?: null | [] }); - @Injectable() export class NoteEditService implements OnApplicationShutdown { #shutdownController = new AbortController(); @@ -444,7 +442,7 @@ export class NoteEditService implements OnApplicationShutdown { if (user.host && !data.cw) { await this.federatedInstanceService.fetch(user.host).then(async i => { - if (i.isNSFW && !this.isPureRenote(data)) { + if (i.isNSFW && !this.noteCreateService.isPureRenote(data)) { data.cw = 'Instance is marked as NSFW'; } }); @@ -789,11 +787,6 @@ export class NoteEditService implements OnApplicationShutdown { if (!user.noindex) this.index(note); } - @bindThis - private isPureRenote(note: Option): note is PureRenoteOption { - return this.isRenote(note) && !this.isQuote(note); - } - @bindThis private isRenote(note: Option): note is Option & { renote: MiNote } { return note.renote != null; From cc394d9a4bd560097ddfa7c4d11f7abe9a993fa8 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sun, 17 Nov 2024 09:32:13 -0500 Subject: [PATCH 4/4] quote all symbols in hellspawn upgrade script --- UPGRADE_NOTES.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/UPGRADE_NOTES.md b/UPGRADE_NOTES.md index fb81a611b7..c941de6643 100644 --- a/UPGRADE_NOTES.md +++ b/UPGRADE_NOTES.md @@ -11,23 +11,23 @@ The following script will correct any local or remote hellspawns in the database ```postgresql /* Remove "instance is marked as NSFW" hellspawns */ -UPDATE note -SET cw = null +UPDATE "note" +SET "cw" = null WHERE "renoteId" IS NOT NULL AND "text" IS NULL - AND cw = 'Instance is marked as NSFW' + AND "cw" = 'Instance is marked as NSFW' AND "replyId" IS NULL AND "hasPoll" = false AND "fileIds" = '{}'; /* Fix legacy / user-created hellspawns */ -UPDATE note -SET text = '.' +UPDATE "note" +SET "text" = '.' WHERE "renoteId" IS NOT NULL AND "text" IS NULL - AND cw IS NOT NULL + AND "cw" IS NOT NULL AND "replyId" IS NULL AND "hasPoll" = false AND "fileIds" = '{}';