kill any from streaming API Implementation (#14251)
* chore: add JsonValue type * refactor: kill any from Connection.ts * refactor: fix StreamEventEmitter contains undefined instead of null * refactor: kill any from channels * docs(changelog): Fix: Steaming APIが不正なデータを受けた場合の動作が不安定である問題 * fix license header * fix lints
This commit is contained in:
parent
ec1c392f1e
commit
10ce7bf3c4
21 changed files with 155 additions and 83 deletions
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class AdminChannel extends Channel {
|
||||
|
|
@ -14,7 +15,7 @@ class AdminChannel extends Channel {
|
|||
public static kind = 'read:admin:stream';
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
// Subscribe admin stream
|
||||
this.subscriber.on(`adminStream:${this.user!.id}`, data => {
|
||||
this.send(data);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { Injectable } from '@nestjs/common';
|
|||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class AntennaChannel extends Channel {
|
||||
|
|
@ -27,8 +28,9 @@ class AntennaChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
this.antennaId = params.antennaId as string;
|
||||
public async init(params: JsonObject) {
|
||||
if (typeof params.antennaId !== 'string') return;
|
||||
this.antennaId = params.antennaId;
|
||||
|
||||
// Subscribe stream
|
||||
this.subscriber.on(`antennaStream:${this.antennaId}`, this.onEvent);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import type { Packed } from '@/misc/json-schema.js';
|
|||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class ChannelChannel extends Channel {
|
||||
|
|
@ -27,8 +28,9 @@ class ChannelChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
this.channelId = params.channelId as string;
|
||||
public async init(params: JsonObject) {
|
||||
if (typeof params.channelId !== 'string') return;
|
||||
this.channelId = params.channelId;
|
||||
|
||||
// Subscribe stream
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class DriveChannel extends Channel {
|
||||
|
|
@ -14,7 +15,7 @@ class DriveChannel extends Channel {
|
|||
public static kind = 'read:account';
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
// Subscribe drive stream
|
||||
this.subscriber.on(`driveStream:${this.user!.id}`, data => {
|
||||
this.send(data);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class GlobalTimelineChannel extends Channel {
|
||||
|
|
@ -32,12 +33,12 @@ class GlobalTimelineChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null);
|
||||
if (!policies.gtlAvailable) return;
|
||||
|
||||
this.withRenotes = params.withRenotes ?? true;
|
||||
this.withFiles = params.withFiles ?? false;
|
||||
this.withRenotes = !!(params.withRenotes ?? true);
|
||||
this.withFiles = !!(params.withFiles ?? false);
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import type { Packed } from '@/misc/json-schema.js';
|
|||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class HashtagChannel extends Channel {
|
||||
|
|
@ -28,11 +29,11 @@ class HashtagChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
if (!Array.isArray(params.q)) return;
|
||||
if (!params.q.every(x => Array.isArray(x) && x.every(y => typeof y === 'string'))) return;
|
||||
this.q = params.q;
|
||||
|
||||
if (this.q == null) return;
|
||||
|
||||
// Subscribe stream
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import type { Packed } from '@/misc/json-schema.js';
|
|||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class HomeTimelineChannel extends Channel {
|
||||
|
|
@ -29,9 +30,9 @@ class HomeTimelineChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
this.withRenotes = params.withRenotes ?? true;
|
||||
this.withFiles = params.withFiles ?? false;
|
||||
public async init(params: JsonObject) {
|
||||
this.withRenotes = !!(params.withRenotes ?? true);
|
||||
this.withFiles = !!(params.withFiles ?? false);
|
||||
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class HybridTimelineChannel extends Channel {
|
||||
|
|
@ -34,13 +35,13 @@ class HybridTimelineChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any): Promise<void> {
|
||||
public async init(params: JsonObject): Promise<void> {
|
||||
const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null);
|
||||
if (!policies.ltlAvailable) return;
|
||||
|
||||
this.withRenotes = params.withRenotes ?? true;
|
||||
this.withReplies = params.withReplies ?? false;
|
||||
this.withFiles = params.withFiles ?? false;
|
||||
this.withRenotes = !!(params.withRenotes ?? true);
|
||||
this.withReplies = !!(params.withReplies ?? false);
|
||||
this.withFiles = !!(params.withFiles ?? false);
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { isQuotePacked, isRenotePacked } from '@/misc/is-renote.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class LocalTimelineChannel extends Channel {
|
||||
|
|
@ -33,13 +34,13 @@ class LocalTimelineChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null);
|
||||
if (!policies.ltlAvailable) return;
|
||||
|
||||
this.withRenotes = params.withRenotes ?? true;
|
||||
this.withReplies = params.withReplies ?? false;
|
||||
this.withFiles = params.withFiles ?? false;
|
||||
this.withRenotes = !!(params.withRenotes ?? true);
|
||||
this.withReplies = !!(params.withReplies ?? false);
|
||||
this.withFiles = !!(params.withFiles ?? false);
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { Injectable } from '@nestjs/common';
|
|||
import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted.js';
|
||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class MainChannel extends Channel {
|
||||
|
|
@ -25,7 +26,7 @@ class MainChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
// Subscribe main stream channel
|
||||
this.subscriber.on(`mainStream:${this.user!.id}`, async data => {
|
||||
switch (data.type) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
import Xev from 'xev';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
const ev = new Xev();
|
||||
|
|
@ -22,19 +23,22 @@ class QueueStatsChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
ev.addListener('queueStats', this.onStats);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private onStats(stats: any) {
|
||||
private onStats(stats: JsonObject) {
|
||||
this.send('stats', stats);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onMessage(type: string, body: any) {
|
||||
public onMessage(type: string, body: JsonValue) {
|
||||
switch (type) {
|
||||
case 'requestLog':
|
||||
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
|
||||
if (typeof body.id !== 'string') return;
|
||||
if (typeof body.length !== 'number') return;
|
||||
ev.once(`queueStatsLog:${body.id}`, statsLog => {
|
||||
this.send('statsLog', statsLog);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { DI } from '@/di-symbols.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { ReversiService } from '@/core/ReversiService.js';
|
||||
import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
|
||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class ReversiGameChannel extends Channel {
|
||||
|
|
@ -28,25 +29,41 @@ class ReversiGameChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
this.gameId = params.gameId as string;
|
||||
public async init(params: JsonObject) {
|
||||
if (typeof params.gameId !== 'string') return;
|
||||
this.gameId = params.gameId;
|
||||
|
||||
this.subscriber.on(`reversiGameStream:${this.gameId}`, this.send);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onMessage(type: string, body: any) {
|
||||
public onMessage(type: string, body: JsonValue) {
|
||||
switch (type) {
|
||||
case 'ready': this.ready(body); break;
|
||||
case 'updateSettings': this.updateSettings(body.key, body.value); break;
|
||||
case 'cancel': this.cancelGame(); break;
|
||||
case 'putStone': this.putStone(body.pos, body.id); break;
|
||||
case 'ready':
|
||||
if (typeof body !== 'boolean') return;
|
||||
this.ready(body);
|
||||
break;
|
||||
case 'updateSettings':
|
||||
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
|
||||
if (typeof body.key !== 'string') return;
|
||||
if (typeof body.value !== 'object' || body.value === null || Array.isArray(body.value)) return;
|
||||
this.updateSettings(body.key, body.value);
|
||||
break;
|
||||
case 'cancel':
|
||||
this.cancelGame();
|
||||
break;
|
||||
case 'putStone':
|
||||
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
|
||||
if (typeof body.pos !== 'number') return;
|
||||
if (typeof body.id !== 'string') return;
|
||||
this.putStone(body.pos, body.id);
|
||||
break;
|
||||
case 'claimTimeIsUp': this.claimTimeIsUp(); break;
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private async updateSettings(key: string, value: any) {
|
||||
private async updateSettings(key: string, value: JsonObject) {
|
||||
if (this.user == null) return;
|
||||
|
||||
this.reversiService.updateSettings(this.gameId!, this.user, key, value);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class ReversiChannel extends Channel {
|
||||
|
|
@ -21,7 +22,7 @@ class ReversiChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
this.subscriber.on(`reversiStream:${this.user!.id}`, this.send);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class RoleTimelineChannel extends Channel {
|
||||
|
|
@ -28,8 +29,9 @@ class RoleTimelineChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
this.roleId = params.roleId as string;
|
||||
public async init(params: JsonObject) {
|
||||
if (typeof params.roleId !== 'string') return;
|
||||
this.roleId = params.roleId;
|
||||
|
||||
this.subscriber.on(`roleTimelineStream:${this.roleId}`, this.onEvent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
import Xev from 'xev';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
const ev = new Xev();
|
||||
|
|
@ -22,19 +23,20 @@ class ServerStatsChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
public async init(params: JsonObject) {
|
||||
ev.addListener('serverStats', this.onStats);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private onStats(stats: any) {
|
||||
private onStats(stats: JsonObject) {
|
||||
this.send('stats', stats);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onMessage(type: string, body: any) {
|
||||
public onMessage(type: string, body: JsonValue) {
|
||||
switch (type) {
|
||||
case 'requestLog':
|
||||
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
|
||||
ev.once(`serverStatsLog:${body.id}`, statsLog => {
|
||||
this.send('statsLog', statsLog);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||
import type { JsonObject } from '@/misc/json-value.js';
|
||||
import Channel, { type MiChannelService } from '../channel.js';
|
||||
|
||||
class UserListChannel extends Channel {
|
||||
|
|
@ -36,10 +37,11 @@ class UserListChannel extends Channel {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async init(params: any) {
|
||||
this.listId = params.listId as string;
|
||||
this.withFiles = params.withFiles ?? false;
|
||||
this.withRenotes = params.withRenotes ?? true;
|
||||
public async init(params: JsonObject) {
|
||||
if (typeof params.listId !== 'string') return;
|
||||
this.listId = params.listId;
|
||||
this.withFiles = !!(params.withFiles ?? false);
|
||||
this.withRenotes = !!(params.withRenotes ?? true);
|
||||
|
||||
// Check existence and owner
|
||||
const listExist = await this.userListsRepository.exists({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue