feat: 通報の即時解決機能を追加 (#113)
* feat: 通報の即時解決機能を追加 * fix: 条件変更時に有効期限を変更していないのに勝手に更新される問題を修正 * fix: 条件のパターンの削除ができない問題を修正 * fix: リソルバーの通報を解決する判定基準が間違っていたのを修正 * fix: 変更する変数が間違っていたのを修正 * fix: getUTCMonthはゼロ始まりかも * enhance: Storybookのストーリーを作成 * fix: 色々修正 * fix: 型エラーを修正 * [ci skip] Update CHANGELOG.md * [ci skip] Update CHANGELOG.md * Update CHANGELOG.md * リファクタリング * refactor: 型定義をよりよくした * refactor: beforeExpiresAtの初期値はundefinedの方がいい * refactor: 変数の名前を変更 * Fix: リモートサーバーから転送された通報も対象に追加 * Update CHANGELOG.md * take review --------- Co-authored-by: Chocolate Pie <106949016+chocolate-pie@users.noreply.github.com>
This commit is contained in:
parent
27f57b031b
commit
0bed053b7d
29 changed files with 1059 additions and 44 deletions
|
@ -0,0 +1,114 @@
|
|||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { MoreThan, IsNull } from 'typeorm';
|
||||
import RE2 from 're2';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type Logger from '@/logger.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { EmailService } from '@/core/EmailService.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import { InstanceActorService } from '@/core/InstanceActorService.js';
|
||||
import type { AbuseReportResolversRepository, AbuseUserReportsRepository, UsersRepository } from '@/models/index.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
||||
import { QueueService } from '@/core/QueueService.js';
|
||||
import { QueueLoggerService } from '../QueueLoggerService.js';
|
||||
import type { DbAbuseReportJobData } from '../types.js';
|
||||
import type * as Bull from 'bullmq';
|
||||
|
||||
@Injectable()
|
||||
export class ReportAbuseProcessorService {
|
||||
private logger: Logger;
|
||||
|
||||
constructor(
|
||||
@Inject(DI.abuseReportResolversRepository)
|
||||
private abuseReportResolversRepository: AbuseReportResolversRepository,
|
||||
|
||||
@Inject(DI.abuseUserReportsRepository)
|
||||
private abuseUserReportsRepository: AbuseUserReportsRepository,
|
||||
|
||||
@Inject(DI.usersRepository)
|
||||
private usersRepository: UsersRepository,
|
||||
|
||||
private queueLoggerService: QueueLoggerService,
|
||||
private globalEventService: GlobalEventService,
|
||||
private instanceActorService: InstanceActorService,
|
||||
private apRendererService: ApRendererService,
|
||||
private roleService: RoleService,
|
||||
private metaService: MetaService,
|
||||
private emailService: EmailService,
|
||||
private queueService: QueueService,
|
||||
) {
|
||||
this.logger = this.queueLoggerService.logger.createSubLogger('report-abuse');
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async process(job: Bull.Job<DbAbuseReportJobData>): Promise<void> {
|
||||
this.logger.info('Running...');
|
||||
|
||||
const resolvers = await this.abuseReportResolversRepository.find({
|
||||
where: [
|
||||
{ expirationDate: MoreThan(new Date()) },
|
||||
{ expirationDate: IsNull() },
|
||||
],
|
||||
});
|
||||
|
||||
const targetUser = await this.usersRepository.findOneByOrFail({
|
||||
id: job.data.targetUserId,
|
||||
});
|
||||
|
||||
const reporter = await this.usersRepository.findOneByOrFail({
|
||||
id: job.data.reporterId,
|
||||
});
|
||||
|
||||
const actor = await this.instanceActorService.getInstanceActor();
|
||||
|
||||
const targetUserAcct = targetUser.host ? `${targetUser.username.toLowerCase()}@${targetUser.host}` : targetUser.username.toLowerCase();
|
||||
const reporterAcct = reporter.host ? `${reporter.username.toLowerCase()}@${reporter.host}` : reporter.username.toLowerCase();
|
||||
|
||||
for (const resolver of resolvers) {
|
||||
if (!(resolver.targetUserPattern || resolver.reporterPattern || resolver.reportContentPattern)) {
|
||||
continue;
|
||||
}
|
||||
const isTargetUserPatternMatched = resolver.targetUserPattern ? new RE2(resolver.targetUserPattern).test(targetUserAcct) : true;
|
||||
const isReporterPatternMatched = resolver.reporterPattern ? new RE2(resolver.reporterPattern).test(reporterAcct) : true;
|
||||
const isReportContentPatternMatched = resolver.reportContentPattern ? new RE2(resolver.reportContentPattern).test(job.data.comment) : true;
|
||||
|
||||
if (isTargetUserPatternMatched && isReporterPatternMatched && isReportContentPatternMatched) {
|
||||
if (resolver.forward && job.data.targetUserHost !== null) {
|
||||
this.queueService.deliver(actor, this.apRendererService.addContext(this.apRendererService.renderFlag(actor, targetUser.uri!, job.data.comment)), targetUser.inbox, false);
|
||||
}
|
||||
|
||||
await this.abuseUserReportsRepository.update(job.data.id, {
|
||||
resolved: true,
|
||||
assigneeId: actor.id,
|
||||
forwarded: resolver.forward && job.data.targetUserHost !== null,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Publish event to moderators
|
||||
setImmediate(async () => {
|
||||
const moderators = await this.roleService.getModerators();
|
||||
|
||||
for (const moderator of moderators) {
|
||||
this.globalEventService.publishAdminStream(moderator.id, 'newAbuseUserReport', {
|
||||
id: job.data.id,
|
||||
targetUserId: job.data.targetUserId,
|
||||
reporterId: job.data.reporterId,
|
||||
comment: job.data.comment,
|
||||
});
|
||||
}
|
||||
|
||||
const meta = await this.metaService.fetch();
|
||||
if (meta.email) {
|
||||
this.emailService.sendEmail(meta.email, 'New abuse report',
|
||||
sanitizeHtml(job.data.comment),
|
||||
sanitizeHtml(job.data.comment));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue