Skip to content

Commit

Permalink
Merge pull request #11926 from misskey-dev/develop
Browse files Browse the repository at this point in the history
* fix(backend): Redisに古いMisskeyバージョンのキャッシュが残っている場合の問題を修正

* Update CHANGELOG.md

* enhance(front)end: improve moderation log

* enhance: ノートの翻訳機能の利用可否をロールで設定可能に

Resolve #11923

* 2023.9.3

* 後方互換性の強化

* Update CHANGELOG.md

* fix test

* [ci skip] New Crowdin updates (#11922)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Simplified)

* feat: AiScriptでホストのアドレスを参照できる定数 (#11924)

* add HOST_URL

* Update CHANGELOG.md

* tweak

---------

Co-authored-by: syuilo <[email protected]>

---------

Co-authored-by: FineArchs <[email protected]>
  • Loading branch information
syuilo and FineArchs authored Sep 30, 2023
2 parents 7adc8fc + 09dfb9b commit 0e6cd57
Show file tree
Hide file tree
Showing 21 changed files with 125 additions and 9 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
-->

## 2023.9.3
### General
- Enhance: ノートの翻訳機能の利用可否をロールで設定可能に

### Client
- Enhance: AiScriptでホストのアドレスを参照する定数`SERVER_URL`を追加
- Enhance: モデレーションログ機能の強化
- Enhance: ローカリゼーションの更新

### Server
- Fix: Redisに古いバージョンのキャッシュが残っている場合、キャッシュが消えるまでの間通知が届かなくなる問題を修正
- Fix: 後方互換性の修正

## 2023.9.2

### General
Expand Down
6 changes: 6 additions & 0 deletions locales/de-DE.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,9 @@ authenticationRequiredToContinue: "Bitte authentifiziere dich, um fortzufahren"
dateAndTime: "Zeit"
showRenotes: "Renotes anzeigen"
edited: "Bearbeitet"
notificationRecieveConfig: "Benachrichtigungseinstellungen"
mutualFollow: "Gegenseitig gefolgt"
fileAttachedOnly: "Nur Notizen mit Dateien"
_announcement:
forExistingUsers: "Nur für existierende Nutzer"
forExistingUsersDescription: "Ist diese Option aktiviert, wird diese Ankündigung nur Nutzern angezeigt, die zum Zeitpunkt der Ankündigung bereits registriert sind. Ist sie deaktiviert, wird sie auch Nutzern, die sich nach dessen Veröffentlichung registrieren, angezeigt."
Expand Down Expand Up @@ -2132,3 +2135,6 @@ _moderationLogTypes:
unmarkSensitiveDriveFile: "Datei als nicht sensitiv markiert"
resolveAbuseReport: "Meldung bearbeitet"
createInvitation: "Einladung erstellt"
createAd: "Werbung erstellt"
deleteAd: "Werbung gelöscht"
updateAd: "Werbung aktualisiert"
6 changes: 6 additions & 0 deletions locales/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,9 @@ authenticationRequiredToContinue: "Please authenticate to continue"
dateAndTime: "Timestamp"
showRenotes: "Show renotes"
edited: "Edited"
notificationRecieveConfig: "Notification Settings"
mutualFollow: "Mutual follow"
fileAttachedOnly: "Only notes with files"
_announcement:
forExistingUsers: "Existing users only"
forExistingUsersDescription: "This announcement will only be shown to users existing at the point of publishment if enabled. If disabled, those newly signing up after it has been posted will also see it."
Expand Down Expand Up @@ -2132,3 +2135,6 @@ _moderationLogTypes:
unmarkSensitiveDriveFile: "File unmarked as sensitive"
resolveAbuseReport: "Report resolved"
createInvitation: "Invite generated"
createAd: "Ad created"
deleteAd: "Ad deleted"
updateAd: "Ad updated"
1 change: 1 addition & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1562,6 +1562,7 @@ export interface Locale {
"descriptionOfRateLimitFactor": string;
"canHideAds": string;
"canSearchNotes": string;
"canUseTranslator": string;
};
"_condition": {
"isLocal": string;
Expand Down
3 changes: 2 additions & 1 deletion locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,8 @@ _role:
rateLimitFactor: "レートリミット"
descriptionOfRateLimitFactor: "小さいほど制限が緩和され、大きいほど制限が強化されます。"
canHideAds: "広告の非表示"
canSearchNotes: "ノート検索の利用可否"
canSearchNotes: "ノート検索の利用"
canUseTranslator: "翻訳機能の利用"
_condition:
isLocal: "ローカルユーザー"
isRemote: "リモートユーザー"
Expand Down
21 changes: 21 additions & 0 deletions locales/ko-KR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,9 @@ totp: "인증 앱"
totpDescription: "인증 앱을 사용하여 일회성 비밀번호 입력"
moderator: "모더레이터"
moderation: "모더레이션"
moderationNote: "모더레이션 노트"
addModerationNote: "모더레이션 노트 추가하기"
moderationLogs: "모더레이션 로그"
nUsersMentioned: "{n}명이 언급함"
securityKeyAndPasskey: "보안 키 또는 패스 키"
securityKey: "보안 키"
Expand Down Expand Up @@ -1107,6 +1110,18 @@ youHaveUnreadAnnouncements: "읽지 않은 공지사항이 있습니다."
useSecurityKey: "브라우저 또는 기기의 안내에 따라 보안 키 또는 패스키를 사용해 주십시오."
replies: "답글"
renotes: "리노트"
loadReplies: "답글 보기"
loadConversation: "대화 보기"
pinnedList: "고정해놓은 리스트"
keepScreenOn: "기기 화면을 항상 켜기"
verifiedLink: "이 링크의 소유자임이 확인되었습니다."
notifyNotes: "새 노트 알림 켜기"
unnotifyNotes: "새 노트 알림 끄기"
authentication: "인증"
showRenotes: "리노트 표시"
edited: "수정됨"
notificationRecieveConfig: "알림 설정"
mutualFollow: "맞팔로우"
_announcement:
forExistingUsers: "기존 유저에게만 알림"
forExistingUsersDescription: "활성화하면 이 공지사항을 게시한 시점에서 이미 가입한 유저에게만 표시합니다. 비활성화하면 게시 후에 가입한 유저에게도 표시합니다."
Expand Down Expand Up @@ -1135,6 +1150,12 @@ _serverRules:
description: "회원 가입 이전에 간단하게 표시할 서버 규칙입니다. 이용 약관의 요약으로 구성하는 것을 추천합니다."
_serverSettings:
iconUrl: "아이콘 URL"
appIconUsageExample: "예를 들어, PWA나 스마트폰 홈 화면에 북마크로 추가되었을 때 등"
appIconStyleRecommendation: "아이콘이 원형 또는 둥근 사각형으로 잘리는 경우가 있으므로, 가장자리 여백이 충분한 사진을 사용하는 것을 추천합니다."
appIconResolutionMustBe: "해상도는 반드시 {resolution} 이어야 합니다."
manifestJsonOverride: "manifest.json 오버라이드"
shortName: "약칭"
shortNameDescription: "서버의 정식 명칭이 긴 경우에, 대신에 표시할 수 있는 약칭이나 통칭."
_accountMigration:
moveFrom: "다른 계정에서 이 계정으로 이사"
moveFromSub: "다른 계정에 대한 별칭을 생성"
Expand Down
6 changes: 6 additions & 0 deletions locales/th-TH.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,9 @@ authentication: "การตรวจสอบสิทธิ์"
dateAndTime: "เวลาประทับ"
showRenotes: "แสดงรีโน้ต"
edited: "แก้ไขแล้ว"
notificationRecieveConfig: "การตั้งค่าการแจ้งเตือน"
mutualFollow: "ติดตามซึ่งกันและกัน"
fileAttachedOnly: "เฉพาะโน้ตที่มีไฟล์เท่านั้น"
_announcement:
forExistingUsers: "ผู้ใช้งานที่มีอยู่เท่านั้น"
forExistingUsersDescription: "การประกาศนี้จะแสดงต่อผู้ใช้ที่มีอยู่ ณ จุดที่เผยแพร่นั้นๆถ้าหากเปิดใช้งาน ถ้าหากปิดใช้งานผู้ที่กำลังสมัครใหม่หลังจากโพสต์แล้วนั้นก็จะเห็นเช่นกัน"
Expand Down Expand Up @@ -2104,3 +2107,6 @@ _moderationLogTypes:
resetPassword: "รีเซ็ตรหัสผ่าน"
resolveAbuseReport: "รายงานได้รับการแก้ไขแล้ว"
createInvitation: "สร้างคำเชิญ"
createAd: "สร้างโฆษณาแล้ว"
deleteAd: "ลบโฆษณาออกแล้ว"
updateAd: "อัปเดตโฆษณาแล้ว"
6 changes: 6 additions & 0 deletions locales/zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,9 @@ authenticationRequiredToContinue: "要继续,请先进行验证"
dateAndTime: "日期和时间"
showRenotes: "显示转帖"
edited: "已编辑"
notificationRecieveConfig: "通知接收设置"
mutualFollow: "互相关注"
fileAttachedOnly: "仅限媒体"
_announcement:
forExistingUsers: "仅限现有用户"
forExistingUsersDescription: "若启用,该公告将仅对创建此公告时存在的用户可见。 如果禁用,则在创建此公告后注册的用户也可以看到该公告。"
Expand Down Expand Up @@ -2130,3 +2133,6 @@ _moderationLogTypes:
unmarkSensitiveDriveFile: "取消标记网盘文件为敏感媒体"
resolveAbuseReport: "处理举报"
createInvitation: "发行邀请码"
createAd: "创建了广告"
deleteAd: "删除了广告"
updateAd: "更新了广告"
5 changes: 5 additions & 0 deletions locales/zh-TW.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,8 @@ authentication: "驗證"
authenticationRequiredToContinue: "請於繼續前完成驗證"
dateAndTime: "日期與時間"
showRenotes: "顯示轉發貼文"
edited: "已編輯"
mutualFollow: "互相追隨"
_announcement:
forExistingUsers: "僅限既有的使用者"
forExistingUsersDescription: "啟用代表僅向現存使用者顯示;停用代表張貼後註冊的新使用者也會看到。"
Expand Down Expand Up @@ -2131,3 +2133,6 @@ _moderationLogTypes:
unmarkSensitiveDriveFile: "撤銷標記為敏感檔案"
resolveAbuseReport: "解決檢舉"
createInvitation: "建立邀請碼"
createAd: "建立廣告"
deleteAd: "刪除廣告"
updateAd: "更新廣告"
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "2023.9.2",
"version": "2023.9.3",
"codename": "nasubi",
"repository": {
"type": "git",
Expand Down
5 changes: 4 additions & 1 deletion packages/backend/src/core/NotificationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ export class NotificationService implements OnApplicationShutdown {
notifierId?: MiUser['id'] | null,
): Promise<MiNotification | null> {
const profile = await this.cacheService.userProfileCache.fetch(notifieeId);
const recieveConfig = profile.notificationRecieveConfig[type];

// 古いMisskeyバージョンのキャッシュが残っている可能性がある
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const recieveConfig = (profile.notificationRecieveConfig ?? {})[type];
if (recieveConfig?.type === 'never') {
return null;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/backend/src/core/RoleService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export type RolePolicies = {
inviteExpirationTime: number;
canManageCustomEmojis: boolean;
canSearchNotes: boolean;
canUseTranslator: boolean;
canHideAds: boolean;
driveCapacityMb: number;
alwaysMarkNsfw: boolean;
Expand All @@ -58,6 +59,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
inviteExpirationTime: 0,
canManageCustomEmojis: false,
canSearchNotes: false,
canUseTranslator: true,
canHideAds: false,
driveCapacityMb: 100,
alwaysMarkNsfw: false,
Expand Down Expand Up @@ -303,6 +305,7 @@ export class RoleService implements OnApplicationShutdown {
inviteExpirationTime: calc('inviteExpirationTime', vs => Math.max(...vs)),
canManageCustomEmojis: calc('canManageCustomEmojis', vs => vs.some(v => v === true)),
canSearchNotes: calc('canSearchNotes', vs => vs.some(v => v === true)),
canUseTranslator: calc('canUseTranslator', vs => vs.some(v => v === true)),
canHideAds: calc('canHideAds', vs => vs.some(v => v === true)),
driveCapacityMb: calc('driveCapacityMb', vs => Math.max(...vs)),
alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)),
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/core/entities/UserEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ export class UserEntityService implements OnModuleInit {
hasPendingReceivedFollowRequest: this.getHasPendingReceivedFollowRequest(user.id),
mutedWords: profile!.mutedWords,
mutedInstances: profile!.mutedInstances,
mutingNotificationTypes: [], // 後方互換性のため
notificationRecieveConfig: profile!.notificationRecieveConfig,
emailNotificationTypes: profile!.emailNotificationTypes,
achievements: profile!.achievements,
Expand Down
16 changes: 14 additions & 2 deletions packages/backend/src/server/api/endpoints/notes/translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,25 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { MetaService } from '@/core/MetaService.js';
import { HttpRequestService } from '@/core/HttpRequestService.js';
import { GetterService } from '@/server/api/GetterService.js';
import { RoleService } from '@/core/RoleService.js';
import { ApiError } from '../../error.js';

export const meta = {
tags: ['notes'],

requireCredential: false,
requireCredential: true,

res: {
type: 'object',
optional: false, nullable: false,
},

errors: {
unavailable: {
message: 'Translate of notes unavailable.',
code: 'UNAVAILABLE',
id: '50a70314-2d8a-431b-b433-efa5cc56444c',
},
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
Expand All @@ -47,14 +53,20 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private getterService: GetterService,
private metaService: MetaService,
private httpRequestService: HttpRequestService,
private roleService: RoleService,
) {
super(meta, paramDef, async (ps, me) => {
const policies = await this.roleService.getUserPolicies(me.id);
if (!policies.canUseTranslator) {
throw new ApiError(meta.errors.unavailable);
}

const note = await this.getterService.getNote(ps.noteId).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
throw err;
});

if (!(await this.noteEntityService.isVisibleForMe(note, me ? me.id : null))) {
if (!(await this.noteEntityService.isVisibleForMe(note, me.id))) {
return 204; // TODO: 良い感じのエラー返す
}

Expand Down
2 changes: 2 additions & 0 deletions packages/backend/test/e2e/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ describe('ユーザー', () => {
unreadAnnouncements: user.unreadAnnouncements,
mutedWords: user.mutedWords,
mutedInstances: user.mutedInstances,
mutingNotificationTypes: user.mutingNotificationTypes,
notificationRecieveConfig: user.notificationRecieveConfig,
emailNotificationTypes: user.emailNotificationTypes,
achievements: user.achievements,
Expand Down Expand Up @@ -414,6 +415,7 @@ describe('ユーザー', () => {
assert.deepStrictEqual(response.unreadAnnouncements, []);
assert.deepStrictEqual(response.mutedWords, []);
assert.deepStrictEqual(response.mutedInstances, []);
assert.deepStrictEqual(response.mutingNotificationTypes, []);
assert.deepStrictEqual(response.notificationRecieveConfig, {});
assert.deepStrictEqual(response.emailNotificationTypes, ['follow', 'receiveFollowRequest']);
assert.deepStrictEqual(response.achievements, []);
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const ROLE_POLICIES = [
'inviteExpirationTime',
'canManageCustomEmojis',
'canSearchNotes',
'canUseTranslator',
'canHideAds',
'driveCapacityMb',
'alwaysMarkNsfw',
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/pages/admin/modlog.ModLog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<span v-else-if="log.type === 'suspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
<span v-else-if="log.type === 'unsuspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
<span v-else-if="log.type === 'resetPassword'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
<span v-else-if="log.type === 'assignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
<span v-else-if="log.type === 'unassignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
<span v-else-if="log.type === 'assignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} <i class="ti ti-arrow-right"></i> {{ log.info.roleName }}</span>
<span v-else-if="log.type === 'unassignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} <i class="ti ti-equal-not"></i> {{ log.info.roleName }}</span>
<span v-else-if="log.type === 'createRole'">: {{ log.info.role.name }}</span>
<span v-else-if="log.type === 'updateRole'">: {{ log.info.before.name }}</span>
<span v-else-if="log.type === 'deleteRole'">: {{ log.info.role.name }}</span>
Expand Down
20 changes: 20 additions & 0 deletions packages/frontend/src/pages/admin/roles.editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,26 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkFolder>

<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseTranslator, 'canUseTranslator'])">
<template #label>{{ i18n.ts._role._options.canUseTranslator }}</template>
<template #suffix>
<span v-if="role.policies.canUseTranslator.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
<span v-else>{{ role.policies.canUseTranslator.value ? i18n.ts.yes : i18n.ts.no }}</span>
<span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.canUseTranslator)"></i></span>
</template>
<div class="_gaps">
<MkSwitch v-model="role.policies.canUseTranslator.useDefault" :readonly="readonly">
<template #label>{{ i18n.ts._role.useBaseValue }}</template>
</MkSwitch>
<MkSwitch v-model="role.policies.canUseTranslator.value" :disabled="role.policies.canUseTranslator.useDefault" :readonly="readonly">
<template #label>{{ i18n.ts.enable }}</template>
</MkSwitch>
<MkRange v-model="role.policies.canUseTranslator.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.driveCapacity, 'driveCapacityMb'])">
<template #label>{{ i18n.ts._role._options.driveCapacity }}</template>
<template #suffix>
Expand Down
8 changes: 8 additions & 0 deletions packages/frontend/src/pages/admin/roles.vue
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkSwitch>
</MkFolder>

<MkFolder v-if="matchQuery([i18n.ts._role._options.canUseTranslator, 'canSearchNotes'])">
<template #label>{{ i18n.ts._role._options.canUseTranslator }}</template>
<template #suffix>{{ policies.canUseTranslator ? i18n.ts.yes : i18n.ts.no }}</template>
<MkSwitch v-model="policies.canUseTranslator">
<template #label>{{ i18n.ts.enable }}</template>
</MkSwitch>
</MkFolder>

<MkFolder v-if="matchQuery([i18n.ts._role._options.driveCapacity, 'driveCapacityMb'])">
<template #label>{{ i18n.ts._role._options.driveCapacity }}</template>
<template #suffix>{{ policies.driveCapacityMb }}MB</template>
Expand Down
3 changes: 2 additions & 1 deletion packages/frontend/src/scripts/aiscript/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as os from '@/os.js';
import { $i } from '@/account.js';
import { miLocalStorage } from '@/local-storage.js';
import { customEmojis } from '@/custom-emojis.js';
import { lang } from '@/config.js';
import { url, lang } from '@/config.js';

export function createAiScriptEnv(opts) {
return {
Expand All @@ -17,6 +17,7 @@ export function createAiScriptEnv(opts) {
USER_USERNAME: $i ? values.STR($i.username) : values.NULL,
CUSTOM_EMOJIS: utils.jsToVal(customEmojis.value),
LOCALE: values.STR(lang),
SERVER_URL: values.STR(url),
'Mk:dialog': values.FN_NATIVE(async ([title, text, type]) => {
await os.alert({
type: type ? type.value : 'info',
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/scripts/get-note-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export function getNoteMenu(props: {
text: i18n.ts.share,
action: share,
},
instance.translatorAvailable ? {
$i && $i.policies.canUseTranslator && instance.translatorAvailable ? {
icon: 'ti ti-language-hiragana',
text: i18n.ts.translate,
action: translate,
Expand Down

0 comments on commit 0e6cd57

Please sign in to comment.