Skip to content

Commit

Permalink
Merge branch 'develop' into nanka-iroiro-2024-08-14
Browse files Browse the repository at this point in the history
  • Loading branch information
syuilo committed Aug 17, 2024
2 parents daeab84 + bfaf938 commit f94f732
Show file tree
Hide file tree
Showing 16 changed files with 105 additions and 36 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Fix: ページ遷移に失敗することがある問題を修正
- Fix: iOSでユーザー名などがリンクとして誤検知される現象を抑制
- Fix: mCaptchaを使用していてもbotプロテクションに関する警告が消えないのを修正
- Fix: ユーザーのモデレーションページにおいてユーザー名にドットが入っているとシステムアカウントとして表示されてしまう問題を修正

### Server
- Enhance: 凍結されたアカウントのフォローリクエストを表示しないように
Expand All @@ -24,6 +25,8 @@
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/679)
- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように
- キュー処理のつまりが改善される可能性があります
- Fix: リバーシの対局設定の変更が反映されないのを修正
- Fix: 無制限にストリーミングのチャンネルに接続できる問題を修正

## 2024.7.0

Expand Down
4 changes: 4 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8985,6 +8985,10 @@ export interface Locale extends ILocale {
* ブロックを追加
*/
"chooseBlock": string;
/**
* セクションタイトルを入力
*/
"enterSectionTitle": string;
/**
* 種類を選択
*/
Expand Down
1 change: 1 addition & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2371,6 +2371,7 @@ _pages:
eyeCatchingImageSet: "アイキャッチ画像を設定"
eyeCatchingImageRemove: "アイキャッチ画像を削除"
chooseBlock: "ブロックを追加"
enterSectionTitle: "セクションタイトルを入力"
selectType: "種類を選択"
contentBlocks: "コンテンツ"
inputBlocks: "入力"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"glob": "11.0.0"
},
"devDependencies": {
"@misskey-dev/eslint-plugin": "2.0.2",
"@misskey-dev/eslint-plugin": "2.0.3",
"@types/node": "20.14.12",
"@typescript-eslint/eslint-plugin": "7.17.0",
"@typescript-eslint/parser": "7.17.0",
Expand Down
33 changes: 28 additions & 5 deletions packages/backend/src/core/ReversiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import { ModuleRef } from '@nestjs/core';
import { reversiUpdateKeys } from 'misskey-js';
import * as Reversi from 'misskey-reversi';
import { IsNull, LessThan, MoreThan } from 'typeorm';
import type {
Expand Down Expand Up @@ -399,18 +400,40 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
}

@bindThis
public async updateSettings(gameId: MiReversiGame['id'], user: MiUser, key: string, value: any) {
public isValidReversiUpdateKey(key: unknown): key is typeof reversiUpdateKeys[number] {
if (typeof key !== 'string') return false;
return (reversiUpdateKeys as string[]).includes(key);
}

@bindThis
public isValidReversiUpdateValue<K extends typeof reversiUpdateKeys[number]>(key: K, value: unknown): value is MiReversiGame[K] {
switch (key) {
case 'map':
return Array.isArray(value) && value.every(row => typeof row === 'string');
case 'bw':
return typeof value === 'string' && ['random', '1', '2'].includes(value);
case 'isLlotheo':
return typeof value === 'boolean';
case 'canPutEverywhere':
return typeof value === 'boolean';
case 'loopedBoard':
return typeof value === 'boolean';
case 'timeLimitForEachTurn':
return typeof value === 'number' && value >= 0;
default:
return false;
}
}

@bindThis
public async updateSettings<K extends typeof reversiUpdateKeys[number]>(gameId: MiReversiGame['id'], user: MiUser, key: K, value: MiReversiGame[K]) {
const game = await this.get(gameId);
if (game == null) throw new Error('game not found');
if (game.isStarted) return;
if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return;
if ((game.user1Id === user.id) && game.user1Ready) return;
if ((game.user2Id === user.id) && game.user2Ready) return;

if (!['map', 'bw', 'isLlotheo', 'canPutEverywhere', 'loopedBoard', 'timeLimitForEachTurn'].includes(key)) return;

// TODO: より厳格なバリデーション

const updatedGame = {
...game,
[key]: value,
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/server/api/stream/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import type { ChannelsService } from './ChannelsService.js';
import type { EventEmitter } from 'events';
import type Channel from './channel.js';

const MAX_CHANNELS_PER_CONNECTION = 32;

/**
* Main stream connection
*/
Expand Down Expand Up @@ -255,6 +257,10 @@ export default class Connection {
*/
@bindThis
public connectChannel(id: string, params: JsonObject | undefined, channel: string, pong = false) {
if (this.channels.length >= MAX_CHANNELS_PER_CONNECTION) {
return;
}

const channelService = this.channelsService.getChannelService(channel);

if (channelService.requireCredential && this.user == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityServi
import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
import Channel, { type MiChannelService } from '../channel.js';
import { reversiUpdateKeys } from 'misskey-js';

class ReversiGameChannel extends Channel {
public readonly chName = 'reversiGame';
Expand Down Expand Up @@ -46,8 +47,9 @@ class ReversiGameChannel extends Channel {
break;
case 'updateSettings':
if (!isJsonObject(body)) return;
if (typeof body.key !== 'string') return;
if (!isJsonObject(body.value)) return;
if (!this.reversiService.isValidReversiUpdateKey(body.key)) return;
if (!this.reversiService.isValidReversiUpdateValue(body.key, body.value)) return;

this.updateSettings(body.key, body.value);
break;
case 'cancel':
Expand All @@ -64,7 +66,7 @@ class ReversiGameChannel extends Channel {
}

@bindThis
private async updateSettings(key: string, value: JsonObject) {
private async updateSettings<K extends typeof reversiUpdateKeys[number]>(key: K, value: MiReversiGame[K]) {
if (this.user == null) return;

this.reversiService.updateSettings(this.gameId!, this.user, key, value);
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/pages/admin-user.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>

<MkInfo v-if="user.username.includes('.')">{{ i18n.ts.isSystemAccount }}</MkInfo>
<MkInfo v-if="['instance.actor', 'relay.actor'].includes(user.username)">{{ i18n.ts.isSystemAccount }}</MkInfo>

<FormLink v-if="user.host" :to="`/instance-info/${user.host}`">{{ i18n.ts.instanceInfo }}</FormLink>

Expand Down
15 changes: 15 additions & 0 deletions packages/frontend/src/pages/page-editor/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { i18n } from '@/i18n.js';

export function getPageBlockList() {
return [
{ value: 'section', text: i18n.ts._pages.blocks.section },
{ value: 'text', text: i18n.ts._pages.blocks.text },
{ value: 'image', text: i18n.ts._pages.blocks.image },
{ value: 'note', text: i18n.ts._pages.blocks.note },
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { deepClone } from '@/scripts/clone.js';
import MkButton from '@/components/MkButton.vue';
import { getPageBlockList } from '@/pages/page-editor/common.js';

const XBlocks = defineAsyncComponent(() => import('../page-editor.blocks.vue'));

Expand All @@ -53,11 +54,9 @@ watch(children, () => {
deep: true,
});

const getPageBlockList = inject<(any) => any>('getPageBlockList');

async function rename() {
const { canceled, result: title } = await os.inputText({
title: 'Enter title',
title: i18n.ts._pages.enterSectionTitle,
default: props.modelValue.title,
});
if (canceled) return;
Expand Down
11 changes: 1 addition & 10 deletions packages/frontend/src/pages/page-editor/page-editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { $i } from '@/account.js';
import { mainRouter } from '@/router/main.js';
import { getPageBlockList } from '@/pages/page-editor/common.js';

const props = defineProps<{
initPageId?: string;
Expand All @@ -101,7 +102,6 @@ const alignCenter = ref(false);
const hideTitleWhenPinned = ref(false);

provide('readonly', readonly.value);
provide('getPageBlockList', getPageBlockList);

watch(eyeCatchingImageId, async () => {
if (eyeCatchingImageId.value == null) {
Expand Down Expand Up @@ -216,15 +216,6 @@ async function add() {
content.value.push({ id, type });
}

function getPageBlockList() {
return [
{ value: 'section', text: i18n.ts._pages.blocks.section },
{ value: 'text', text: i18n.ts._pages.blocks.text },
{ value: 'image', text: i18n.ts._pages.blocks.image },
{ value: 'note', text: i18n.ts._pages.blocks.note },
];
}

function setEyeCatchingImage(img) {
selectFile(img.currentTarget ?? img.target, null).then(file => {
eyeCatchingImageId.value = file.id;
Expand Down
24 changes: 20 additions & 4 deletions packages/frontend/src/pages/timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>

<script lang="ts" setup>
import { computed, watch, provide, shallowRef, ref } from 'vue';
import { computed, watch, provide, shallowRef, ref, onMounted, onActivated } from 'vue';
import type { Tab } from '@/components/global/MkPageHeader.tabs.vue';
import MkTimeline from '@/components/MkTimeline.vue';
import MkInfo from '@/components/MkInfo.vue';
Expand All @@ -53,15 +53,18 @@ import { deepMerge } from '@/scripts/merge.js';
import { MenuItem } from '@/types/menu.js';
import { miLocalStorage } from '@/local-storage.js';
import { availableBasicTimelines, hasWithReplies, isAvailableBasicTimeline, isBasicTimeline, basicTimelineIconClass } from '@/timelines.js';

import type { BasicTimelineType } from '@/timelines.js';

provide('shouldOmitHeaderTitle', true);

const tlComponent = shallowRef<InstanceType<typeof MkTimeline>>();
const rootEl = shallowRef<HTMLElement>();

type TimelinePageSrc = BasicTimelineType | `list:${string}`;

const queue = ref(0);
const srcWhenNotSignin = ref<'local' | 'global'>(isAvailableBasicTimeline('local') ? 'local' : 'global');
const src = computed<'home' | 'local' | 'social' | 'global' | `list:${string}`>({
const src = computed<TimelinePageSrc>({
get: () => ($i ? defaultStore.reactiveState.tl.value.src : srcWhenNotSignin.value),
set: (x) => saveSrc(x),
});
Expand Down Expand Up @@ -195,7 +198,7 @@ async function chooseChannel(ev: MouseEvent): Promise<void> {
os.popupMenu(items, ev.currentTarget ?? ev.target);
}

function saveSrc(newSrc: 'home' | 'local' | 'social' | 'global' | `list:${string}`): void {
function saveSrc(newSrc: TimelinePageSrc): void {
const out = deepMerge({ src: newSrc }, defaultStore.state.tl);

if (newSrc.startsWith('userList:')) {
Expand Down Expand Up @@ -236,6 +239,19 @@ function closeTutorial(): void {
defaultStore.set('timelineTutorials', before);
}

function switchTlIfNeeded() {
if (isBasicTimeline(src.value) && !availableBasicTimelines().includes(src.value)) {
src.value = availableBasicTimelines()[0];
}
}

onMounted(() => {
switchTlIfNeeded();
});
onActivated(() => {
switchTlIfNeeded();
});

const headerActions = computed(() => {
const tmp = [
{
Expand Down
3 changes: 3 additions & 0 deletions packages/misskey-js/etc/misskey-js.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2832,6 +2832,9 @@ type ReversiShowGameResponse = operations['reversi___show-game']['responses']['2
// @public (undocumented)
type ReversiSurrenderRequest = operations['reversi___surrender']['requestBody']['content']['application/json'];

// @public (undocumented)
export const reversiUpdateKeys: ["map", "bw", "isLlotheo", "canPutEverywhere", "loopedBoard", "timeLimitForEachTurn"];

// @public (undocumented)
type ReversiVerifyRequest = operations['reversi___verify']['requestBody']['content']['application/json'];

Expand Down
13 changes: 9 additions & 4 deletions packages/misskey-js/src/consts.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import type { operations } from './autogen/types.js';
import type {
AbuseReportNotificationRecipient, Ad,
AbuseReportNotificationRecipient,
Ad,
Announcement,
EmojiDetailed, InviteCode,
EmojiDetailed,
InviteCode,
MetaDetailed,
Note,
Role, SystemWebhook, UserLite,
Role,
ReversiGameDetailed,
SystemWebhook,
UserLite,
} from './autogen/models.js';

export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'roleAssigned', 'achievementEarned'] as const;
Expand Down Expand Up @@ -160,7 +165,7 @@ export const reversiUpdateKeys = [
'canPutEverywhere',
'loopedBoard',
'timeLimitForEachTurn',
] as const;
] as const satisfies (keyof ReversiGameDetailed)[];

export type ReversiUpdateKey = typeof reversiUpdateKeys[number];

Expand Down
1 change: 1 addition & 0 deletions packages/misskey-js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const mutedNoteReasons = consts.mutedNoteReasons;
export const followingVisibilities = consts.followingVisibilities;
export const followersVisibilities = consts.followersVisibilities;
export const moderationLogTypes = consts.moderationLogTypes;
export const reversiUpdateKeys = consts.reversiUpdateKeys;

// api extractor not supported yet
//export * as api from './api.js';
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f94f732

Please sign in to comment.