diff --git a/UPGRADE_NOTES.md b/UPGRADE_NOTES.md index 8bebd4eb34790dffea739fde66b1daa7864116c8..c941de6643d54bda49136dec6876e5188b0a3894 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 diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 1bc4599a602200a1bede36d9381aed4e04400188..892a929c41549c8a6a432148a1b30e3b4c0f6b77 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -146,6 +146,8 @@ type Option = { app?: MiApp | null; }; +export 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 + public 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 d31958e5d4abd3ac2ce5757d2e5b94377b94d009..e5e3c38cd3f057cd1d2a1175cd9b20d4ea46ab61 100644 --- a/packages/backend/src/core/NoteEditService.ts +++ b/packages/backend/src/core/NoteEditService.ts @@ -442,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) { + if (i.isNSFW && !this.noteCreateService.isPureRenote(data)) { data.cw = 'Instance is marked as NSFW'; } });