diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2022-03-04 20:23:53 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2022-03-04 20:23:53 +0900 |
| commit | e68278f93e82ba396ea2b1fbe0c7e0231c640421 (patch) | |
| tree | 19fbe3831469e227b949e5f4030599f1aec9e5f5 /packages/backend/src | |
| parent | fix query error (diff) | |
| download | misskey-e68278f93e82ba396ea2b1fbe0c7e0231c640421.tar.gz misskey-e68278f93e82ba396ea2b1fbe0c7e0231c640421.tar.bz2 misskey-e68278f93e82ba396ea2b1fbe0c7e0231c640421.zip | |
feat: 時限ミュート
#7677
Diffstat (limited to 'packages/backend/src')
8 files changed, 58 insertions, 1 deletions
diff --git a/packages/backend/src/models/entities/muting.ts b/packages/backend/src/models/entities/muting.ts index 8cdd2af9d1..b3a7e7a671 100644 --- a/packages/backend/src/models/entities/muting.ts +++ b/packages/backend/src/models/entities/muting.ts @@ -15,6 +15,13 @@ export class Muting { public createdAt: Date; @Index() + @Column('timestamp with time zone', { + nullable: true, + default: null, + }) + public expiresAt: Date | null; + + @Index() @Column({ ...id(), comment: 'The mutee user ID.', diff --git a/packages/backend/src/models/repositories/muting.ts b/packages/backend/src/models/repositories/muting.ts index 6ffecc302a..643e0b68ee 100644 --- a/packages/backend/src/models/repositories/muting.ts +++ b/packages/backend/src/models/repositories/muting.ts @@ -16,6 +16,7 @@ export class MutingRepository extends Repository<Muting> { return await awaitAll({ id: muting.id, createdAt: muting.createdAt.toISOString(), + expiresAt: muting.expiresAt ? muting.expiresAt.toISOString() : null, muteeId: muting.muteeId, mutee: Users.pack(muting.muteeId, me, { detail: true, diff --git a/packages/backend/src/models/schema/muting.ts b/packages/backend/src/models/schema/muting.ts index d75a4fbfed..3ab99e17e7 100644 --- a/packages/backend/src/models/schema/muting.ts +++ b/packages/backend/src/models/schema/muting.ts @@ -12,6 +12,11 @@ export const packedMutingSchema = { optional: false, nullable: false, format: 'date-time', }, + expiresAt: { + type: 'string', + optional: false, nullable: true, + format: 'date-time', + }, muteeId: { type: 'string', optional: false, nullable: false, diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index 94055e9c5a..1b1c21c4f0 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -273,6 +273,11 @@ export default function() { repeat: { cron: '0 0 * * *' }, }); + systemQueue.add('checkExpiredMutings', { + }, { + repeat: { cron: '*/5 * * * *' }, + }); + processSystemQueue(systemQueue); } diff --git a/packages/backend/src/queue/processors/db/export-mute.ts b/packages/backend/src/queue/processors/db/export-mute.ts index 8602e00bff..9fb144abb2 100644 --- a/packages/backend/src/queue/processors/db/export-mute.ts +++ b/packages/backend/src/queue/processors/db/export-mute.ts @@ -7,7 +7,7 @@ import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; import { getFullApAccount } from '@/misc/convert-host.js'; import { Users, Mutings } from '@/models/index.js'; -import { MoreThan } from 'typeorm'; +import { IsNull, MoreThan } from 'typeorm'; import { DbUserJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('export-mute'); @@ -40,6 +40,7 @@ export async function exportMute(job: Bull.Job<DbUserJobData>, done: any): Promi const mutes = await Mutings.find({ where: { muterId: user.id, + expiresAt: IsNull(), ...(cursor ? { id: MoreThan(cursor) } : {}), }, take: 100, diff --git a/packages/backend/src/queue/processors/system/check-expired-mutings.ts b/packages/backend/src/queue/processors/system/check-expired-mutings.ts new file mode 100644 index 0000000000..621269e7e1 --- /dev/null +++ b/packages/backend/src/queue/processors/system/check-expired-mutings.ts @@ -0,0 +1,30 @@ +import Bull from 'bull'; +import { In } from 'typeorm'; +import { Mutings } from '@/models/index.js'; +import { queueLogger } from '../../logger.js'; +import { publishUserEvent } from '@/services/stream.js'; + +const logger = queueLogger.createSubLogger('check-expired-mutings'); + +export async function checkExpiredMutings(job: Bull.Job<Record<string, unknown>>, done: any): Promise<void> { + logger.info(`Checking expired mutings...`); + + const expired = await Mutings.createQueryBuilder('muting') + .where('muting.expiresAt IS NOT NULL') + .andWhere('muting.expiresAt < :now', { now: new Date() }) + .innerJoinAndSelect('muting.mutee', 'mutee') + .getMany(); + + if (expired.length > 0) { + await Mutings.delete({ + id: In(expired.map(m => m.id)), + }); + + for (const m of expired) { + publishUserEvent(m.muterId, 'unmute', m.mutee!); + } + } + + logger.succ(`All expired mutings checked.`); + done(); +} diff --git a/packages/backend/src/queue/processors/system/index.ts b/packages/backend/src/queue/processors/system/index.ts index dca3249e82..f90f6efafd 100644 --- a/packages/backend/src/queue/processors/system/index.ts +++ b/packages/backend/src/queue/processors/system/index.ts @@ -2,11 +2,13 @@ import Bull from 'bull'; import { tickCharts } from './tick-charts.js'; import { resyncCharts } from './resync-charts.js'; import { cleanCharts } from './clean-charts.js'; +import { checkExpiredMutings } from './check-expired-mutings.js'; const jobs = { tickCharts, resyncCharts, cleanCharts, + checkExpiredMutings, } as Record<string, Bull.ProcessCallbackFunction<Record<string, unknown>> | Bull.ProcessPromiseFunction<Record<string, unknown>>>; export default function(dbQueue: Bull.Queue<Record<string, unknown>>) { diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts index 0178aab143..dacee40d01 100644 --- a/packages/backend/src/server/api/endpoints/mute/create.ts +++ b/packages/backend/src/server/api/endpoints/mute/create.ts @@ -38,6 +38,7 @@ export const paramDef = { type: 'object', properties: { userId: { type: 'string', format: 'misskey:id' }, + expiresAt: { type: 'integer', nullable: true }, }, required: ['userId'], } as const; @@ -67,10 +68,15 @@ export default define(meta, paramDef, async (ps, user) => { throw new ApiError(meta.errors.alreadyMuting); } + if (ps.expiresAt && ps.expiresAt <= Date.now()) { + return; + } + // Create mute await Mutings.insert({ id: genId(), createdAt: new Date(), + expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null, muterId: muter.id, muteeId: mutee.id, } as Muting); |