From 01a5300be88665ae414c15e8e0667c93799d8f0e Mon Sep 17 00:00:00 2001
From: dakkar
Date: Sat, 18 Jan 2025 12:51:38 +0000
Subject: handle more complex ruby from/to html - fixes #605
this is not exactly great, but it should be "good enough"
note that the new `group` function should not escape in the wild, as
we don't document it and only use it internally
I tried using `$[scale foo bar]` instead of `$[group foo bar]`, but
that would be rendered as `foo bar` when sent over the network
to non-misskey instances, and we don't want that
---
packages/backend/src/core/MfmService.ts | 67 +++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
(limited to 'packages/backend/src')
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index 42676d6f98..48995672c5 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -230,6 +230,67 @@ export class MfmService {
break;
}
+ case 'rp': break
+ case 'rt': {
+ appendChildren(node.childNodes);
+ break;
+ }
+ case 'ruby': {
+ if (node.childNodes) {
+ /*
+ we get:
+ ```
+
+ some text
+ more text
+ ```
+
+ and we want to produce:
+ ```
+ $[ruby $[group some text] annotation]
+ $[ruby $[group more text] more annotation]
+ ```
+
+ that `group` is a hack, because when the `ruby` render
+ sees just text inside the `$[ruby]`, it splits on
+ whitespace, considers the first "word" to be the main
+ content, and the rest the annotation
+
+ with that `group`, we force it to consider the whole
+ group as the main content
+
+ (note that the `rp` are to be ignored, they only exist
+ for browsers who don't understand ruby)
+ */
+ let nonRtNodes=[];
+ // scan children, ignore `rp`, split on `rt`
+ for (const child of node.childNodes) {
+ if (treeAdapter.isTextNode(child)) {
+ nonRtNodes.push(child);
+ continue;
+ }
+ if (!treeAdapter.isElementNode(child)) {
+ continue;
+ }
+ if (child.nodeName == 'rp') {
+ continue;
+ }
+ if (child.nodeName == 'rt') {
+ text += '$[ruby $[group ';
+ appendChildren(nonRtNodes);
+ text += '] ';
+ analyze(child);
+ text += '] ';
+ nonRtNodes=[];
+ continue;
+ }
+ nonRtNodes.push(child);
+ }
+ }
+ break;
+ }
+
default: // includes inline elements
{
appendChildren(node.childNodes);
@@ -348,6 +409,12 @@ export class MfmService {
}
}
+ case 'group': { // this is mostly a hack for `ruby`
+ const el = doc.createElement('span');
+ appendChildren(node.children, el);
+ return el;
+ }
+
default: {
return fnDefault(node);
}
--
cgit v1.2.3-freya
From 68adb6c05d9c019c16ad7ae0370922475c0914b4 Mon Sep 17 00:00:00 2001
From: dakkar
Date: Sat, 18 Jan 2025 14:54:17 +0000
Subject: pick lints
---
packages/backend/src/core/MfmService.ts | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
(limited to 'packages/backend/src')
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index 48995672c5..bc624daaee 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -230,7 +230,7 @@ export class MfmService {
break;
}
- case 'rp': break
+ case 'rp': break;
case 'rt': {
appendChildren(node.childNodes);
break;
@@ -263,7 +263,7 @@ export class MfmService {
(note that the `rp` are to be ignored, they only exist
for browsers who don't understand ruby)
*/
- let nonRtNodes=[];
+ let nonRtNodes = [];
// scan children, ignore `rp`, split on `rt`
for (const child of node.childNodes) {
if (treeAdapter.isTextNode(child)) {
@@ -273,16 +273,16 @@ export class MfmService {
if (!treeAdapter.isElementNode(child)) {
continue;
}
- if (child.nodeName == 'rp') {
+ if (child.nodeName === 'rp') {
continue;
}
- if (child.nodeName == 'rt') {
+ if (child.nodeName === 'rt') {
text += '$[ruby $[group ';
appendChildren(nonRtNodes);
text += '] ';
analyze(child);
text += '] ';
- nonRtNodes=[];
+ nonRtNodes = [];
continue;
}
nonRtNodes.push(child);
--
cgit v1.2.3-freya
From 408e2f824a686defd3ea96cc5782b6b59779b7b9 Mon Sep 17 00:00:00 2001
From: dakkar
Date: Sun, 19 Jan 2025 11:15:01 +0000
Subject: format ruby for masto api
---
packages/backend/src/core/MfmService.ts | 68 +++++++++++++++++++++++++++++---
packages/backend/test/unit/MfmService.ts | 38 ++++++++++++++++++
2 files changed, 100 insertions(+), 6 deletions(-)
(limited to 'packages/backend/src')
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index bc624daaee..dc47e38562 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -409,7 +409,9 @@ export class MfmService {
}
}
- case 'group': { // this is mostly a hack for `ruby`
+ // hack for ruby, should never be needed because we should
+ // never send this out to other instances
+ case 'group': {
const el = doc.createElement('span');
appendChildren(node.children, el);
return el;
@@ -593,11 +595,65 @@ export class MfmService {
},
async fn(node) {
- const el = doc.createElement('span');
- el.textContent = '*';
- await appendChildren(node.children, el);
- el.textContent += '*';
- return el;
+ switch (node.props.name) {
+ case 'group': { // hack for ruby
+ const el = doc.createElement('span');
+ await appendChildren(node.children, el);
+ return el;
+ }
+ case 'ruby': {
+ if (node.children.length === 1) {
+ const child = node.children[0];
+ const text = child.type === 'text' ? child.props.text : '';
+ const rubyEl = doc.createElement('ruby');
+ const rtEl = doc.createElement('rt');
+
+ const rpStartEl = doc.createElement('rp');
+ rpStartEl.appendChild(doc.createTextNode('('));
+ const rpEndEl = doc.createElement('rp');
+ rpEndEl.appendChild(doc.createTextNode(')'));
+
+ rubyEl.appendChild(doc.createTextNode(text.split(' ')[0]));
+ rtEl.appendChild(doc.createTextNode(text.split(' ')[1]));
+ rubyEl.appendChild(rpStartEl);
+ rubyEl.appendChild(rtEl);
+ rubyEl.appendChild(rpEndEl);
+ return rubyEl;
+ } else {
+ const rt = node.children.at(-1);
+
+ if (!rt) {
+ const el = doc.createElement('span');
+ await appendChildren(node.children, el);
+ return el;
+ }
+
+ const text = rt.type === 'text' ? rt.props.text : '';
+ const rubyEl = doc.createElement('ruby');
+ const rtEl = doc.createElement('rt');
+
+ const rpStartEl = doc.createElement('rp');
+ rpStartEl.appendChild(doc.createTextNode('('));
+ const rpEndEl = doc.createElement('rp');
+ rpEndEl.appendChild(doc.createTextNode(')'));
+
+ await appendChildren(node.children.slice(0, node.children.length - 1), rubyEl);
+ rtEl.appendChild(doc.createTextNode(text.trim()));
+ rubyEl.appendChild(rpStartEl);
+ rubyEl.appendChild(rtEl);
+ rubyEl.appendChild(rpEndEl);
+ return rubyEl;
+ }
+ }
+
+ default: {
+ const el = doc.createElement('span');
+ el.textContent = '*';
+ await appendChildren(node.children, el);
+ el.textContent += '*';
+ return el;
+ }
+ }
},
blockCode(node) {
diff --git a/packages/backend/test/unit/MfmService.ts b/packages/backend/test/unit/MfmService.ts
index 93ce0672dc..5c3ffba422 100644
--- a/packages/backend/test/unit/MfmService.ts
+++ b/packages/backend/test/unit/MfmService.ts
@@ -47,12 +47,50 @@ describe('MfmService', () => {
});
test('ruby', () => {
+ const input = '$[ruby some text ignore me]';
+ const output = 'sometext
';
+ assert.equal(mfmService.toHtml(mfm.parse(input)), output);
+ });
+
+ test('ruby2', () => {
+ const input = '$[ruby *some text* ignore me]';
+ const output = 'some textignore me
';
+ assert.equal(mfmService.toHtml(mfm.parse(input)), output);
+ });
+
+ test('ruby 3', () => {
const input = '$[ruby $[group *some* text] ignore me]';
const output = 'some textignore me
';
assert.equal(mfmService.toHtml(mfm.parse(input)), output);
});
});
+ describe('toMastoApiHtml', () => {
+ test('br', async () => {
+ const input = 'foo\nbar\nbaz';
+ const output = 'foo
bar
baz
';
+ assert.equal(await mfmService.toMastoApiHtml(mfm.parse(input)), output);
+ });
+
+ test('br alt', async () => {
+ const input = 'foo\r\nbar\rbaz';
+ const output = 'foo
bar
baz
';
+ assert.equal(await mfmService.toMastoApiHtml(mfm.parse(input)), output);
+ });
+
+ test('escape', async () => {
+ const input = '```\nHello, world!
\n```';
+ const output = '<p>Hello, world!</p>
';
+ assert.equal(await mfmService.toMastoApiHtml(mfm.parse(input)), output);
+ });
+
+ test('ruby', async () => {
+ const input = '$[ruby $[group *some* text] ignore me]';
+ const output = '*some* textignore me
';
+ assert.equal(await mfmService.toMastoApiHtml(mfm.parse(input)), output);
+ });
+ });
+
describe('fromHtml', () => {
test('p', () => {
assert.deepStrictEqual(mfmService.fromHtml('a
b
'), 'a\n\nb');
--
cgit v1.2.3-freya
From 1080f19e99ffccdebb09c39035d93d9b561ef0e6 Mon Sep 17 00:00:00 2001
From: piuvas
Date: Fri, 24 Jan 2025 18:37:18 -0300
Subject: generalize current language so we match more broadly on fallback
---
packages/backend/src/server/web/boot.embed.js | 2 +-
packages/backend/src/server/web/boot.js | 2 +-
packages/frontend/src/_dev_boot_.ts | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
(limited to 'packages/backend/src')
diff --git a/packages/backend/src/server/web/boot.embed.js b/packages/backend/src/server/web/boot.embed.js
index b07dce3ac4..1af1dc545b 100644
--- a/packages/backend/src/server/web/boot.embed.js
+++ b/packages/backend/src/server/web/boot.embed.js
@@ -48,7 +48,7 @@
if (supportedLangs.includes(navigator.language)) {
lang = navigator.language;
} else {
- lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
+ lang = supportedLangs.find(x => x.split('-')[0] === navigator.language.split('-')[0]);
// Fallback
if (lang == null) lang = 'en-US';
diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js
index bf83340bde..54750e26e5 100644
--- a/packages/backend/src/server/web/boot.js
+++ b/packages/backend/src/server/web/boot.js
@@ -39,7 +39,7 @@
if (supportedLangs.includes(navigator.language)) {
lang = navigator.language;
} else {
- lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
+ lang = supportedLangs.find(x => x.split('-')[0] === navigator.language.split('-')[0]);
// Fallback
if (lang == null) lang = 'en-US';
diff --git a/packages/frontend/src/_dev_boot_.ts b/packages/frontend/src/_dev_boot_.ts
index f312765dcf..ebce7e735f 100644
--- a/packages/frontend/src/_dev_boot_.ts
+++ b/packages/frontend/src/_dev_boot_.ts
@@ -25,7 +25,7 @@ async function main() {
if (supportedLangs.includes(navigator.language)) {
lang = navigator.language;
} else {
- lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
+ lang = supportedLangs.find(x => x.split('-')[0] === navigator.language.split('-')[0]);
// Fallback
if (lang == null) lang = 'en-US';
--
cgit v1.2.3-freya
From 83f2d93d30100f38df2ed34807ec5d8d80a19c4b Mon Sep 17 00:00:00 2001
From: Hazelnoot
Date: Sat, 1 Feb 2025 18:53:32 -0500
Subject: increase rate limit on federation/update-remote-user
---
.../src/server/api/endpoints/federation/update-remote-user.ts | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
(limited to 'packages/backend/src')
diff --git a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts
index 3ec9522c44..5217f79065 100644
--- a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts
+++ b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts
@@ -13,10 +13,11 @@ export const meta = {
requireCredential: false,
- // 2 calls per second
+ // Up to 10 calls, then 4 / second.
+ // This allows for reliable automation.
limit: {
- duration: 1000,
- max: 2,
+ max: 10,
+ dripRate: 250,
},
} as const;
--
cgit v1.2.3-freya
From bd716ed8377ab160abf23f60ccc43affebc87882 Mon Sep 17 00:00:00 2001
From: Hazelnoot
Date: Sat, 1 Feb 2025 23:56:41 -0500
Subject: increase the rate limit for `/api/i` endpoint, preventing some 429
errors if multiple tabs reload simultaneously
---
packages/backend/src/server/api/endpoints/i.ts | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
(limited to 'packages/backend/src')
diff --git a/packages/backend/src/server/api/endpoints/i.ts b/packages/backend/src/server/api/endpoints/i.ts
index 9347c9ca27..48a2e3b40a 100644
--- a/packages/backend/src/server/api/endpoints/i.ts
+++ b/packages/backend/src/server/api/endpoints/i.ts
@@ -31,10 +31,12 @@ export const meta = {
},
},
- // 3 calls per second
+ // up to 20 calls, then 1 per second.
+ // This handles bursty traffic when all tabs reload as a group
limit: {
- duration: 1000,
- max: 3,
+ max: 20,
+ dripSize: 1,
+ dripRate: 1000,
},
} as const;
--
cgit v1.2.3-freya
From 1bedf954f296a7151e0e878cecb0154508c93967 Mon Sep 17 00:00:00 2001
From: Hazelnoot
Date: Mon, 27 Jan 2025 01:57:14 -0500
Subject: increase rate limit for `users/show` endpoint
---
packages/backend/src/server/api/endpoints/users/show.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
(limited to 'packages/backend/src')
diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts
index 7ebca78a7d..118362149d 100644
--- a/packages/backend/src/server/api/endpoints/users/show.ts
+++ b/packages/backend/src/server/api/endpoints/users/show.ts
@@ -57,10 +57,10 @@ export const meta = {
},
},
- // 5 calls per 2 seconds
+ // up to 50 calls @ 4 per second
limit: {
- duration: 1000 * 2,
- max: 5,
+ max: 50,
+ dripRate: 250,
},
} as const;
--
cgit v1.2.3-freya
From 74407bc8ee43a8c7b4bc8b7e16bdfb8acd2c794c Mon Sep 17 00:00:00 2001
From: Hazelnoot
Date: Sat, 1 Feb 2025 17:07:34 -0500
Subject: add MiUserProfile.defaultCW property and API
---
locales/index.d.ts | 2 +-
.../1738446745738-add_user_profile_default_cw.js | 11 +++++++++++
packages/backend/src/core/entities/UserEntityService.ts | 1 +
packages/backend/src/models/UserProfile.ts | 10 ++++++++--
packages/backend/src/models/json-schema/user.ts | 4 ++++
packages/backend/src/server/api/endpoints/i/update.ts | 17 +++++++++++++++++
packages/misskey-js/src/autogen/types.ts | 5 +++++
7 files changed, 47 insertions(+), 3 deletions(-)
create mode 100644 packages/backend/migration/1738446745738-add_user_profile_default_cw.js
(limited to 'packages/backend/src')
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 70eba52ea0..af5faefe1a 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -11631,7 +11631,7 @@ export interface Locale extends ILocale {
*/
"robotsTxt": string;
/**
- * Adding entries here will override the default robots.txt packaged with Sharkey. Maximum 2048 characters.
+ * Adding entries here will override the default robots.txt packaged with Sharkey.
*/
"robotsTxtDescription": string;
}
diff --git a/packages/backend/migration/1738446745738-add_user_profile_default_cw.js b/packages/backend/migration/1738446745738-add_user_profile_default_cw.js
new file mode 100644
index 0000000000..205ca2087a
--- /dev/null
+++ b/packages/backend/migration/1738446745738-add_user_profile_default_cw.js
@@ -0,0 +1,11 @@
+export class AddUserProfileDefaultCw1738446745738 {
+ name = 'AddUserProfileDefaultCw1738446745738'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "user_profile" ADD "default_cw" text`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "default_cw"`);
+ }
+}
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index 6bfe865038..0ca784fa52 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -669,6 +669,7 @@ export class UserEntityService implements OnModuleInit {
achievements: profile!.achievements,
loggedInDays: profile!.loggedInDates.length,
policies: this.roleService.getUserPolicies(user.id),
+ defaultCW: profile?.defaultCW ?? null,
} : {}),
...(opts.includeSecrets ? {
diff --git a/packages/backend/src/models/UserProfile.ts b/packages/backend/src/models/UserProfile.ts
index 751b1aff08..3c2362227e 100644
--- a/packages/backend/src/models/UserProfile.ts
+++ b/packages/backend/src/models/UserProfile.ts
@@ -36,10 +36,10 @@ export class MiUserProfile {
})
public birthday: string | null;
- @Column("varchar", {
+ @Column('varchar', {
length: 128,
nullable: true,
- comment: "The ListenBrainz username of the User.",
+ comment: 'The ListenBrainz username of the User.',
})
public listenbrainz: string | null;
@@ -290,6 +290,12 @@ export class MiUserProfile {
unlockedAt: number;
}[];
+ @Column('text', {
+ name: 'default_cw',
+ nullable: true,
+ })
+ public defaultCW: string | null;
+
//#region Denormalized fields
@Index()
@Column('varchar', {
diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts
index f953008b3f..f6c7bd2151 100644
--- a/packages/backend/src/models/json-schema/user.ts
+++ b/packages/backend/src/models/json-schema/user.ts
@@ -752,6 +752,10 @@ export const packedMeDetailedOnlySchema = {
},
},
//#endregion
+ defaultCW: {
+ type: 'string',
+ nullable: true, optional: false,
+ },
},
} as const;
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index 09c06a108d..e487562687 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -133,6 +133,12 @@ export const meta = {
id: '0b3f9f6a-2f4d-4b1f-9fb4-49d3a2fd7191',
httpStatusCode: 422,
},
+
+ maxCwLength: {
+ message: 'You tried setting a default content warning which is too long.',
+ code: 'MAX_CW_LENGTH',
+ id: '7004c478-bda3-4b4f-acb2-4316398c9d52',
+ },
},
res: {
@@ -243,6 +249,7 @@ export const paramDef = {
uniqueItems: true,
items: { type: 'string' },
},
+ defaultCW: { type: 'string', nullable: true },
},
} as const;
@@ -494,6 +501,16 @@ export default class extends Endpoint { // eslint-
updates.alsoKnownAs = newAlsoKnownAs.size > 0 ? Array.from(newAlsoKnownAs) : null;
}
+ let defaultCW = ps.defaultCW;
+ if (defaultCW !== undefined) {
+ if (defaultCW === '') defaultCW = null;
+ if (defaultCW && defaultCW.length > this.config.maxCwLength) {
+ throw new ApiError(meta.errors.maxCwLength);
+ }
+
+ profileUpdates.defaultCW = defaultCW;
+ }
+
//#region emojis/tags
let emojis = [] as string[];
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 888e46e008..78dac5f08b 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -4217,6 +4217,7 @@ export type components = {
/** Format: date-time */
lastUsed: string;
}[];
+ defaultCW: string | null;
};
UserDetailedNotMe: components['schemas']['UserLite'] & components['schemas']['UserDetailedNotMeOnly'];
MeDetailed: components['schemas']['UserLite'] & components['schemas']['UserDetailedNotMeOnly'] & components['schemas']['MeDetailedOnly'];
@@ -5224,6 +5225,7 @@ export type components = {
enableFC: boolean;
fcSiteKey: string | null;
enableAchievements: boolean | null;
+ robotsTxt: string | null;
enableTestcaptcha: boolean;
swPublickey: string | null;
/** @default /assets/ai.png */
@@ -5434,6 +5436,7 @@ export type operations = {
enableStatsForFederatedInstances: boolean;
enableServerMachineStats: boolean;
enableAchievements: boolean;
+ robotsTxt: string | null;
enableIdenticonGeneration: boolean;
manifestJsonOverride: string;
policies: Record;
@@ -10163,6 +10166,7 @@ export type operations = {
enableStatsForFederatedInstances?: boolean;
enableServerMachineStats?: boolean;
enableAchievements?: boolean;
+ robotsTxt?: string | null;
enableIdenticonGeneration?: boolean;
serverRules?: string[];
bannedEmailDomains?: string[];
@@ -21631,6 +21635,7 @@ export type operations = {
};
emailNotificationTypes?: string[];
alsoKnownAs?: string[];
+ defaultCW?: string | null;
};
};
};
--
cgit v1.2.3-freya
From c8f8a61a00d07802dc5056eae48144e49bce742c Mon Sep 17 00:00:00 2001
From: Hazelnoot
Date: Sat, 1 Feb 2025 23:15:02 -0500
Subject: add MiUserProfile.defaultCWPriority property and API
---
.../1738468079662-add_user_profile_default_cw_priority.js | 13 +++++++++++++
packages/backend/src/core/entities/UserEntityService.ts | 7 +++++--
packages/backend/src/models/UserProfile.ts | 9 ++++++++-
packages/backend/src/models/json-schema/user.ts | 5 +++++
packages/backend/src/server/api/endpoints/i/update.ts | 8 ++++++++
packages/backend/src/types.ts | 2 ++
packages/misskey-js/src/autogen/types.ts | 4 ++++
7 files changed, 45 insertions(+), 3 deletions(-)
create mode 100644 packages/backend/migration/1738468079662-add_user_profile_default_cw_priority.js
(limited to 'packages/backend/src')
diff --git a/packages/backend/migration/1738468079662-add_user_profile_default_cw_priority.js b/packages/backend/migration/1738468079662-add_user_profile_default_cw_priority.js
new file mode 100644
index 0000000000..90de25e06f
--- /dev/null
+++ b/packages/backend/migration/1738468079662-add_user_profile_default_cw_priority.js
@@ -0,0 +1,13 @@
+export class AddUserProfileDefaultCwPriority1738468079662 {
+ name = 'AddUserProfileDefaultCwPriority1738468079662'
+
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE TYPE "public"."user_profile_default_cw_priority_enum" AS ENUM ('default', 'parent', 'defaultParent', 'parentDefault')`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ADD "default_cw_priority" "public"."user_profile_default_cw_priority_enum" NOT NULL DEFAULT 'parent'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "default_cw_priority"`);
+ await queryRunner.query(`DROP TYPE "public"."user_profile_default_cw_priority_enum"`);
+ }
+}
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index 0ca784fa52..6ea2d6629a 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -49,11 +49,13 @@ import { IdService } from '@/core/IdService.js';
import type { AnnouncementService } from '@/core/AnnouncementService.js';
import type { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { AvatarDecorationService } from '@/core/AvatarDecorationService.js';
+import { isSystemAccount } from '@/misc/is-system-account.js';
import type { OnModuleInit } from '@nestjs/common';
import type { NoteEntityService } from './NoteEntityService.js';
import type { DriveFileEntityService } from './DriveFileEntityService.js';
import type { PageEntityService } from './PageEntityService.js';
-import { isSystemAccount } from '@/misc/is-system-account.js';
+
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
const Ajv = _Ajv.default;
const ajv = new Ajv();
@@ -669,7 +671,8 @@ export class UserEntityService implements OnModuleInit {
achievements: profile!.achievements,
loggedInDays: profile!.loggedInDates.length,
policies: this.roleService.getUserPolicies(user.id),
- defaultCW: profile?.defaultCW ?? null,
+ defaultCW: profile!.defaultCW,
+ defaultCWPriority: profile!.defaultCWPriority,
} : {}),
...(opts.includeSecrets ? {
diff --git a/packages/backend/src/models/UserProfile.ts b/packages/backend/src/models/UserProfile.ts
index 3c2362227e..449c2f370b 100644
--- a/packages/backend/src/models/UserProfile.ts
+++ b/packages/backend/src/models/UserProfile.ts
@@ -4,7 +4,7 @@
*/
import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm';
-import { obsoleteNotificationTypes, followingVisibilities, followersVisibilities, notificationTypes } from '@/types.js';
+import { obsoleteNotificationTypes, followingVisibilities, followersVisibilities, notificationTypes, noteVisibilities, defaultCWPriorities } from '@/types.js';
import { id } from './util/id.js';
import { MiUser } from './User.js';
import { MiPage } from './Page.js';
@@ -296,6 +296,13 @@ export class MiUserProfile {
})
public defaultCW: string | null;
+ @Column('enum', {
+ name: 'default_cw_priority',
+ enum: defaultCWPriorities,
+ default: 'parent',
+ })
+ public defaultCWPriority: typeof defaultCWPriorities[number];
+
//#region Denormalized fields
@Index()
@Column('varchar', {
diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts
index f6c7bd2151..93b031e9c5 100644
--- a/packages/backend/src/models/json-schema/user.ts
+++ b/packages/backend/src/models/json-schema/user.ts
@@ -756,6 +756,11 @@ export const packedMeDetailedOnlySchema = {
type: 'string',
nullable: true, optional: false,
},
+ defaultCWPriority: {
+ type: 'string',
+ enum: ['default', 'parent', 'defaultParent', 'parentDefault'],
+ nullable: false, optional: false,
+ },
},
} as const;
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index e487562687..e1552fed8a 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -250,6 +250,11 @@ export const paramDef = {
items: { type: 'string' },
},
defaultCW: { type: 'string', nullable: true },
+ defaultCWPriority: {
+ type: 'string',
+ enum: ['default', 'parent', 'defaultParent', 'parentDefault'],
+ nullable: false,
+ },
},
} as const;
@@ -510,6 +515,9 @@ export default class extends Endpoint { // eslint-
profileUpdates.defaultCW = defaultCW;
}
+ if (ps.defaultCWPriority !== undefined) {
+ profileUpdates.defaultCWPriority = ps.defaultCWPriority;
+ }
//#region emojis/tags
diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts
index 37bed27fb1..067481d9da 100644
--- a/packages/backend/src/types.ts
+++ b/packages/backend/src/types.ts
@@ -58,6 +58,8 @@ export const mutedNoteReasons = ['word', 'manual', 'spam', 'other'] as const;
export const followingVisibilities = ['public', 'followers', 'private'] as const;
export const followersVisibilities = ['public', 'followers', 'private'] as const;
+export const defaultCWPriorities = ['default', 'parent', 'defaultParent', 'parentDefault'] as const;
+
/**
* ユーザーがエクスポートできるものの種類
*
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 78dac5f08b..c7268ade6a 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -4218,6 +4218,8 @@ export type components = {
lastUsed: string;
}[];
defaultCW: string | null;
+ /** @enum {string} */
+ defaultCWPriority: 'default' | 'parent' | 'defaultParent' | 'parentDefault';
};
UserDetailedNotMe: components['schemas']['UserLite'] & components['schemas']['UserDetailedNotMeOnly'];
MeDetailed: components['schemas']['UserLite'] & components['schemas']['UserDetailedNotMeOnly'] & components['schemas']['MeDetailedOnly'];
@@ -21636,6 +21638,8 @@ export type operations = {
emailNotificationTypes?: string[];
alsoKnownAs?: string[];
defaultCW?: string | null;
+ /** @enum {string} */
+ defaultCWPriority?: 'default' | 'parent' | 'defaultParent' | 'parentDefault';
};
};
};
--
cgit v1.2.3-freya