parent
eb5781465b
commit
54630edb0f
@ -22,6 +22,7 @@
|
|||||||
- ロールの並び順を設定可能に
|
- ロールの並び順を設定可能に
|
||||||
- カスタム絵文字にライセンス情報を付与できるように
|
- カスタム絵文字にライセンス情報を付与できるように
|
||||||
- 指定した文字列を含む投稿の公開範囲をホームにできるように
|
- 指定した文字列を含む投稿の公開範囲をホームにできるように
|
||||||
|
- 使われてないアンテナは自動停止されるように
|
||||||
|
|
||||||
### Client
|
### Client
|
||||||
- 設定から自分のロールを確認できるように
|
- 設定から自分のロールを確認できるように
|
||||||
|
17
packages/backend/migration/1679309757174-antenna-active.js
Normal file
17
packages/backend/migration/1679309757174-antenna-active.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
export class antennaActive1679309757174 {
|
||||||
|
name = 'antennaActive1679309757174'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "antenna" ADD "lastUsedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT 'now'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "antenna" ADD "isActive" boolean NOT NULL DEFAULT true`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_084c2abb8948ef59a37dce6ac1" ON "antenna" ("lastUsedAt") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_36ef5192a1ce55ed0e40aa4db5" ON "antenna" ("isActive") `);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_36ef5192a1ce55ed0e40aa4db5"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_084c2abb8948ef59a37dce6ac1"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "isActive"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "lastUsedAt"`);
|
||||||
|
}
|
||||||
|
}
|
@ -71,12 +71,14 @@ export class AntennaService implements OnApplicationShutdown {
|
|||||||
this.antennas.push({
|
this.antennas.push({
|
||||||
...body,
|
...body,
|
||||||
createdAt: new Date(body.createdAt),
|
createdAt: new Date(body.createdAt),
|
||||||
|
lastUsedAt: new Date(body.lastUsedAt),
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'antennaUpdated':
|
case 'antennaUpdated':
|
||||||
this.antennas[this.antennas.findIndex(a => a.id === body.id)] = {
|
this.antennas[this.antennas.findIndex(a => a.id === body.id)] = {
|
||||||
...body,
|
...body,
|
||||||
createdAt: new Date(body.createdAt),
|
createdAt: new Date(body.createdAt),
|
||||||
|
lastUsedAt: new Date(body.lastUsedAt),
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case 'antennaDeleted':
|
case 'antennaDeleted':
|
||||||
@ -217,7 +219,9 @@ export class AntennaService implements OnApplicationShutdown {
|
|||||||
@bindThis
|
@bindThis
|
||||||
public async getAntennas() {
|
public async getAntennas() {
|
||||||
if (!this.antennasFetched) {
|
if (!this.antennasFetched) {
|
||||||
this.antennas = await this.antennasRepository.find();
|
this.antennas = await this.antennasRepository.findBy({
|
||||||
|
isActive: true,
|
||||||
|
});
|
||||||
this.antennasFetched = true;
|
this.antennasFetched = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ export class AntennaEntityService {
|
|||||||
notify: antenna.notify,
|
notify: antenna.notify,
|
||||||
withReplies: antenna.withReplies,
|
withReplies: antenna.withReplies,
|
||||||
withFile: antenna.withFile,
|
withFile: antenna.withFile,
|
||||||
|
isActive: antenna.isActive,
|
||||||
hasUnreadNote,
|
hasUnreadNote,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,10 @@ export class Antenna {
|
|||||||
})
|
})
|
||||||
public createdAt: Date;
|
public createdAt: Date;
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column('timestamp with time zone')
|
||||||
|
public lastUsedAt: Date;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
@ -83,4 +87,10 @@ export class Antenna {
|
|||||||
|
|
||||||
@Column('boolean')
|
@Column('boolean')
|
||||||
public notify: boolean;
|
public notify: boolean;
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column('boolean', {
|
||||||
|
default: true,
|
||||||
|
})
|
||||||
|
public isActive: boolean;
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,10 @@ export const packedAntennaSchema = {
|
|||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
},
|
},
|
||||||
|
isActive: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
hasUnreadNote: {
|
hasUnreadNote: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { In, LessThan } from 'typeorm';
|
import { In, LessThan } from 'typeorm';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { AntennaNotesRepository, MutedNotesRepository, NotificationsRepository, RoleAssignmentsRepository, UserIpsRepository } from '@/models/index.js';
|
import type { AntennaNotesRepository, AntennasRepository, MutedNotesRepository, NotificationsRepository, RoleAssignmentsRepository, UserIpsRepository } from '@/models/index.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
@ -26,6 +26,9 @@ export class CleanProcessorService {
|
|||||||
@Inject(DI.mutedNotesRepository)
|
@Inject(DI.mutedNotesRepository)
|
||||||
private mutedNotesRepository: MutedNotesRepository,
|
private mutedNotesRepository: MutedNotesRepository,
|
||||||
|
|
||||||
|
@Inject(DI.antennasRepository)
|
||||||
|
private antennasRepository: AntennasRepository,
|
||||||
|
|
||||||
@Inject(DI.antennaNotesRepository)
|
@Inject(DI.antennaNotesRepository)
|
||||||
private antennaNotesRepository: AntennaNotesRepository,
|
private antennaNotesRepository: AntennaNotesRepository,
|
||||||
|
|
||||||
@ -55,8 +58,16 @@ export class CleanProcessorService {
|
|||||||
reason: 'word',
|
reason: 'word',
|
||||||
});
|
});
|
||||||
|
|
||||||
this.antennaNotesRepository.delete({
|
this.mutedNotesRepository.delete({
|
||||||
id: LessThan(this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 90)))),
|
id: LessThan(this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 90)))),
|
||||||
|
reason: 'word',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 7日以上使われてないアンテナを停止
|
||||||
|
this.antennasRepository.update({
|
||||||
|
lastUsedAt: LessThan(new Date(Date.now() - (1000 * 60 * 60 * 24 * 7))),
|
||||||
|
}, {
|
||||||
|
isActive: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const expiredRoleAssignments = await this.roleAssignmentsRepository.createQueryBuilder('assign')
|
const expiredRoleAssignments = await this.roleAssignmentsRepository.createQueryBuilder('assign')
|
||||||
|
@ -103,9 +103,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
const antenna = await this.antennasRepository.insert({
|
const antenna = await this.antennasRepository.insert({
|
||||||
id: this.idService.genId(),
|
id: this.idService.genId(),
|
||||||
createdAt: new Date(),
|
createdAt: now,
|
||||||
|
lastUsedAt: now,
|
||||||
userId: me.id,
|
userId: me.id,
|
||||||
name: ps.name,
|
name: ps.name,
|
||||||
src: ps.src,
|
src: ps.src,
|
||||||
|
@ -101,6 +101,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||||||
this.noteReadService.read(me.id, notes);
|
this.noteReadService.read(me.id, notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.antennasRepository.update(antenna.id, {
|
||||||
|
lastUsedAt: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
return await this.noteEntityService.packMany(notes, me);
|
return await this.noteEntityService.packMany(notes, me);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user