Merge upstream

This commit is contained in:
무라쿠모 2024-09-18 00:11:23 +09:00
commit 4b6cbdab39
No known key found for this signature in database
GPG key ID: 139D6573F92DA9F7
73 changed files with 1199 additions and 356 deletions

View file

@ -97,6 +97,11 @@ export const meta = {
type: 'number',
optional: false, nullable: false,
},
lastReadAt: {
type: 'string',
optional: false, nullable: true,
format: 'date-time',
},
},
},
},
@ -140,6 +145,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
userId: announcement.userId,
user: announcement.userInfo,
reads: announcement.reads,
lastReadAt: announcement.lastReadAt?.toISOString() ?? null,
}));
});
}

View file

@ -0,0 +1,94 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
import { DI } from '@/di-symbols.js';
import type { UserAccountMoveLogRepository } from '@/models/_.js';
import { UserAccountMoveLogEntityService } from '@/core/entities/UserAccountMoveLogEntityService.js';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,
kind: 'read:admin:show-account-move-log',
res: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
optional: false, nullable: false,
properties: {
id: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
createdAt: {
type: 'string',
optional: false, nullable: false,
format: 'date-time',
},
movedToId: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
movedTo: {
type: 'object',
optional: false, nullable: false,
ref: 'UserDetailed',
},
movedFromId: {
type: 'string',
optional: false, nullable: false,
format: 'id',
},
movedFrom: {
type: 'object',
optional: false, nullable: false,
ref: 'UserDetailed',
},
},
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
movedFromId: { type: 'string', format: 'misskey:id', nullable: true },
movedToId: { type: 'string', format: 'misskey:id', nullable: true },
},
required: [],
} as const;
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
@Inject(DI.userAccountMoveLogRepository)
private userAccountMoveLogRepository: UserAccountMoveLogRepository,
private userAccountMoveLogEntityService: UserAccountMoveLogEntityService,
private queryService: QueryService,
) {
super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.userAccountMoveLogRepository.createQueryBuilder('accountMoveLogs'), ps.sinceId, ps.untilId);
if (ps.movedFromId != null) {
query.andWhere('accountMoveLogs.movedFromId = :movedFromId', { movedFromId: ps.movedFromId });
}
if (ps.movedToId != null) {
query.andWhere('accountMoveLogs.movedToId = :movedToId', { movedToId: ps.movedToId });
}
const accountMoveLogs = await query.limit(ps.limit).getMany();
return await this.userAccountMoveLogEntityService.packMany(accountMoveLogs, me);
});
}
}

View file

@ -72,12 +72,16 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (ps.hostname) {
query.andWhere('user.host = :hostname', { hostname: ps.hostname.toLowerCase() });
}
const chartUsers: { userId: string; count: number; }[] = [];
let pvRankedUsers: { userId: string; count: number; }[] | undefined = undefined;
if (ps.sort?.endsWith('pv')) {
await this.perUserPvChart.getChartUsers('hour', 0, null, ps.limit, ps.offset).then(users => {
chartUsers.push(...users);
});
// 直近12時間のPVランキングを取得
pvRankedUsers = await this.perUserPvChart.getUsersRanking(
'hour', ps.sort.startsWith('+') ? 'DESC' : 'ASC',
12, null, ps.limit, ps.offset,
);
}
switch (ps.sort) {
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
@ -85,16 +89,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
case '-createdAt': query.orderBy('user.id', 'ASC'); break;
case '+updatedAt': query.andWhere('user.updatedAt IS NOT NULL').orderBy('user.updatedAt', 'DESC'); break;
case '-updatedAt': query.andWhere('user.updatedAt IS NOT NULL').orderBy('user.updatedAt', 'ASC'); break;
case '+pv':
if (chartUsers.length > 0) {
query.andWhere('user.id IN (:...userIds)', { userIds: chartUsers.map(user => user.userId) });
}
break;
case '-pv':
if (chartUsers.length > 0) {
query.andWhere('user.id IN (:...userIds)', { userIds: chartUsers.map(user => user.userId) });
}
break;
case '+pv': query.andWhere((pvRankedUsers?.length ?? 0) > 0 ? 'user.id IN (:...userIds)' : '1 = 0', { userIds: pvRankedUsers?.map(user => user.userId) ?? [] }); break;
case '-pv': query.andWhere((pvRankedUsers?.length ?? 0) > 0 ? 'user.id IN (:...userIds)' : '1 = 0', { userIds: pvRankedUsers?.map(user => user.userId) ?? [] }); break;
default: query.orderBy('user.id', 'ASC'); break;
}
@ -107,14 +103,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const users = await query.getMany();
if (ps.sort === '+pv') {
users.sort((a, b) => {
const aPv = chartUsers.find(user => user.userId === a.id)?.count ?? 0;
const bPv = chartUsers.find(user => user.userId === b.id)?.count ?? 0;
const aPv = pvRankedUsers?.find(u => u.userId === a.id)?.count ?? 0;
const bPv = pvRankedUsers?.find(u => u.userId === b.id)?.count ?? 0;
return bPv - aPv;
});
} else if (ps.sort === '-pv') {
users.sort((a, b) => {
const aPv = chartUsers.find(user => user.userId === a.id)?.count ?? 0;
const bPv = chartUsers.find(user => user.userId === b.id)?.count ?? 0;
const aPv = pvRankedUsers?.find(u => u.userId === a.id)?.count ?? 0;
const bPv = pvRankedUsers?.find(u => u.userId === b.id)?.count ?? 0;
return aPv - bPv;
});
}