refactor(account): account delete, truncate, auto note removal
This commit is contained in:
parent
4e99008e8d
commit
d84bff37ec
@ -1273,6 +1273,8 @@ temporarilySeeThis: "Nevermind, just show me this"
|
|||||||
sensitiveDoubleClickRequired: "Require double-click to open sensitive media"
|
sensitiveDoubleClickRequired: "Require double-click to open sensitive media"
|
||||||
mutualLink: "Mutual Link"
|
mutualLink: "Mutual Link"
|
||||||
saveThisFile: "Save this file to Drive"
|
saveThisFile: "Save this file to Drive"
|
||||||
|
autoRemoval: "Automatic note deletion"
|
||||||
|
autoRemovalDescription: "You can delete your note when it exceeds period you set."
|
||||||
_bubbleGame:
|
_bubbleGame:
|
||||||
howToPlay: "How to play"
|
howToPlay: "How to play"
|
||||||
hold: "Hold"
|
hold: "Hold"
|
||||||
@ -1331,6 +1333,14 @@ _announcement:
|
|||||||
dialogAnnouncementUxWarn: "Having two or more dialog-style notifications simultaneously can significantly impact the user experience, so please use them carefully."
|
dialogAnnouncementUxWarn: "Having two or more dialog-style notifications simultaneously can significantly impact the user experience, so please use them carefully."
|
||||||
silence: "No notification"
|
silence: "No notification"
|
||||||
silenceDescription: "Turning this on will skip the notification of this announcement and the user won't need to read it."
|
silenceDescription: "Turning this on will skip the notification of this announcement and the user won't need to read it."
|
||||||
|
_autoRemoval:
|
||||||
|
use: "Use automatic note deletion"
|
||||||
|
deleteAfter: "Period threshold"
|
||||||
|
deleteAfterDescription: "When your notes exceeds this period, notes will be deleted."
|
||||||
|
noPiningNotes: "Exclude pinned notes"
|
||||||
|
noPiningNotesDescription: "Delete notes except that are not pinned in profile."
|
||||||
|
noSpecifiedNotes: "Exclude direct notes"
|
||||||
|
noSpecifiedNotesDescription: "Delete notes without direct visibility."
|
||||||
_initialAccountSetting:
|
_initialAccountSetting:
|
||||||
accountCreated: "Your account was successfully created!"
|
accountCreated: "Your account was successfully created!"
|
||||||
letsStartAccountSetup: "For starters, let's set up your profile."
|
letsStartAccountSetup: "For starters, let's set up your profile."
|
||||||
@ -1742,29 +1752,31 @@ _role:
|
|||||||
canCreateContent: "Can create contents"
|
canCreateContent: "Can create contents"
|
||||||
canUpdateContent: "Can edit contents"
|
canUpdateContent: "Can edit contents"
|
||||||
canDeleteContent: "Can delete contents"
|
canDeleteContent: "Can delete contents"
|
||||||
|
canUseAutoNoteRemoval: "Can use automatic note deletion"
|
||||||
canUseAccountRemoval: "Can delete account"
|
canUseAccountRemoval: "Can delete account"
|
||||||
|
canUseAccountTruncate: "Can truncate account"
|
||||||
canPurgeAccount: "Can delete account completely"
|
canPurgeAccount: "Can delete account completely"
|
||||||
canUpdateAvatar: "Can change avatar"
|
canUpdateAvatar: "Can change avatar"
|
||||||
canUpdateBanner: "Can change banner"
|
canUpdateBanner: "Can change banner"
|
||||||
mentionMax: "Maximum number of mentions in a note"
|
mentionLimit: "Maximum number of mentions in a note"
|
||||||
canInvite: "Can create instance invite codes"
|
canInvite: "Can create instance invite codes"
|
||||||
inviteLimit: "Invite limit"
|
inviteLimit: "Invite limit"
|
||||||
inviteLimitCycle: "Invite limit cooldown"
|
inviteLimitCycle: "Invite limit cooldown"
|
||||||
inviteExpirationTime: "Invite expiration interval"
|
inviteExpirationTime: "Invite expiration interval"
|
||||||
canManageCustomEmojis: "Can manage custom emojis"
|
canManageCustomEmojis: "Can manage custom emojis"
|
||||||
canManageAvatarDecorations: "Manage avatar decorations"
|
canManageAvatarDecorations: "Manage avatar decorations"
|
||||||
driveCapacity: "Drive capacity"
|
driveCapacityMb: "Drive capacity (MB)"
|
||||||
alwaysMarkNsfw: "Always mark files as NSFW"
|
alwaysMarkNsfw: "Always mark files as NSFW"
|
||||||
skipNsfwDetection: "Skip NSFW detection by AI"
|
skipNsfwDetection: "Skip NSFW detection by AI"
|
||||||
pinMax: "Maximum number of pinned notes"
|
pinLimit: "Maximum number of pinned notes"
|
||||||
antennaMax: "Maximum number of antennas"
|
antennaLimit: "Maximum number of antennas"
|
||||||
antennaNotesMax: "Maximum number of notes stored in antennas"
|
antennaNotesLimit: "Maximum number of notes stored in antennas"
|
||||||
wordMuteMax: "Maximum number of characters allowed in word mutes"
|
wordMuteLimit: "Maximum number of words allowed in word mutes"
|
||||||
webhookMax: "Maximum number of Webhooks"
|
webhookLimit: "Maximum number of Webhooks"
|
||||||
clipMax: "Maximum number of Clips"
|
clipLimit: "Maximum number of Clips"
|
||||||
noteEachClipsMax: "Maximum number of notes within a clip"
|
noteEachClipsLimit: "Maximum number of notes within a clip"
|
||||||
userListMax: "Maximum number of user lists"
|
userListLimit: "Maximum number of user lists"
|
||||||
userEachUserListsMax: "Maximum number of users within a user list"
|
userEachUserListsLimit: "Maximum number of users within a user list"
|
||||||
rateLimitFactor: "Rate limit"
|
rateLimitFactor: "Rate limit"
|
||||||
descriptionOfRateLimitFactor: "Lower rate limits are less restrictive, higher ones more restrictive. "
|
descriptionOfRateLimitFactor: "Lower rate limits are less restrictive, higher ones more restrictive. "
|
||||||
canHideAds: "Can hide ads"
|
canHideAds: "Can hide ads"
|
||||||
@ -1822,17 +1834,19 @@ _accountDelete:
|
|||||||
accountDelete: "Delete account"
|
accountDelete: "Delete account"
|
||||||
mayTakeTime: "As account deletion is a resource-heavy process, it may take some time to complete depending on how much content you have created and how many files you have uploaded."
|
mayTakeTime: "As account deletion is a resource-heavy process, it may take some time to complete depending on how much content you have created and how many files you have uploaded."
|
||||||
sendEmail: "Once account deletion has been completed, an email will be sent to the email address registered to this account."
|
sendEmail: "Once account deletion has been completed, an email will be sent to the email address registered to this account."
|
||||||
requestAccountDelete: "Request account deletion"
|
requestAccountDelete: "Request to delete my account"
|
||||||
started: "Deletion has been started."
|
started: "Deletion has been started."
|
||||||
inProgress: "Deletion is currently in progress"
|
inProgress: "Your account is currently being deleted"
|
||||||
youCantUseThisTime: "You can't request account deletion for now."
|
youCantUseThisTime: "You can't request account deletion for now."
|
||||||
|
youAreRootAndCantUseThisTime: "You can't request account deletion 'cause you are root."
|
||||||
_accountTruncate:
|
_accountTruncate:
|
||||||
accountTruncate: "Truncate account"
|
accountTruncate: "Truncate account"
|
||||||
purgeDriveFiles: "Also purge drive's files"
|
purgeDriveFiles: "Also truncate drive's files"
|
||||||
mayTakeTime: "As account deletion is a resource-heavy process, it may take some time to complete depending on how much content you have created and how many files you have uploaded."
|
mayTakeTime: "As account truncate task is a resource-heavy process, it may take some time to complete depending on how much content you have created and how many files you have uploaded."
|
||||||
requestAccountTruncate: "Request to truncate my account"
|
requestAccountTruncate: "Request to truncate my account"
|
||||||
started: "Truncate task has been started."
|
started: "Truncate task has been started."
|
||||||
inProgress: "Your account is currently being truncated"
|
inProgress: "Your account is currently being truncated"
|
||||||
|
youCantUseThisTime: "You can't request account truncate task for now."
|
||||||
_ad:
|
_ad:
|
||||||
back: "Back"
|
back: "Back"
|
||||||
reduceFrequencyOfThisAd: "Show this ad less"
|
reduceFrequencyOfThisAd: "Show this ad less"
|
||||||
|
72
locales/index.d.ts
vendored
72
locales/index.d.ts
vendored
@ -5224,9 +5224,21 @@ export interface Locale extends ILocale {
|
|||||||
*/
|
*/
|
||||||
"youAreOnVacation": string;
|
"youAreOnVacation": string;
|
||||||
/**
|
/**
|
||||||
* 노트 자동 삭제
|
* ノート自動削除
|
||||||
*/
|
*/
|
||||||
"autoRemoval": string;
|
"autoRemoval": string;
|
||||||
|
/**
|
||||||
|
* ノート自動削除は、作成してから一定期間が経過したノートを削除してくれる機能です。
|
||||||
|
*/
|
||||||
|
"autoRemovalDescription": string;
|
||||||
|
/**
|
||||||
|
* 危険区域
|
||||||
|
*/
|
||||||
|
"dangerZone": string;
|
||||||
|
/**
|
||||||
|
* 以下の機能を利用する際は、特にご注意ください。
|
||||||
|
*/
|
||||||
|
"dangerZoneDescription": string;
|
||||||
"_bubbleGame": {
|
"_bubbleGame": {
|
||||||
/**
|
/**
|
||||||
* 遊び方
|
* 遊び方
|
||||||
@ -5432,33 +5444,37 @@ export interface Locale extends ILocale {
|
|||||||
};
|
};
|
||||||
"_autoRemoval": {
|
"_autoRemoval": {
|
||||||
/**
|
/**
|
||||||
* 노트 자동 삭제를 사용하기
|
* ノート自動削除を使用する
|
||||||
*/
|
*/
|
||||||
"use": string;
|
"use": string;
|
||||||
/**
|
/**
|
||||||
* 이 기간이 지난 후에 자동으로 삭제
|
* この期間が過ぎたら自動的に削除する
|
||||||
*/
|
*/
|
||||||
"deleteAfter": string;
|
"deleteAfter": string;
|
||||||
/**
|
/**
|
||||||
* 여기에 적힌 일 수가 지나면 노트를 자동으로 삭제합니다. 활성화 이후에는 삭제 대상인 노트도 같이 제거됩니다.
|
* ここに書かれた日数が過ぎるとノートを自動的に削除します。有効化後は、削除対象のノートも一緒に削除されます。
|
||||||
*/
|
*/
|
||||||
"deleteAfterDescription": string;
|
"deleteAfterDescription": string;
|
||||||
/**
|
/**
|
||||||
* 고정된 노트를 제외하기
|
* 固定されたノートを除外する
|
||||||
*/
|
*/
|
||||||
"noPiningNotes": string;
|
"noPiningNotes": string;
|
||||||
/**
|
/**
|
||||||
* 프로필에 고정된 노트를 제외하고 삭제합니다.
|
* プロフィールに固定されたノートを除いて削除します。
|
||||||
*/
|
*/
|
||||||
"noPiningNotesDescription": string;
|
"noPiningNotesDescription": string;
|
||||||
/**
|
/**
|
||||||
* 다이렉트 노트를 제외하기
|
* ダイレクトノートを除外する
|
||||||
*/
|
*/
|
||||||
"noSpecifiedNotes": string;
|
"noSpecifiedNotes": string;
|
||||||
/**
|
/**
|
||||||
* 다이렉트 노트를 제외하고 삭제합니다.
|
* ダイレクトノートを除いて削除します。
|
||||||
*/
|
*/
|
||||||
"noSpecifiedNotesDescription": string;
|
"noSpecifiedNotesDescription": string;
|
||||||
|
/**
|
||||||
|
* 現在、ノートの自動削除を設定することはできません。
|
||||||
|
*/
|
||||||
|
"youCantUseThisTime": string;
|
||||||
};
|
};
|
||||||
"_initialTutorial": {
|
"_initialTutorial": {
|
||||||
/**
|
/**
|
||||||
@ -6974,10 +6990,18 @@ export interface Locale extends ILocale {
|
|||||||
* コンテンツの削除
|
* コンテンツの削除
|
||||||
*/
|
*/
|
||||||
"canDeleteContent": string;
|
"canDeleteContent": string;
|
||||||
|
/**
|
||||||
|
* ノート自動削除の利用
|
||||||
|
*/
|
||||||
|
"canUseAutoNoteRemoval": string;
|
||||||
/**
|
/**
|
||||||
* アカウントの削除
|
* アカウントの削除
|
||||||
*/
|
*/
|
||||||
"canUseAccountRemoval": string;
|
"canUseAccountRemoval": string;
|
||||||
|
/**
|
||||||
|
* アカウントの整理
|
||||||
|
*/
|
||||||
|
"canUseAccountTruncate": string;
|
||||||
/**
|
/**
|
||||||
* 完全なアカウントの削除
|
* 完全なアカウントの削除
|
||||||
*/
|
*/
|
||||||
@ -6993,7 +7017,7 @@ export interface Locale extends ILocale {
|
|||||||
/**
|
/**
|
||||||
* ノート内の最大メンション数
|
* ノート内の最大メンション数
|
||||||
*/
|
*/
|
||||||
"mentionMax": string;
|
"mentionLimit": string;
|
||||||
/**
|
/**
|
||||||
* サーバー招待コードの発行
|
* サーバー招待コードの発行
|
||||||
*/
|
*/
|
||||||
@ -7019,9 +7043,9 @@ export interface Locale extends ILocale {
|
|||||||
*/
|
*/
|
||||||
"canManageAvatarDecorations": string;
|
"canManageAvatarDecorations": string;
|
||||||
/**
|
/**
|
||||||
* ドライブ容量
|
* ドライブ容量 (MB)
|
||||||
*/
|
*/
|
||||||
"driveCapacity": string;
|
"driveCapacityMb": string;
|
||||||
/**
|
/**
|
||||||
* ファイルにNSFWを常に付与
|
* ファイルにNSFWを常に付与
|
||||||
*/
|
*/
|
||||||
@ -7033,39 +7057,39 @@ export interface Locale extends ILocale {
|
|||||||
/**
|
/**
|
||||||
* ノートのピン留めの最大数
|
* ノートのピン留めの最大数
|
||||||
*/
|
*/
|
||||||
"pinMax": string;
|
"pinLimit": string;
|
||||||
/**
|
/**
|
||||||
* アンテナの作成可能数
|
* アンテナの作成可能数
|
||||||
*/
|
*/
|
||||||
"antennaMax": string;
|
"antennaLimit": string;
|
||||||
/**
|
/**
|
||||||
* アンテナに保持する最大ノート数
|
* アンテナに保持する最大ノート数
|
||||||
*/
|
*/
|
||||||
"antennaNotesMax": string;
|
"antennaNotesLimit": string;
|
||||||
/**
|
/**
|
||||||
* ワードミュートの最大文字数
|
* ワードミュートの最大文字数
|
||||||
*/
|
*/
|
||||||
"wordMuteMax": string;
|
"wordMuteLimit": string;
|
||||||
/**
|
/**
|
||||||
* Webhookの作成可能数
|
* Webhookの作成可能数
|
||||||
*/
|
*/
|
||||||
"webhookMax": string;
|
"webhookLimit": string;
|
||||||
/**
|
/**
|
||||||
* クリップの作成可能数
|
* クリップの作成可能数
|
||||||
*/
|
*/
|
||||||
"clipMax": string;
|
"clipLimit": string;
|
||||||
/**
|
/**
|
||||||
* クリップ内のノートの最大数
|
* クリップ内のノートの最大数
|
||||||
*/
|
*/
|
||||||
"noteEachClipsMax": string;
|
"noteEachClipsLimit": string;
|
||||||
/**
|
/**
|
||||||
* ユーザーリストの作成可能数
|
* ユーザーリストの作成可能数
|
||||||
*/
|
*/
|
||||||
"userListMax": string;
|
"userListLimit": string;
|
||||||
/**
|
/**
|
||||||
* ユーザーリスト内のユーザーの最大数
|
* ユーザーリスト内のユーザーの最大数
|
||||||
*/
|
*/
|
||||||
"userEachUserListsMax": string;
|
"userEachUserListsLimit": string;
|
||||||
/**
|
/**
|
||||||
* レートリミット
|
* レートリミット
|
||||||
*/
|
*/
|
||||||
@ -7299,6 +7323,10 @@ export interface Locale extends ILocale {
|
|||||||
* 現在、アカウントの削除はできません。
|
* 現在、アカウントの削除はできません。
|
||||||
*/
|
*/
|
||||||
"youCantUseThisTime": string;
|
"youCantUseThisTime": string;
|
||||||
|
/**
|
||||||
|
* あなたは最高管理者であるため、アカウントを削除することはできません。
|
||||||
|
*/
|
||||||
|
"youAreRootAndCantUseThisTime": string;
|
||||||
};
|
};
|
||||||
"_accountTruncate": {
|
"_accountTruncate": {
|
||||||
/**
|
/**
|
||||||
@ -7325,6 +7353,10 @@ export interface Locale extends ILocale {
|
|||||||
* 整理が進行中
|
* 整理が進行中
|
||||||
*/
|
*/
|
||||||
"inProgress": string;
|
"inProgress": string;
|
||||||
|
/**
|
||||||
|
* 現在、アカウントの整理はできません。
|
||||||
|
*/
|
||||||
|
"youCantUseThisTime": string;
|
||||||
};
|
};
|
||||||
"_ad": {
|
"_ad": {
|
||||||
/**
|
/**
|
||||||
|
@ -1301,7 +1301,10 @@ mindControlDescription: "必要に応じて、Misskeyの疲労感を少なくす
|
|||||||
hideCounters: "すべてのカウンターを隠す"
|
hideCounters: "すべてのカウンターを隠す"
|
||||||
hideCountersDescription: "ユーザーページのノート、フォロー、フォロワー数、およびこれらの統計をすべて非表示にします。"
|
hideCountersDescription: "ユーザーページのノート、フォロー、フォロワー数、およびこれらの統計をすべて非表示にします。"
|
||||||
youAreOnVacation: "現在、休暇モードを使用しています。 このメッセージを閉じるにはここをクリックしてください。"
|
youAreOnVacation: "現在、休暇モードを使用しています。 このメッセージを閉じるにはここをクリックしてください。"
|
||||||
autoRemoval: "노트 자동 삭제"
|
autoRemoval: "ノート自動削除"
|
||||||
|
autoRemovalDescription: "ノート自動削除は、作成してから一定期間が経過したノートを削除してくれる機能です。"
|
||||||
|
dangerZone: "危険区域"
|
||||||
|
dangerZoneDescription: "以下の機能を利用する際は、特にご注意ください。"
|
||||||
|
|
||||||
_bubbleGame:
|
_bubbleGame:
|
||||||
howToPlay: "遊び方"
|
howToPlay: "遊び方"
|
||||||
@ -1360,13 +1363,14 @@ _announcement:
|
|||||||
silenceDescription: "オンにすると、このお知らせは通知されず、既読にする必要もなくなります。"
|
silenceDescription: "オンにすると、このお知らせは通知されず、既読にする必要もなくなります。"
|
||||||
|
|
||||||
_autoRemoval:
|
_autoRemoval:
|
||||||
use: "노트 자동 삭제를 사용하기"
|
use: "ノート自動削除を使用する"
|
||||||
deleteAfter: "이 기간이 지난 후에 자동으로 삭제"
|
deleteAfter: "この期間が過ぎたら自動的に削除する"
|
||||||
deleteAfterDescription: "여기에 적힌 일 수가 지나면 노트를 자동으로 삭제합니다. 활성화 이후에는 삭제 대상인 노트도 같이 제거됩니다."
|
deleteAfterDescription: "ここに書かれた日数が過ぎるとノートを自動的に削除します。有効化後は、削除対象のノートも一緒に削除されます。"
|
||||||
noPiningNotes: "고정된 노트를 제외하기"
|
noPiningNotes: "固定されたノートを除外する"
|
||||||
noPiningNotesDescription: "프로필에 고정된 노트를 제외하고 삭제합니다."
|
noPiningNotesDescription: "プロフィールに固定されたノートを除いて削除します。"
|
||||||
noSpecifiedNotes: "다이렉트 노트를 제외하기"
|
noSpecifiedNotes: "ダイレクトノートを除外する"
|
||||||
noSpecifiedNotesDescription: "다이렉트 노트를 제외하고 삭제합니다."
|
noSpecifiedNotesDescription: "ダイレクトノートを除いて削除します。"
|
||||||
|
youCantUseThisTime: "現在、ノートの自動削除を設定することはできません。"
|
||||||
|
|
||||||
_initialTutorial:
|
_initialTutorial:
|
||||||
launchTutorial: "チュートリアルを見る"
|
launchTutorial: "チュートリアルを見る"
|
||||||
@ -1801,29 +1805,31 @@ _role:
|
|||||||
canCreateContent: "コンテンツの作成"
|
canCreateContent: "コンテンツの作成"
|
||||||
canUpdateContent: "コンテンツの編集"
|
canUpdateContent: "コンテンツの編集"
|
||||||
canDeleteContent: "コンテンツの削除"
|
canDeleteContent: "コンテンツの削除"
|
||||||
|
canUseAutoNoteRemoval: "ノート自動削除の利用"
|
||||||
canUseAccountRemoval: "アカウントの削除"
|
canUseAccountRemoval: "アカウントの削除"
|
||||||
|
canUseAccountTruncate: "アカウントの整理"
|
||||||
canPurgeAccount: "完全なアカウントの削除"
|
canPurgeAccount: "完全なアカウントの削除"
|
||||||
canUpdateAvatar: "アイコンの変更"
|
canUpdateAvatar: "アイコンの変更"
|
||||||
canUpdateBanner: "バナーの変更"
|
canUpdateBanner: "バナーの変更"
|
||||||
mentionMax: "ノート内の最大メンション数"
|
mentionLimit: "ノート内の最大メンション数"
|
||||||
canInvite: "サーバー招待コードの発行"
|
canInvite: "サーバー招待コードの発行"
|
||||||
inviteLimit: "招待コードの作成可能数"
|
inviteLimit: "招待コードの作成可能数"
|
||||||
inviteLimitCycle: "招待コードの発行間隔"
|
inviteLimitCycle: "招待コードの発行間隔"
|
||||||
inviteExpirationTime: "招待コードの有効期限"
|
inviteExpirationTime: "招待コードの有効期限"
|
||||||
canManageCustomEmojis: "カスタム絵文字の管理"
|
canManageCustomEmojis: "カスタム絵文字の管理"
|
||||||
canManageAvatarDecorations: "アバターデコレーションの管理"
|
canManageAvatarDecorations: "アバターデコレーションの管理"
|
||||||
driveCapacity: "ドライブ容量"
|
driveCapacityMb: "ドライブ容量 (MB)"
|
||||||
alwaysMarkNsfw: "ファイルにNSFWを常に付与"
|
alwaysMarkNsfw: "ファイルにNSFWを常に付与"
|
||||||
skipNsfwDetection: "AIによるNSFW検出を無視"
|
skipNsfwDetection: "AIによるNSFW検出を無視"
|
||||||
pinMax: "ノートのピン留めの最大数"
|
pinLimit: "ノートのピン留めの最大数"
|
||||||
antennaMax: "アンテナの作成可能数"
|
antennaLimit: "アンテナの作成可能数"
|
||||||
antennaNotesMax: "アンテナに保持する最大ノート数"
|
antennaNotesLimit: "アンテナに保持する最大ノート数"
|
||||||
wordMuteMax: "ワードミュートの最大文字数"
|
wordMuteLimit: "ワードミュートの最大文字数"
|
||||||
webhookMax: "Webhookの作成可能数"
|
webhookLimit: "Webhookの作成可能数"
|
||||||
clipMax: "クリップの作成可能数"
|
clipLimit: "クリップの作成可能数"
|
||||||
noteEachClipsMax: "クリップ内のノートの最大数"
|
noteEachClipsLimit: "クリップ内のノートの最大数"
|
||||||
userListMax: "ユーザーリストの作成可能数"
|
userListLimit: "ユーザーリストの作成可能数"
|
||||||
userEachUserListsMax: "ユーザーリスト内のユーザーの最大数"
|
userEachUserListsLimit: "ユーザーリスト内のユーザーの最大数"
|
||||||
rateLimitFactor: "レートリミット"
|
rateLimitFactor: "レートリミット"
|
||||||
descriptionOfRateLimitFactor: "小さいほど制限が緩和され、大きいほど制限が強化されます。"
|
descriptionOfRateLimitFactor: "小さいほど制限が緩和され、大きいほど制限が強化されます。"
|
||||||
canHideAds: "広告の非表示"
|
canHideAds: "広告の非表示"
|
||||||
@ -1890,6 +1896,7 @@ _accountDelete:
|
|||||||
started: "削除処理が開始されました。"
|
started: "削除処理が開始されました。"
|
||||||
inProgress: "削除が進行中"
|
inProgress: "削除が進行中"
|
||||||
youCantUseThisTime: "現在、アカウントの削除はできません。"
|
youCantUseThisTime: "現在、アカウントの削除はできません。"
|
||||||
|
youAreRootAndCantUseThisTime: "あなたは最高管理者であるため、アカウントを削除することはできません。"
|
||||||
|
|
||||||
_accountTruncate:
|
_accountTruncate:
|
||||||
accountDelete: "アカウントの整理"
|
accountDelete: "アカウントの整理"
|
||||||
@ -1898,6 +1905,7 @@ _accountTruncate:
|
|||||||
requestAccountTruncate: "アカウント整理をリクエスト"
|
requestAccountTruncate: "アカウント整理をリクエスト"
|
||||||
started: "整理処理が開始されました。"
|
started: "整理処理が開始されました。"
|
||||||
inProgress: "整理が進行中"
|
inProgress: "整理が進行中"
|
||||||
|
youCantUseThisTime: "現在、アカウントの整理はできません。"
|
||||||
|
|
||||||
_ad:
|
_ad:
|
||||||
back: "戻る"
|
back: "戻る"
|
||||||
|
@ -797,7 +797,7 @@ saveConfirm: "저장하시겠습니까?"
|
|||||||
deleteConfirm: "삭제하시겠습니까?"
|
deleteConfirm: "삭제하시겠습니까?"
|
||||||
invalidValue: "올바른 값이 아닙니다."
|
invalidValue: "올바른 값이 아닙니다."
|
||||||
registry: "레지스트리"
|
registry: "레지스트리"
|
||||||
closeAccount: "계정 폐쇄"
|
closeAccount: "계정 삭제"
|
||||||
currentVersion: "현재 버전"
|
currentVersion: "현재 버전"
|
||||||
latestVersion: "최신 버전"
|
latestVersion: "최신 버전"
|
||||||
youAreRunningUpToDateClient: "사용 중인 클라이언트는 최신입니다."
|
youAreRunningUpToDateClient: "사용 중인 클라이언트는 최신입니다."
|
||||||
@ -1287,11 +1287,14 @@ hideCounters: "모든 카운터를 가리기"
|
|||||||
hideCountersDescription: "유저 페이지의 노트, 팔로잉, 팔로워 수 및 이러한 통계를 모두 숨깁니다."
|
hideCountersDescription: "유저 페이지의 노트, 팔로잉, 팔로워 수 및 이러한 통계를 모두 숨깁니다."
|
||||||
youAreOnVacation: "현재 휴가 모드를 사용 중입니다. 이 메시지를 닫으려면 여기를 클릭하세요."
|
youAreOnVacation: "현재 휴가 모드를 사용 중입니다. 이 메시지를 닫으려면 여기를 클릭하세요."
|
||||||
autoRemoval: "노트 자동 삭제"
|
autoRemoval: "노트 자동 삭제"
|
||||||
|
autoRemovalDescription: "노트 자동 삭제는 작성한 지 일정 기간이 지난 노트를 삭제해주는 기능입니다."
|
||||||
abuseReportCategory: "신고 유형"
|
abuseReportCategory: "신고 유형"
|
||||||
selectCategory: "카테고리 선택"
|
selectCategory: "카테고리 선택"
|
||||||
reportComplete: "신고 완료"
|
reportComplete: "신고 완료"
|
||||||
blockThisUser: "이 유저 차단하기"
|
blockThisUser: "이 유저 차단하기"
|
||||||
muteThisUser: "이 유저 뮤트하기"
|
muteThisUser: "이 유저 뮤트하기"
|
||||||
|
dangerZone: "위험한 것들"
|
||||||
|
dangerZoneDescription: "함부로 실행하면 어딘가 고장날 수 있는 설정들이니, 실행할 때는 주의하세요."
|
||||||
_bubbleGame:
|
_bubbleGame:
|
||||||
howToPlay: "설명"
|
howToPlay: "설명"
|
||||||
hold: "홀드"
|
hold: "홀드"
|
||||||
@ -1348,11 +1351,12 @@ _announcement:
|
|||||||
_autoRemoval:
|
_autoRemoval:
|
||||||
use: "노트 자동 삭제를 사용하기"
|
use: "노트 자동 삭제를 사용하기"
|
||||||
deleteAfter: "이 기간이 지난 후에 자동으로 삭제"
|
deleteAfter: "이 기간이 지난 후에 자동으로 삭제"
|
||||||
deleteAfterDescription: 여기에 적힌 일 수가 지나면 노트를 자동으로 삭제합니다. 활성화 이후에는 삭제 대상인 노트도 같이 제거됩니다.
|
deleteAfterDescription: "여기에 적힌 일 수가 지나면 노트를 자동으로 삭제합니다. 활성화 이후에는 삭제 대상인 노트도 같이 제거됩니다."
|
||||||
noPiningNotes: "고정된 노트를 제외하기"
|
noPiningNotes: "고정된 노트를 제외하기"
|
||||||
noPiningNotesDescription: "프로필에 고정된 노트를 제외하고 삭제합니다."
|
noPiningNotesDescription: "프로필에 고정된 노트를 제외하고 삭제합니다."
|
||||||
noSpecifiedNotes: "다이렉트 노트를 제외하기"
|
noSpecifiedNotes: "다이렉트 노트를 제외하기"
|
||||||
noSpecifiedNotesDescription: "다이렉트 노트를 제외하고 삭제합니다."
|
noSpecifiedNotesDescription: "다이렉트 노트를 제외하고 삭제합니다."
|
||||||
|
youCantUseThisTime: "지금은 노트 자동 삭제를 설정할 수 없습니다."
|
||||||
_initialTutorial:
|
_initialTutorial:
|
||||||
launchTutorial: "튜토리얼 보기"
|
launchTutorial: "튜토리얼 보기"
|
||||||
title: "튜토리얼"
|
title: "튜토리얼"
|
||||||
@ -1777,11 +1781,13 @@ _role:
|
|||||||
ltlAvailable: "로컬 타임라인 보이기"
|
ltlAvailable: "로컬 타임라인 보이기"
|
||||||
canPublicNote: "공개 노트 허용"
|
canPublicNote: "공개 노트 허용"
|
||||||
canInitiateConversation: "멘션, 답글, 인용 허용"
|
canInitiateConversation: "멘션, 답글, 인용 허용"
|
||||||
mentionMax: "노트에 넣을 수 있는 멘션 수"
|
mentionLimit: "노트에 넣을 수 있는 멘션 수"
|
||||||
canCreateContent: "컨텐츠 생성 허용"
|
canCreateContent: "컨텐츠 생성 허용"
|
||||||
canUpdateContent: "컨텐츠 수정 허용"
|
canUpdateContent: "컨텐츠 수정 허용"
|
||||||
canDeleteContent: "컨텐츠 삭제 허용"
|
canDeleteContent: "컨텐츠 삭제 허용"
|
||||||
|
canUseAutoNoteRemoval: "노트 자동 삭제 허용"
|
||||||
canUseAccountRemoval: "계정 삭제 허용"
|
canUseAccountRemoval: "계정 삭제 허용"
|
||||||
|
canUseAccountTruncate: "계정 청소 허용"
|
||||||
canPurgeAccount: "완전한 계정 삭제 허용"
|
canPurgeAccount: "완전한 계정 삭제 허용"
|
||||||
canUpdateAvatar: "아바타 변경 허용"
|
canUpdateAvatar: "아바타 변경 허용"
|
||||||
canUpdateBanner: "배너 변경 허용"
|
canUpdateBanner: "배너 변경 허용"
|
||||||
@ -1791,18 +1797,18 @@ _role:
|
|||||||
inviteExpirationTime: "초대장 만료 기간"
|
inviteExpirationTime: "초대장 만료 기간"
|
||||||
canManageCustomEmojis: "커스텀 이모지 관리"
|
canManageCustomEmojis: "커스텀 이모지 관리"
|
||||||
canManageAvatarDecorations: "아바타 장식 관리"
|
canManageAvatarDecorations: "아바타 장식 관리"
|
||||||
driveCapacity: "드라이브 용량"
|
driveCapacityMb: "드라이브 용량 (MB)"
|
||||||
alwaysMarkNsfw: "파일을 항상 NSFW로 지정"
|
alwaysMarkNsfw: "파일을 항상 NSFW로 지정"
|
||||||
skipNsfwDetection: "자동 NSFW 감지 기능 미사용"
|
skipNsfwDetection: "자동 NSFW 감지 기능 미사용"
|
||||||
pinMax: "고정할 수 있는 노트 수"
|
pinLimit: "고정할 수 있는 노트 수"
|
||||||
antennaMax: "만들 수 있는 안테나 수"
|
antennaLimit: "만들 수 있는 안테나 수"
|
||||||
antennaNotesMax: "안테나에서 저장할 수 있는 노트 수"
|
antennaNotesLimit: "안테나에서 저장할 수 있는 노트 수"
|
||||||
wordMuteMax: "단어 뮤트할 수 있는 문자 수"
|
wordMuteLimit: "단어 뮤트할 수 있는 문자 수"
|
||||||
webhookMax: "만들 수 있는 웹후크 수"
|
webhookLimit: "만들 수 있는 웹후크 수"
|
||||||
clipMax: "만들 수 있는 클립 수"
|
clipLimit: "만들 수 있는 클립 수"
|
||||||
noteEachClipsMax: "클립에 넣을 수 있는 노트 수"
|
noteEachClipsLimit: "클립에 넣을 수 있는 노트 수"
|
||||||
userListMax: "만들 수 있는 유저 리스트 수"
|
userListLimit: "만들 수 있는 유저 리스트 수"
|
||||||
userEachUserListsMax: "유저 리스트에 넣을 수 있는 유저 수"
|
userEachUserListsLimit: "유저 리스트에 넣을 수 있는 유저 수"
|
||||||
rateLimitFactor: "요청 빈도 제한"
|
rateLimitFactor: "요청 빈도 제한"
|
||||||
descriptionOfRateLimitFactor: "작을수록 제한이 완화되고, 클수록 제한이 강화됩니다."
|
descriptionOfRateLimitFactor: "작을수록 제한이 완화되고, 클수록 제한이 강화됩니다."
|
||||||
canHideAds: "광고 숨기기"
|
canHideAds: "광고 숨기기"
|
||||||
@ -1859,6 +1865,7 @@ _accountDelete:
|
|||||||
started: "삭제 작업이 시작되었습니다."
|
started: "삭제 작업이 시작되었습니다."
|
||||||
inProgress: "삭제 진행 중"
|
inProgress: "삭제 진행 중"
|
||||||
youCantUseThisTime: "지금은 계정 삭제를 진행할 수 없습니다."
|
youCantUseThisTime: "지금은 계정 삭제를 진행할 수 없습니다."
|
||||||
|
youAreRootAndCantUseThisTime: "당신은 최고 관리자이므로, 지금은 계정 삭제를 진행할 수 없습니다."
|
||||||
_accountTruncate:
|
_accountTruncate:
|
||||||
accountTruncate: "계정 청소"
|
accountTruncate: "계정 청소"
|
||||||
purgeDriveFiles: "드라이브의 파일도 정리하기"
|
purgeDriveFiles: "드라이브의 파일도 정리하기"
|
||||||
@ -1866,6 +1873,7 @@ _accountTruncate:
|
|||||||
requestAccountTruncate: "계정 청소를 요청하기"
|
requestAccountTruncate: "계정 청소를 요청하기"
|
||||||
started: "청소 작업이 시작되었습니다."
|
started: "청소 작업이 시작되었습니다."
|
||||||
inProgress: "청소 진행 중"
|
inProgress: "청소 진행 중"
|
||||||
|
youCantUseThisTime: "지금은 계정 청소를 진행할 수 없습니다."
|
||||||
_ad:
|
_ad:
|
||||||
back: "뒤로"
|
back: "뒤로"
|
||||||
reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기"
|
reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기"
|
||||||
|
@ -2,18 +2,12 @@ export class AutoNoteRemoval1725706236633 {
|
|||||||
name = 'AutoNoteRemoval1725706236633'
|
name = 'AutoNoteRemoval1725706236633'
|
||||||
|
|
||||||
async up(queryRunner) {
|
async up(queryRunner) {
|
||||||
await queryRunner.query(`CREATE TABLE "auto_removal_condition" ("id" character varying(32) NOT NULL, "deleteAfter" bigint NOT NULL DEFAULT '7', "noPiningNotes" boolean NOT NULL DEFAULT true, "noSpecifiedNotes" boolean NOT NULL DEFAULT true, CONSTRAINT "PK_e6a0b2b5bc8fbc0a07d7e34be7d" PRIMARY KEY ("id"))`);
|
await queryRunner.query(`CREATE TABLE "auto_removal_condition" ("userId" character varying(32) NOT NULL, "deleteAfter" bigint NOT NULL DEFAULT '7', "noPiningNotes" boolean NOT NULL DEFAULT true, "noSpecifiedNotes" boolean NOT NULL DEFAULT true)`);
|
||||||
await queryRunner.query(`ALTER TABLE "user" ADD "autoRemoval" boolean NOT NULL DEFAULT false`);
|
await queryRunner.query(`ALTER TABLE "user" ADD "autoRemoval" boolean NOT NULL DEFAULT false`);
|
||||||
await queryRunner.query(`COMMENT ON COLUMN "user"."autoRemoval" IS 'Whether the User is using note auto removal.'`);
|
await queryRunner.query(`COMMENT ON COLUMN "user"."autoRemoval" IS 'Whether the User is using note auto removal.'`);
|
||||||
await queryRunner.query(`ALTER TABLE "user" ADD "autoRemovalConditionId" character varying(32) NOT NULL`);
|
|
||||||
await queryRunner.query(`ALTER TABLE "user" ADD CONSTRAINT "UQ_051c1df368299ee71088b7508b8" UNIQUE ("autoRemovalConditionId")`);
|
|
||||||
await queryRunner.query(`ALTER TABLE "user" ADD CONSTRAINT "FK_051c1df368299ee71088b7508b8" FOREIGN KEY ("autoRemovalConditionId") REFERENCES "auto_removal_condition"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async down(queryRunner) {
|
async down(queryRunner) {
|
||||||
await queryRunner.query(`ALTER TABLE "user" DROP CONSTRAINT "FK_051c1df368299ee71088b7508b8"`);
|
|
||||||
await queryRunner.query(`ALTER TABLE "user" DROP CONSTRAINT "UQ_051c1df368299ee71088b7508b8"`);
|
|
||||||
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "autoRemovalConditionId"`);
|
|
||||||
await queryRunner.query(`COMMENT ON COLUMN "user"."autoRemoval" IS 'Whether the User is using note auto removal.'`);
|
await queryRunner.query(`COMMENT ON COLUMN "user"."autoRemoval" IS 'Whether the User is using note auto removal.'`);
|
||||||
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "autoRemoval"`);
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "autoRemoval"`);
|
||||||
await queryRunner.query(`DROP TABLE "auto_removal_condition"`);
|
await queryRunner.query(`DROP TABLE "auto_removal_condition"`);
|
||||||
|
@ -40,6 +40,9 @@ export type RolePolicies = {
|
|||||||
canCreateContent: boolean;
|
canCreateContent: boolean;
|
||||||
canUpdateContent: boolean;
|
canUpdateContent: boolean;
|
||||||
canDeleteContent: boolean;
|
canDeleteContent: boolean;
|
||||||
|
canUseAutoNoteRemoval: boolean;
|
||||||
|
canUseAccountRemoval: boolean;
|
||||||
|
canUseAccountTruncate: boolean;
|
||||||
canPurgeAccount: boolean;
|
canPurgeAccount: boolean;
|
||||||
canUpdateAvatar: boolean;
|
canUpdateAvatar: boolean;
|
||||||
canUpdateBanner: boolean;
|
canUpdateBanner: boolean;
|
||||||
@ -69,7 +72,6 @@ export type RolePolicies = {
|
|||||||
userEachUserListsLimit: number;
|
userEachUserListsLimit: number;
|
||||||
rateLimitFactor: number;
|
rateLimitFactor: number;
|
||||||
avatarDecorationLimit: number;
|
avatarDecorationLimit: number;
|
||||||
canUseAccountRemoval: boolean;
|
|
||||||
mutualLinkSectionLimit: number;
|
mutualLinkSectionLimit: number;
|
||||||
mutualLinkLimit: number;
|
mutualLinkLimit: number;
|
||||||
};
|
};
|
||||||
@ -82,6 +84,9 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
|||||||
canCreateContent: true,
|
canCreateContent: true,
|
||||||
canUpdateContent: true,
|
canUpdateContent: true,
|
||||||
canDeleteContent: true,
|
canDeleteContent: true,
|
||||||
|
canUseAutoNoteRemoval: true,
|
||||||
|
canUseAccountRemoval: true,
|
||||||
|
canUseAccountTruncate: true,
|
||||||
canPurgeAccount: true,
|
canPurgeAccount: true,
|
||||||
canUpdateAvatar: true,
|
canUpdateAvatar: true,
|
||||||
canUpdateBanner: true,
|
canUpdateBanner: true,
|
||||||
@ -111,7 +116,6 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
|||||||
userEachUserListsLimit: 50,
|
userEachUserListsLimit: 50,
|
||||||
rateLimitFactor: 1,
|
rateLimitFactor: 1,
|
||||||
avatarDecorationLimit: 1,
|
avatarDecorationLimit: 1,
|
||||||
canUseAccountRemoval: true,
|
|
||||||
mutualLinkSectionLimit: 1,
|
mutualLinkSectionLimit: 1,
|
||||||
mutualLinkLimit: 3,
|
mutualLinkLimit: 3,
|
||||||
};
|
};
|
||||||
@ -397,7 +401,9 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
|||||||
canCreateContent: calc('canCreateContent', vs => vs.some(v => v === true)),
|
canCreateContent: calc('canCreateContent', vs => vs.some(v => v === true)),
|
||||||
canUpdateContent: calc('canUpdateContent', vs => vs.some(v => v === true)),
|
canUpdateContent: calc('canUpdateContent', vs => vs.some(v => v === true)),
|
||||||
canDeleteContent: calc('canDeleteContent', vs => vs.some(v => v === true)),
|
canDeleteContent: calc('canDeleteContent', vs => vs.some(v => v === true)),
|
||||||
|
canUseAutoNoteRemoval: calc('canUseAutoNoteRemoval', vs => vs.some(v => v === true)),
|
||||||
canUseAccountRemoval: calc('canUseAccountRemoval', vs => vs.some(v => v === true)),
|
canUseAccountRemoval: calc('canUseAccountRemoval', vs => vs.some(v => v === true)),
|
||||||
|
canUseAccountTruncate: calc('canUseAccountTruncate', vs => vs.some(v => v === true)),
|
||||||
canPurgeAccount: calc('canPurgeAccount', vs => vs.some(v => v === true)),
|
canPurgeAccount: calc('canPurgeAccount', vs => vs.some(v => v === true)),
|
||||||
canUpdateAvatar: calc('canUpdateAvatar', vs => vs.some(v => v === true)),
|
canUpdateAvatar: calc('canUpdateAvatar', vs => vs.some(v => v === true)),
|
||||||
canUpdateBanner: calc('canUpdateBanner', vs => vs.some(v => v === true)),
|
canUpdateBanner: calc('canUpdateBanner', vs => vs.some(v => v === true)),
|
||||||
|
@ -196,6 +196,18 @@ export const packedRolePoliciesSchema = {
|
|||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
},
|
},
|
||||||
|
canUseAutoNoteRemoval: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
canUseAccountRemoval: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
canUseAccountTruncate: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
canPurgeAccount: {
|
canPurgeAccount: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
@ -312,10 +324,6 @@ export const packedRolePoliciesSchema = {
|
|||||||
type: 'integer',
|
type: 'integer',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
},
|
},
|
||||||
canUseAccountRemoval: {
|
|
||||||
type: 'boolean',
|
|
||||||
optional: false, nullable: false,
|
|
||||||
},
|
|
||||||
mutualLinkSectionLimit: {
|
mutualLinkSectionLimit: {
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
@ -151,7 +151,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
|
|||||||
case 'aggregateRetention': return this.aggregateRetentionProcessorService.process();
|
case 'aggregateRetention': return this.aggregateRetentionProcessorService.process();
|
||||||
case 'checkExpiredMutings': return this.checkExpiredMutingsProcessorService.process();
|
case 'checkExpiredMutings': return this.checkExpiredMutingsProcessorService.process();
|
||||||
case 'clean': return this.cleanProcessorService.process();
|
case 'clean': return this.cleanProcessorService.process();
|
||||||
case 'autoNoteRemoval': return this.autoNoteRemovalProcessorService.process();
|
case 'autoNoteRemoval': return this.autoNoteRemovalProcessorService.process(job);
|
||||||
default: throw new Error(`unrecognized job type ${job.name} for system`);
|
default: throw new Error(`unrecognized job type ${job.name} for system`);
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
@ -12,6 +12,7 @@ import type { MiNote } from '@/models/Note.js';
|
|||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { NoteDeleteService } from '@/core/NoteDeleteService.js';
|
import { NoteDeleteService } from '@/core/NoteDeleteService.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
import { QueueLoggerService } from '../QueueLoggerService.js';
|
import { QueueLoggerService } from '../QueueLoggerService.js';
|
||||||
import type * as Bull from 'bullmq';
|
import type * as Bull from 'bullmq';
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ export class AutoNoteRemovalProcessorService {
|
|||||||
private autoRemovalConditionRepository: AutoRemovalConditionRepository,
|
private autoRemovalConditionRepository: AutoRemovalConditionRepository,
|
||||||
|
|
||||||
private idService: IdService,
|
private idService: IdService,
|
||||||
|
private roleService: RoleService,
|
||||||
private noteDeleteService: NoteDeleteService,
|
private noteDeleteService: NoteDeleteService,
|
||||||
private queueLoggerService: QueueLoggerService,
|
private queueLoggerService: QueueLoggerService,
|
||||||
) {
|
) {
|
||||||
@ -40,7 +42,7 @@ export class AutoNoteRemovalProcessorService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async process(): Promise<void> {
|
public async process(job: Bull.Job<Record<string, unknown>>): Promise<void> {
|
||||||
this.logger.info('Checking notes that to remove automatically...');
|
this.logger.info('Checking notes that to remove automatically...');
|
||||||
this.logger.info('Checking users that enabled note auto-removal');
|
this.logger.info('Checking users that enabled note auto-removal');
|
||||||
const users = await this.usersRepository.find({ where: { autoRemoval: true } });
|
const users = await this.usersRepository.find({ where: { autoRemoval: true } });
|
||||||
@ -51,6 +53,8 @@ export class AutoNoteRemovalProcessorService {
|
|||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
|
const policies = await this.roleService.getUserPolicies(user.id);
|
||||||
|
if (!policies.canUseAutoNoteRemoval) continue;
|
||||||
const autoRemovalCondition = await this.autoRemovalConditionRepository.findOneByOrFail({ userId: user.id });
|
const autoRemovalCondition = await this.autoRemovalConditionRepository.findOneByOrFail({ userId: user.id });
|
||||||
const pinings: MiUserNotePining[] = await this.userNotePiningsRepository.findBy({ userId: user.id });
|
const pinings: MiUserNotePining[] = await this.userNotePiningsRepository.findBy({ userId: user.id });
|
||||||
const piningNoteIds: string[] = pinings.map(pining => pining.noteId); // pining.note always undefined (bug?)
|
const piningNoteIds: string[] = pinings.map(pining => pining.noteId); // pining.note always undefined (bug?)
|
||||||
@ -65,11 +69,11 @@ export class AutoNoteRemovalProcessorService {
|
|||||||
// Delete notes
|
// Delete notes
|
||||||
let cursor: MiNote['id'] | null = null;
|
let cursor: MiNote['id'] | null = null;
|
||||||
let condition: string[] = [];
|
let condition: string[] = [];
|
||||||
if (autoRemovalCondition.noSpecifiedNotes === true) {
|
if (autoRemovalCondition.noSpecifiedNotes) {
|
||||||
condition = [...condition, ...specifiedNoteIds];
|
condition = [...condition, ...specifiedNoteIds];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoRemovalCondition.noPiningNotes === true) {
|
if (autoRemovalCondition.noPiningNotes) {
|
||||||
condition = [...condition, ...piningNoteIds];
|
condition = [...condition, ...piningNoteIds];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,11 +103,13 @@ export class AutoNoteRemovalProcessorService {
|
|||||||
const createdAt: number = this.idService.parse(note.id).date.getTime();
|
const createdAt: number = this.idService.parse(note.id).date.getTime();
|
||||||
const delta: number = now - createdAt;
|
const delta: number = now - createdAt;
|
||||||
if (delta > deleteAfter) {
|
if (delta > deleteAfter) {
|
||||||
await Promise.bind(this.noteDeleteService.delete(user, note, false, user));
|
Promise.bind(this.noteDeleteService.delete(user, note, false, user));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await job.updateProgress(100 / users.length * users.indexOf(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await job.updateProgress(100);
|
||||||
this.logger.succ('All of auto-removable notes deleted');
|
this.logger.succ('All of auto-removable notes deleted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,13 +17,9 @@ export const meta = {
|
|||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
secure: true,
|
secure: true,
|
||||||
|
requireRolePolicy: 'canUseAccountRemoval',
|
||||||
|
|
||||||
errors: {
|
errors: {
|
||||||
removalDisabled: {
|
|
||||||
message: 'Account removal is disabled by your role.',
|
|
||||||
code: 'REMOVAL_DISABLED',
|
|
||||||
id: '453d954b-3d8b-4df0-a261-b26ec6660ea3',
|
|
||||||
},
|
|
||||||
authenticationFailed: {
|
authenticationFailed: {
|
||||||
message: 'Your password or 2FA token is invalid.',
|
message: 'Your password or 2FA token is invalid.',
|
||||||
code: 'AUTHENTICATION_FAILED',
|
code: 'AUTHENTICATION_FAILED',
|
||||||
@ -57,16 +53,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||||||
|
|
||||||
private userAuthService: UserAuthService,
|
private userAuthService: UserAuthService,
|
||||||
private deleteAccountService: DeleteAccountService,
|
private deleteAccountService: DeleteAccountService,
|
||||||
private roleService: RoleService,
|
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
|
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
|
||||||
|
|
||||||
const policies = await this.roleService.getUserPolicies(me.id);
|
|
||||||
if (!policies.canUseAccountRemoval) {
|
|
||||||
throw new ApiError(meta.errors.removalDisabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
const userDetailed = await this.usersRepository.findOneByOrFail({ id: me.id });
|
const userDetailed = await this.usersRepository.findOneByOrFail({ id: me.id });
|
||||||
if (userDetailed.isDeleted) {
|
if (userDetailed.isDeleted) {
|
||||||
throw new ApiError(meta.errors.alreadyRemoved);
|
throw new ApiError(meta.errors.alreadyRemoved);
|
||||||
|
@ -10,11 +10,26 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
|||||||
import { TruncateAccountService } from '@/core/TruncateAccountService.js';
|
import { TruncateAccountService } from '@/core/TruncateAccountService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { UserAuthService } from '@/core/UserAuthService.js';
|
import { UserAuthService } from '@/core/UserAuthService.js';
|
||||||
|
import {ApiError} from "@/server/api/error.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
secure: true,
|
secure: true,
|
||||||
|
requireRolePolicy: 'canUseAccountTruncate',
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
authenticationFailed: {
|
||||||
|
message: 'Your password or 2FA token is invalid.',
|
||||||
|
code: 'AUTHENTICATION_FAILED',
|
||||||
|
id: 'ea791cff-63e7-4b2a-92fc-646ab641794e',
|
||||||
|
},
|
||||||
|
alreadyRemoved: {
|
||||||
|
message: 'Your account is removed.',
|
||||||
|
code: 'ACCOUNT_REMOVED',
|
||||||
|
id: '59b8f0e6-6eb2-4dc1-a080-1de3108416d0',
|
||||||
|
},
|
||||||
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
@ -40,30 +55,26 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||||||
private truncateAccountService: TruncateAccountService,
|
private truncateAccountService: TruncateAccountService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const token = ps.token;
|
const purgeDrive = !!ps.purgeDrive;
|
||||||
const purgeDrive = ps.purgeDrive ? true : false;
|
|
||||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
|
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
|
||||||
|
|
||||||
if (profile.twoFactorEnabled) {
|
|
||||||
if (token == null) {
|
|
||||||
throw new Error('authentication failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.userAuthService.twoFactorAuthenticate(profile, token);
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error('authentication failed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const userDetailed = await this.usersRepository.findOneByOrFail({ id: me.id });
|
const userDetailed = await this.usersRepository.findOneByOrFail({ id: me.id });
|
||||||
if (userDetailed.isDeleted) {
|
if (userDetailed.isDeleted) {
|
||||||
return;
|
throw new ApiError(meta.errors.alreadyRemoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
const passwordMatched = await bcrypt.compare(ps.password, profile.password!);
|
const passwordMatched = await bcrypt.compare(ps.password, profile.password!);
|
||||||
if (!passwordMatched) {
|
if (!passwordMatched) {
|
||||||
throw new Error('incorrect password');
|
throw new ApiError(meta.errors.authenticationFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profile.twoFactorEnabled) {
|
||||||
|
const token = ps.token;
|
||||||
|
if (token == null) {
|
||||||
|
throw new ApiError(meta.errors.authenticationFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.userAuthService.twoFactorAuthenticate(profile, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.truncateAccountService.truncateAccount(me, purgeDrive);
|
await this.truncateAccountService.truncateAccount(me, purgeDrive);
|
||||||
|
@ -79,6 +79,9 @@ export const ROLE_POLICIES = [
|
|||||||
'canCreateContent',
|
'canCreateContent',
|
||||||
'canUpdateContent',
|
'canUpdateContent',
|
||||||
'canDeleteContent',
|
'canDeleteContent',
|
||||||
|
'canUseAutoNoteRemoval',
|
||||||
|
'canUseAccountRemoval',
|
||||||
|
'canUseAccountTruncate',
|
||||||
'canPurgeAccount',
|
'canPurgeAccount',
|
||||||
'canUpdateAvatar',
|
'canUpdateAvatar',
|
||||||
'canUpdateBanner',
|
'canUpdateBanner',
|
||||||
@ -108,7 +111,6 @@ export const ROLE_POLICIES = [
|
|||||||
'userEachUserListsLimit',
|
'userEachUserListsLimit',
|
||||||
'rateLimitFactor',
|
'rateLimitFactor',
|
||||||
'avatarDecorationLimit',
|
'avatarDecorationLimit',
|
||||||
'canUseAccountRemoval',
|
|
||||||
'mutualLinkSectionLimit',
|
'mutualLinkSectionLimit',
|
||||||
'mutualLinkLimit',
|
'mutualLinkLimit',
|
||||||
] as const;
|
] as const;
|
||||||
|
@ -245,6 +245,26 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseAutoNoteRemoval, 'canUseAutoNoteRemoval'])">
|
||||||
|
<template #label>{{ i18n.ts._role._options.canUseAutoNoteRemoval }}</template>
|
||||||
|
<template #suffix>
|
||||||
|
<span v-if="role.policies.canUseAutoNoteRemoval.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
|
<span v-else>{{ role.policies.canUseAutoNoteRemoval.value ? i18n.ts.yes : i18n.ts.no }}</span>
|
||||||
|
<span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.canUseAutoNoteRemoval)"></i></span>
|
||||||
|
</template>
|
||||||
|
<div class="_gaps">
|
||||||
|
<MkSwitch v-model="role.policies.canUseAutoNoteRemoval.useDefault" :readonly="readonly">
|
||||||
|
<template #label>{{ i18n.ts._role.useBaseValue }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
<MkSwitch v-model="role.policies.canUseAutoNoteRemoval.value" :disabled="role.policies.canUseAutoNoteRemoval.useDefault" :readonly="readonly">
|
||||||
|
<template #label>{{ i18n.ts.enable }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
<MkRange v-model="role.policies.canUseAutoNoteRemoval.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''">
|
||||||
|
<template #label>{{ i18n.ts._role.priority }}</template>
|
||||||
|
</MkRange>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseAccountRemoval, 'canUseAccountRemoval'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseAccountRemoval, 'canUseAccountRemoval'])">
|
||||||
<template #label>{{ i18n.ts._role._options.canUseAccountRemoval }}</template>
|
<template #label>{{ i18n.ts._role._options.canUseAccountRemoval }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
@ -265,6 +285,26 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseAccountTruncate, 'canUseAccountTruncate'])">
|
||||||
|
<template #label>{{ i18n.ts._role._options.canUseAccountTruncate }}</template>
|
||||||
|
<template #suffix>
|
||||||
|
<span v-if="role.policies.canUseAccountTruncate.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
|
<span v-else>{{ role.policies.canUseAccountTruncate.value ? i18n.ts.yes : i18n.ts.no }}</span>
|
||||||
|
<span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.canUseAccountTruncate)"></i></span>
|
||||||
|
</template>
|
||||||
|
<div class="_gaps">
|
||||||
|
<MkSwitch v-model="role.policies.canUseAccountTruncate.useDefault" :readonly="readonly">
|
||||||
|
<template #label>{{ i18n.ts._role.useBaseValue }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
<MkSwitch v-model="role.policies.canUseAccountTruncate.value" :disabled="role.policies.canUseAccountTruncate.useDefault" :readonly="readonly">
|
||||||
|
<template #label>{{ i18n.ts.enable }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
<MkRange v-model="role.policies.canUseAccountTruncate.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''">
|
||||||
|
<template #label>{{ i18n.ts._role.priority }}</template>
|
||||||
|
</MkRange>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.canPurgeAccount, 'canPurgeAccount'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.canPurgeAccount, 'canPurgeAccount'])">
|
||||||
<template #label>{{ i18n.ts._role._options.canPurgeAccount }}</template>
|
<template #label>{{ i18n.ts._role._options.canPurgeAccount }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
@ -325,8 +365,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.mentionMax, 'mentionLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.mentionLimit, 'mentionLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.mentionMax }}</template>
|
<template #label>{{ i18n.ts._role._options.mentionLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.mentionLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.mentionLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.mentionLimit.value }}</span>
|
<span v-else>{{ role.policies.mentionLimit.value }}</span>
|
||||||
@ -543,8 +583,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.driveCapacity, 'driveCapacityMb'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.driveCapacityMb, 'driveCapacityMb'])">
|
||||||
<template #label>{{ i18n.ts._role._options.driveCapacity }}</template>
|
<template #label>{{ i18n.ts._role._options.driveCapacityMb }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.driveCapacityMb.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.driveCapacityMb.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.driveCapacityMb.value + 'MB' }}</span>
|
<span v-else>{{ role.policies.driveCapacityMb.value + 'MB' }}</span>
|
||||||
@ -603,8 +643,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.pinMax, 'pinLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.pinLimit, 'pinLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.pinMax }}</template>
|
<template #label>{{ i18n.ts._role._options.pinLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.pinLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.pinLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.pinLimit.value }}</span>
|
<span v-else>{{ role.policies.pinLimit.value }}</span>
|
||||||
@ -622,8 +662,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaMax, 'antennaLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaLimit, 'antennaLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.antennaMax }}</template>
|
<template #label>{{ i18n.ts._role._options.antennaLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.antennaLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.antennaLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.antennaLimit.value }}</span>
|
<span v-else>{{ role.policies.antennaLimit.value }}</span>
|
||||||
@ -641,8 +681,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaNotesMax, 'antennaNotesLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaNotesLimit, 'antennaNotesLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.antennaNotesMax }}</template>
|
<template #label>{{ i18n.ts._role._options.antennaNotesLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.antennaNotesLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.antennaNotesLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.antennaNotesLimit.value }}</span>
|
<span v-else>{{ role.policies.antennaNotesLimit.value }}</span>
|
||||||
@ -660,8 +700,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.wordMuteMax, 'wordMuteLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.wordMuteLimit, 'wordMuteLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.wordMuteMax }}</template>
|
<template #label>{{ i18n.ts._role._options.wordMuteLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.wordMuteLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.wordMuteLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.wordMuteLimit.value }}</span>
|
<span v-else>{{ role.policies.wordMuteLimit.value }}</span>
|
||||||
@ -680,8 +720,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.webhookMax, 'webhookLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.webhookLimit, 'webhookLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.webhookMax }}</template>
|
<template #label>{{ i18n.ts._role._options.webhookLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.webhookLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.webhookLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.webhookLimit.value }}</span>
|
<span v-else>{{ role.policies.webhookLimit.value }}</span>
|
||||||
@ -699,8 +739,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.clipMax, 'clipLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.clipLimit, 'clipLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.clipMax }}</template>
|
<template #label>{{ i18n.ts._role._options.clipLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.clipLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.clipLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.clipLimit.value }}</span>
|
<span v-else>{{ role.policies.clipLimit.value }}</span>
|
||||||
@ -718,8 +758,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.noteEachClipsMax, 'noteEachClipsLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.noteEachClipsLimit, 'noteEachClipsLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.noteEachClipsMax }}</template>
|
<template #label>{{ i18n.ts._role._options.noteEachClipsLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.noteEachClipsLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.noteEachClipsLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.noteEachClipsLimit.value }}</span>
|
<span v-else>{{ role.policies.noteEachClipsLimit.value }}</span>
|
||||||
@ -737,8 +777,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.userListMax, 'userListLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.userListLimit, 'userListLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.userListMax }}</template>
|
<template #label>{{ i18n.ts._role._options.userListLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.userListLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.userListLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.userListLimit.value }}</span>
|
<span v-else>{{ role.policies.userListLimit.value }}</span>
|
||||||
@ -756,8 +796,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.userEachUserListsMax, 'userEachUserListsLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.userEachUserListsLimit, 'userEachUserListsLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.userEachUserListsMax }}</template>
|
<template #label>{{ i18n.ts._role._options.userEachUserListsLimit }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span v-if="role.policies.userEachUserListsLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
<span v-if="role.policies.userEachUserListsLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
<span v-else>{{ role.policies.userEachUserListsLimit.value }}</span>
|
<span v-else>{{ role.policies.userEachUserListsLimit.value }}</span>
|
||||||
|
@ -80,6 +80,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseAutoNoteRemoval, 'canUseAutoNoteRemoval'])">
|
||||||
|
<template #label>{{ i18n.ts._role._options.canUseAutoNoteRemoval }}</template>
|
||||||
|
<template #suffix>{{ policies.canUseAutoNoteRemoval ? i18n.ts.yes : i18n.ts.no }}</template>
|
||||||
|
<MkSwitch v-model="policies.canUseAutoNoteRemoval">
|
||||||
|
<template #label>{{ i18n.ts.enable }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseAccountRemoval, 'canUseAccountRemoval'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseAccountRemoval, 'canUseAccountRemoval'])">
|
||||||
<template #label>{{ i18n.ts._role._options.canUseAccountRemoval }}</template>
|
<template #label>{{ i18n.ts._role._options.canUseAccountRemoval }}</template>
|
||||||
<template #suffix>{{ policies.canUseAccountRemoval ? i18n.ts.yes : i18n.ts.no }}</template>
|
<template #suffix>{{ policies.canUseAccountRemoval ? i18n.ts.yes : i18n.ts.no }}</template>
|
||||||
@ -88,6 +96,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseAccountTruncate, 'canUseAccountTruncate'])">
|
||||||
|
<template #label>{{ i18n.ts._role._options.canUseAccountTruncate }}</template>
|
||||||
|
<template #suffix>{{ policies.canUseAccountTruncate ? i18n.ts.yes : i18n.ts.no }}</template>
|
||||||
|
<MkSwitch v-model="policies.canUseAccountTruncate">
|
||||||
|
<template #label>{{ i18n.ts.enable }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.canPurgeAccount, 'canPurgeAccount'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.canPurgeAccount, 'canPurgeAccount'])">
|
||||||
<template #label>{{ i18n.ts._role._options.canPurgeAccount }}</template>
|
<template #label>{{ i18n.ts._role._options.canPurgeAccount }}</template>
|
||||||
<template #suffix>{{ policies.canPurgeAccount ? i18n.ts.yes : i18n.ts.no }}</template>
|
<template #suffix>{{ policies.canPurgeAccount ? i18n.ts.yes : i18n.ts.no }}</template>
|
||||||
@ -112,8 +128,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.mentionMax, 'mentionLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.mentionLimit, 'mentionLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.mentionMax }}</template>
|
<template #label>{{ i18n.ts._role._options.mentionLimit }}</template>
|
||||||
<template #suffix>{{ policies.mentionLimit }}</template>
|
<template #suffix>{{ policies.mentionLimit }}</template>
|
||||||
<MkInput v-model="policies.mentionLimit" type="number">
|
<MkInput v-model="policies.mentionLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
@ -198,8 +214,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.driveCapacity, 'driveCapacityMb'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.driveCapacityMb, 'driveCapacityMb'])">
|
||||||
<template #label>{{ i18n.ts._role._options.driveCapacity }}</template>
|
<template #label>{{ i18n.ts._role._options.driveCapacityMb }}</template>
|
||||||
<template #suffix>{{ policies.driveCapacityMb }}MB</template>
|
<template #suffix>{{ policies.driveCapacityMb }}MB</template>
|
||||||
<MkInput v-model="policies.driveCapacityMb" type="number">
|
<MkInput v-model="policies.driveCapacityMb" type="number">
|
||||||
<template #suffix>MB</template>
|
<template #suffix>MB</template>
|
||||||
@ -222,65 +238,65 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.pinMax, 'pinLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.pinLimit, 'pinLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.pinMax }}</template>
|
<template #label>{{ i18n.ts._role._options.pinLimit }}</template>
|
||||||
<template #suffix>{{ policies.pinLimit }}</template>
|
<template #suffix>{{ policies.pinLimit }}</template>
|
||||||
<MkInput v-model="policies.pinLimit" type="number">
|
<MkInput v-model="policies.pinLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaMax, 'antennaLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaLimit, 'antennaLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.antennaMax }}</template>
|
<template #label>{{ i18n.ts._role._options.antennaLimit }}</template>
|
||||||
<template #suffix>{{ policies.antennaLimit }}</template>
|
<template #suffix>{{ policies.antennaLimit }}</template>
|
||||||
<MkInput v-model="policies.antennaLimit" type="number">
|
<MkInput v-model="policies.antennaLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaNotesMax, 'antennaNotesLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaNotesLimit, 'antennaNotesLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.antennaNotesMax }}</template>
|
<template #label>{{ i18n.ts._role._options.antennaNotesLimit }}</template>
|
||||||
<template #suffix>{{ policies.antennaNotesLimit }}</template>
|
<template #suffix>{{ policies.antennaNotesLimit }}</template>
|
||||||
<MkInput v-model="policies.antennaNotesLimit" type="number">
|
<MkInput v-model="policies.antennaNotesLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.wordMuteMax, 'wordMuteLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.wordMuteLimit, 'wordMuteLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.wordMuteMax }}</template>
|
<template #label>{{ i18n.ts._role._options.wordMuteLimit }}</template>
|
||||||
<template #suffix>{{ policies.wordMuteLimit }}</template>
|
<template #suffix>{{ policies.wordMuteLimit }}</template>
|
||||||
<MkInput v-model="policies.wordMuteLimit" type="number">
|
<MkInput v-model="policies.wordMuteLimit" type="number">
|
||||||
<template #suffix>items</template>
|
<template #suffix>items</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.webhookMax, 'webhookLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.webhookLimit, 'webhookLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.webhookMax }}</template>
|
<template #label>{{ i18n.ts._role._options.webhookLimit }}</template>
|
||||||
<template #suffix>{{ policies.webhookLimit }}</template>
|
<template #suffix>{{ policies.webhookLimit }}</template>
|
||||||
<MkInput v-model="policies.webhookLimit" type="number">
|
<MkInput v-model="policies.webhookLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.clipMax, 'clipLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.clipLimit, 'clipLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.clipMax }}</template>
|
<template #label>{{ i18n.ts._role._options.clipLimit }}</template>
|
||||||
<template #suffix>{{ policies.clipLimit }}</template>
|
<template #suffix>{{ policies.clipLimit }}</template>
|
||||||
<MkInput v-model="policies.clipLimit" type="number">
|
<MkInput v-model="policies.clipLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.noteEachClipsMax, 'noteEachClipsLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.noteEachClipsLimit, 'noteEachClipsLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.noteEachClipsMax }}</template>
|
<template #label>{{ i18n.ts._role._options.noteEachClipsLimit }}</template>
|
||||||
<template #suffix>{{ policies.noteEachClipsLimit }}</template>
|
<template #suffix>{{ policies.noteEachClipsLimit }}</template>
|
||||||
<MkInput v-model="policies.noteEachClipsLimit" type="number">
|
<MkInput v-model="policies.noteEachClipsLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.userListMax, 'userListLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.userListLimit, 'userListLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.userListMax }}</template>
|
<template #label>{{ i18n.ts._role._options.userListLimit }}</template>
|
||||||
<template #suffix>{{ policies.userListLimit }}</template>
|
<template #suffix>{{ policies.userListLimit }}</template>
|
||||||
<MkInput v-model="policies.userListLimit" type="number">
|
<MkInput v-model="policies.userListLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.userEachUserListsMax, 'userEachUserListsLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.userEachUserListsLimit, 'userEachUserListsLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.userEachUserListsMax }}</template>
|
<template #label>{{ i18n.ts._role._options.userEachUserListsLimit }}</template>
|
||||||
<template #suffix>{{ policies.userEachUserListsLimit }}</template>
|
<template #suffix>{{ policies.userEachUserListsLimit }}</template>
|
||||||
<MkInput v-model="policies.userEachUserListsLimit" type="number">
|
<MkInput v-model="policies.userEachUserListsLimit" type="number">
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
@ -16,6 +16,40 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
<FormSection>
|
||||||
|
<template #label><i class="ti ti-time-duration-off"></i> {{ i18n.ts.autoRemoval }}</template>
|
||||||
|
<template #description>{{ i18n.ts.autoRemovalDescription }}</template>
|
||||||
|
|
||||||
|
<div v-if="$i.policies.canUseAutoNoteRemoval" class="_gaps_m">
|
||||||
|
<MkInfo warn rounded>
|
||||||
|
{{ i18n.ts.thisIsExperimentalFeature }}
|
||||||
|
</MkInfo>
|
||||||
|
|
||||||
|
<MkSwitch v-model="autoRemoval" @update:modelValue="saveRemovalCondition()">{{ i18n.ts._autoRemoval.use }}</MkSwitch>
|
||||||
|
|
||||||
|
<template v-if="autoRemoval">
|
||||||
|
<MkInput v-model="deleteAfter" :type="'number'" :placeholder="'7'" :required="true" @update:modelValue="periodChanged = true">
|
||||||
|
<template #label>{{ i18n.ts._autoRemoval.deleteAfter }}</template>
|
||||||
|
<template #caption>{{ i18n.ts._autoRemoval.deleteAfterDescription }}</template>
|
||||||
|
</MkInput>
|
||||||
|
<MkButton v-if="periodChanged" primary class="save" @click="saveRemovalCondition"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
|
||||||
|
|
||||||
|
<MkSwitch v-model="noPiningNotes" @update:modelValue="saveRemovalCondition()">
|
||||||
|
<template #label>{{ i18n.ts._autoRemoval.noPiningNotes }}</template>
|
||||||
|
<template #caption>{{ i18n.ts._autoRemoval.noPiningNotesDescription }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
|
||||||
|
<MkSwitch v-model="noSpecifiedNotes" @update:modelValue="saveRemovalCondition()">
|
||||||
|
<template #label>{{ i18n.ts._autoRemoval.noSpecifiedNotes }}</template>
|
||||||
|
<template #caption>{{ i18n.ts._autoRemoval.noSpecifiedNotesDescription }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div v-else class="_gaps_m">
|
||||||
|
<MkInfo>{{ i18n.ts._autoRemoval.youCantUseThisTime }}</MkInfo>
|
||||||
|
</div>
|
||||||
|
</FormSection>
|
||||||
|
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label><i class="ti ti-lock-access"></i> {{ i18n.ts.hideSensitiveInformation }}</template>
|
<template #label><i class="ti ti-lock-access"></i> {{ i18n.ts.hideSensitiveInformation }}</template>
|
||||||
<template #description>{{ i18n.ts._hideSensitiveInformation.about }}</template>
|
<template #description>{{ i18n.ts._hideSensitiveInformation.about }}</template>
|
||||||
@ -97,39 +131,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
|
|
||||||
<!--
|
|
||||||
<MkSelect v-model="followingVisibility" @update:modelValue="save()">
|
|
||||||
<template #label>{{ i18n.ts.followingVisibility }}</template>
|
|
||||||
<option value="public">{{ i18n.ts._ffVisibility.public }}</option>
|
|
||||||
<option value="followers">{{ i18n.ts._ffVisibility.followers }}</option>
|
|
||||||
<option value="private">{{ i18n.ts._ffVisibility.private }}</option>
|
|
||||||
</MkSelect>
|
|
||||||
|
|
||||||
<MkSelect v-model="followersVisibility" @update:modelValue="save()">
|
|
||||||
<template #label>{{ i18n.ts.followersVisibility }}</template>
|
|
||||||
<option value="public">{{ i18n.ts._ffVisibility.public }}</option>
|
|
||||||
<option value="followers">{{ i18n.ts._ffVisibility.followers }}</option>
|
|
||||||
<option value="private">{{ i18n.ts._ffVisibility.private }}</option>
|
|
||||||
</MkSelect>
|
|
||||||
|
|
||||||
<MkSwitch v-model="hideOnlineStatus" @update:modelValue="save()">
|
|
||||||
{{ i18n.ts.hideOnlineStatus }}
|
|
||||||
<template #caption>{{ i18n.ts.hideOnlineStatusDescription }}</template>
|
|
||||||
</MkSwitch>
|
|
||||||
<MkSwitch v-model="noCrawle" @update:modelValue="save()">
|
|
||||||
{{ i18n.ts.noCrawle }}
|
|
||||||
<template #caption>{{ i18n.ts.noCrawleDescription }}</template>
|
|
||||||
</MkSwitch>
|
|
||||||
<MkSwitch v-model="preventAiLearning" @update:modelValue="save()">
|
|
||||||
{{ i18n.ts.preventAiLearning }}<span class="_beta">{{ i18n.ts.beta }}</span>
|
|
||||||
<template #caption>{{ i18n.ts.preventAiLearningDescription }}</template>
|
|
||||||
</MkSwitch>
|
|
||||||
<MkSwitch v-model="isExplorable" @update:modelValue="save()">
|
|
||||||
{{ i18n.ts.makeExplorable }}
|
|
||||||
<template #caption>{{ i18n.ts.makeExplorableDescription }}</template>
|
|
||||||
</MkSwitch>
|
|
||||||
-->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -147,10 +148,16 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
|||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { unisonReload } from '@/scripts/unison-reload.js';
|
import { unisonReload } from '@/scripts/unison-reload.js';
|
||||||
|
import MkButton from "@/components/MkButton.vue";
|
||||||
|
import MkInput from "@/components/MkInput.vue";
|
||||||
|
|
||||||
const $i = signinRequired();
|
const $i = signinRequired();
|
||||||
|
|
||||||
const isVacation = ref<boolean | undefined>($i.isVacation !== null ? $i.isVacation : undefined);
|
const isVacation = ref<boolean | undefined>($i.isVacation !== null ? $i.isVacation : undefined);
|
||||||
|
const autoRemoval = ref<boolean>($i.autoRemovalCondition.active);
|
||||||
|
const deleteAfter = ref<number>($i.autoRemovalCondition.deleteAfter || 7);
|
||||||
|
const noPiningNotes = ref<boolean>($i.autoRemovalCondition.noPiningNotes);
|
||||||
|
const noSpecifiedNotes = ref<boolean>($i.autoRemovalCondition.noSpecifiedNotes);
|
||||||
|
const periodChanged = ref<boolean>(false);
|
||||||
|
|
||||||
const hideCounters = computed(defaultStore.makeGetterSetter('hideCounters'));
|
const hideCounters = computed(defaultStore.makeGetterSetter('hideCounters'));
|
||||||
const enableCondensedLineForAcct = computed(defaultStore.makeGetterSetter('enableCondensedLineForAcct'));
|
const enableCondensedLineForAcct = computed(defaultStore.makeGetterSetter('enableCondensedLineForAcct'));
|
||||||
@ -160,6 +167,15 @@ const hideDriveFileList = computed(defaultStore.makeGetterSetter('hideDriveFileL
|
|||||||
const hideModerationLog = computed(defaultStore.makeGetterSetter('hideModerationLog'));
|
const hideModerationLog = computed(defaultStore.makeGetterSetter('hideModerationLog'));
|
||||||
const hideRoleList = computed(defaultStore.makeGetterSetter('hideRoleList'));
|
const hideRoleList = computed(defaultStore.makeGetterSetter('hideRoleList'));
|
||||||
|
|
||||||
|
function saveRemovalCondition() {
|
||||||
|
misskeyApi('i/update-removal-condition', {
|
||||||
|
active: autoRemoval.value,
|
||||||
|
deleteAfter: deleteAfter.value,
|
||||||
|
noPiningNotes: noPiningNotes.value,
|
||||||
|
noSpecifiedNotes: noSpecifiedNotes.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
if (isVacation.value === true) {
|
if (isVacation.value === true) {
|
||||||
defaultStore.set('vacationAlert', true);
|
defaultStore.set('vacationAlert', true);
|
||||||
|
@ -36,61 +36,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder>
|
|
||||||
<template #label>{{ i18n.ts.autoRemoval }}</template>
|
|
||||||
|
|
||||||
<div class="_gaps_m">
|
|
||||||
<MkSwitch v-model="autoRemoval">{{ i18n.ts._autoRemoval.use }}</MkSwitch>
|
|
||||||
|
|
||||||
<template v-if="autoRemoval">
|
|
||||||
<MkInput v-model="deleteAfter" :type="'number'" :placeholder="'7'" :required="true">
|
|
||||||
<template #label>{{ i18n.ts._autoRemoval.deleteAfter }}</template>
|
|
||||||
<template #caption>{{ i18n.ts._autoRemoval.deleteAfterDescription }}</template>
|
|
||||||
</MkInput>
|
|
||||||
|
|
||||||
<MkSwitch v-model="noPiningNotes">
|
|
||||||
<template #label>{{ i18n.ts._autoRemoval.noPiningNotes }}</template>
|
|
||||||
<template #caption>{{ i18n.ts._autoRemoval.noPiningNotesDescription }}</template>
|
|
||||||
</MkSwitch>
|
|
||||||
|
|
||||||
<MkSwitch v-model="noSpecifiedNotes">
|
|
||||||
<template #label>{{ i18n.ts._autoRemoval.noSpecifiedNotes }}</template>
|
|
||||||
<template #caption>{{ i18n.ts._autoRemoval.noSpecifiedNotesDescription }}</template>
|
|
||||||
</MkSwitch>
|
|
||||||
</template>
|
|
||||||
<MkButton primary class="save" @click="saveRemovalCondition"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
|
|
||||||
</div>
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<MkFolder>
|
|
||||||
<template #icon><i class="ti ti-alert-triangle"></i></template>
|
|
||||||
<template #label>{{ i18n.ts.closeAccount }}</template>
|
|
||||||
|
|
||||||
<div v-if="$i.policies.canUseAccountRemoval" class="_gaps_m">
|
|
||||||
<MkInfo warn>{{ i18n.ts._accountDelete.mayTakeTime }}</MkInfo>
|
|
||||||
<MkInfo>{{ i18n.ts._accountDelete.sendEmail }}</MkInfo>
|
|
||||||
<MkButton v-if="!$i.isDeleted" danger @click="deleteAccount">{{ i18n.ts._accountDelete.requestAccountDelete }}</MkButton>
|
|
||||||
<MkButton v-else disabled>{{ i18n.ts._accountDelete.inProgress }}</MkButton>
|
|
||||||
</div>
|
|
||||||
<div v-else class="_gaps_m">
|
|
||||||
<MkInfo warn>{{ i18n.ts._accountDelete.youCantUseThisTime }}</MkInfo>
|
|
||||||
</div>
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<MkFolder>
|
|
||||||
<template #icon><i class="ti ti-recycle"></i></template>
|
|
||||||
<template #label>{{ i18n.ts.truncateAccount }}</template>
|
|
||||||
|
|
||||||
<div class="_gaps_m">
|
|
||||||
<FormInfo warn>{{ i18n.ts._accountTruncate.mayTakeTime }}</FormInfo>
|
|
||||||
<MkSwitch v-model="purgeDrive">
|
|
||||||
<template #label>{{ i18n.ts._accountTruncate.purgeDriveFiles }}</template>
|
|
||||||
</MkSwitch>
|
|
||||||
<MkButton v-if="!$i.isDeleted" danger @click="truncateAccount">{{ i18n.ts._accountTruncate.requestAccountTruncate }}</MkButton>
|
|
||||||
<MkButton v-else disabled>{{ i18n.ts._accountTruncate.inProgress }}</MkButton>
|
|
||||||
</div>
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<MkFolder>
|
<MkFolder>
|
||||||
<template #icon><i class="ti ti-code"></i></template>
|
<template #icon><i class="ti ti-code"></i></template>
|
||||||
<template #label>{{ i18n.ts.developer }}</template>
|
<template #label>{{ i18n.ts.developer }}</template>
|
||||||
@ -115,6 +60,48 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<MkButton danger @click="updateRepliesAll(false)"><i class="ti ti-messages-off"></i> {{ i18n.ts.hideRepliesToOthersInTimelineAll }}</MkButton>
|
<MkButton danger @click="updateRepliesAll(false)"><i class="ti ti-messages-off"></i> {{ i18n.ts.hideRepliesToOthersInTimelineAll }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
|
|
||||||
|
<FormSection>
|
||||||
|
<template #label><i class="ti ti-alert-circle"></i> {{ i18n.ts.dangerZone }}</template>
|
||||||
|
<template #description>{{ i18n.ts.dangerZoneDescription }}</template>
|
||||||
|
|
||||||
|
<div class="_gaps_s">
|
||||||
|
<MkFolder>
|
||||||
|
<template #icon><i class="ti ti-trash"></i></template>
|
||||||
|
<template #label>{{ i18n.ts.closeAccount }}</template>
|
||||||
|
|
||||||
|
<div v-if="$i.policies.canUseAccountRemoval && !$i.isRoot" class="_gaps_m">
|
||||||
|
<MkInfo warn>{{ i18n.ts._accountDelete.mayTakeTime }}</MkInfo>
|
||||||
|
<MkInfo>{{ i18n.ts._accountDelete.sendEmail }}</MkInfo>
|
||||||
|
<MkButton v-if="!$i.isDeleted" danger @click="deleteAccount">{{ i18n.ts._accountDelete.requestAccountDelete }}</MkButton>
|
||||||
|
<MkButton v-else disabled>{{ i18n.ts._accountDelete.inProgress }}</MkButton>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="$i.isRoot === true" class="_gaps_m">
|
||||||
|
<MkInfo>{{ i18n.ts._accountDelete.youAreRootAndCantUseThisTime }}</MkInfo>
|
||||||
|
</div>
|
||||||
|
<div v-else class="_gaps_m">
|
||||||
|
<MkInfo>{{ i18n.ts._accountDelete.youCantUseThisTime }}</MkInfo>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder>
|
||||||
|
<template #icon><i class="ti ti-bomb"></i></template>
|
||||||
|
<template #label>{{ i18n.ts.truncateAccount }}</template>
|
||||||
|
|
||||||
|
<div v-if="$i.policies.canUseAccountTruncate" class="_gaps_m">
|
||||||
|
<MkInfo warn>{{ i18n.ts._accountTruncate.mayTakeTime }}</MkInfo>
|
||||||
|
<MkSwitch v-model="purgeDrive">
|
||||||
|
<template #label>{{ i18n.ts._accountTruncate.purgeDriveFiles }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
<MkButton v-if="!$i.isDeleted" danger @click="truncateAccount">{{ i18n.ts._accountTruncate.requestAccountTruncate }}</MkButton>
|
||||||
|
<MkButton v-else disabled>{{ i18n.ts._accountTruncate.inProgress }}</MkButton>
|
||||||
|
</div>
|
||||||
|
<div v-else class="_gaps_m">
|
||||||
|
<MkInfo>{{ i18n.ts._accountTruncate.youCantUseThisTime }}</MkInfo>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
</div>
|
||||||
|
</FormSection>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -140,19 +127,6 @@ const $i = signinRequired();
|
|||||||
const purgeDrive = ref<boolean>(false);
|
const purgeDrive = ref<boolean>(false);
|
||||||
const devMode = computed(defaultStore.makeGetterSetter('devMode'));
|
const devMode = computed(defaultStore.makeGetterSetter('devMode'));
|
||||||
const defaultWithReplies = computed(defaultStore.makeGetterSetter('defaultWithReplies'));
|
const defaultWithReplies = computed(defaultStore.makeGetterSetter('defaultWithReplies'));
|
||||||
const autoRemoval = ref<boolean>($i.autoRemovalCondition.active);
|
|
||||||
const deleteAfter = ref<number>($i.autoRemovalCondition.deleteAfter || 7);
|
|
||||||
const noPiningNotes = ref<boolean>($i.autoRemovalCondition.noPiningNotes);
|
|
||||||
const noSpecifiedNotes = ref<boolean>($i.autoRemovalCondition.noSpecifiedNotes);
|
|
||||||
|
|
||||||
function saveRemovalCondition() {
|
|
||||||
misskeyApi('i/update-removal-condition', {
|
|
||||||
active: autoRemoval.value,
|
|
||||||
deleteAfter: deleteAfter.value,
|
|
||||||
noPiningNotes: noPiningNotes.value,
|
|
||||||
noSpecifiedNotes: noSpecifiedNotes.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deleteAccount() {
|
async function deleteAccount() {
|
||||||
{
|
{
|
||||||
|
@ -4972,6 +4972,9 @@ export type components = {
|
|||||||
canCreateContent: boolean;
|
canCreateContent: boolean;
|
||||||
canUpdateContent: boolean;
|
canUpdateContent: boolean;
|
||||||
canDeleteContent: boolean;
|
canDeleteContent: boolean;
|
||||||
|
canUseAutoNoteRemoval: boolean;
|
||||||
|
canUseAccountRemoval: boolean;
|
||||||
|
canUseAccountTruncate: boolean;
|
||||||
canPurgeAccount: boolean;
|
canPurgeAccount: boolean;
|
||||||
canUpdateAvatar: boolean;
|
canUpdateAvatar: boolean;
|
||||||
canUpdateBanner: boolean;
|
canUpdateBanner: boolean;
|
||||||
@ -5001,7 +5004,6 @@ export type components = {
|
|||||||
userEachUserListsLimit: number;
|
userEachUserListsLimit: number;
|
||||||
rateLimitFactor: number;
|
rateLimitFactor: number;
|
||||||
avatarDecorationLimit: number;
|
avatarDecorationLimit: number;
|
||||||
canUseAccountRemoval: boolean;
|
|
||||||
mutualLinkSectionLimit: number;
|
mutualLinkSectionLimit: number;
|
||||||
mutualLinkLimit: number;
|
mutualLinkLimit: number;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user