Merge upstream (Misskey.io)
This commit is contained in:
commit
8bd86ce456
42 changed files with 564 additions and 71 deletions
|
@ -6,11 +6,10 @@
|
|||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import ms from 'ms';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import type { RenoteMutingsRepository } from '@/models/_.js';
|
||||
import type { MiRenoteMuting } from '@/models/RenoteMuting.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { UserRenoteMutingService } from '@/core/UserRenoteMutingService.js';
|
||||
import type { RenoteMutingsRepository } from '@/models/_.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
|
@ -64,7 +63,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
private renoteMutingsRepository: RenoteMutingsRepository,
|
||||
|
||||
private getterService: GetterService,
|
||||
private idService: IdService,
|
||||
private userRenoteMutingService: UserRenoteMutingService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const muter = me;
|
||||
|
@ -81,21 +80,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
});
|
||||
|
||||
// Check if already muting
|
||||
const exist = await this.renoteMutingsRepository.findOneBy({
|
||||
muterId: muter.id,
|
||||
muteeId: mutee.id,
|
||||
const exist = await this.renoteMutingsRepository.exists({
|
||||
where: {
|
||||
muterId: muter.id,
|
||||
muteeId: mutee.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (exist != null) {
|
||||
if (exist) {
|
||||
throw new ApiError(meta.errors.alreadyMuting);
|
||||
}
|
||||
|
||||
// Create mute
|
||||
await this.renoteMutingsRepository.insert({
|
||||
id: this.idService.gen(),
|
||||
muterId: muter.id,
|
||||
muteeId: mutee.id,
|
||||
} as MiRenoteMuting);
|
||||
await this.userRenoteMutingService.mute(muter, mutee);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import { QueryService } from '@/core/QueryService.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['role', 'users'],
|
||||
|
@ -92,10 +93,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
.limit(ps.limit)
|
||||
.getMany();
|
||||
|
||||
return await Promise.all(assigns.map(async assign => ({
|
||||
return (await Promise.allSettled(assigns.map(async assign => ({
|
||||
id: assign.id,
|
||||
user: await this.userEntityService.pack(assign.user!, me, { schema: 'UserDetailed' }),
|
||||
})));
|
||||
}))))
|
||||
.filter((result): result is PromiseFulfilledResult<{ id: string; user: Packed<'UserDetailed'> }> => result.status === 'fulfilled')
|
||||
.map(result => result.value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import type { UsersRepository } from '@/models/_.js';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import PerUserPvChart from '@/core/chart/charts/per-user-pv.js';
|
||||
import { QueryService } from '@/core/QueryService.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
|
@ -31,7 +32,7 @@ export const paramDef = {
|
|||
properties: {
|
||||
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
|
||||
offset: { type: 'integer', default: 0 },
|
||||
sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] },
|
||||
sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt', '+pv', '-pv'] },
|
||||
state: { type: 'string', enum: ['all', 'alive'], default: 'all' },
|
||||
origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'local' },
|
||||
hostname: {
|
||||
|
@ -49,6 +50,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
constructor(
|
||||
@Inject(DI.usersRepository)
|
||||
private usersRepository: UsersRepository,
|
||||
private perUserPvChart: PerUserPvChart,
|
||||
|
||||
private userEntityService: UserEntityService,
|
||||
private queryService: QueryService,
|
||||
|
@ -70,7 +72,12 @@ 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; }[] = [];
|
||||
if (ps.sort?.endsWith('pv')) {
|
||||
await this.perUserPvChart.getChartUsers('hour', 0, null, ps.limit, ps.offset).then(users => {
|
||||
chartUsers.push(...users);
|
||||
});
|
||||
}
|
||||
switch (ps.sort) {
|
||||
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
|
||||
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
|
||||
|
@ -78,6 +85,16 @@ 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;
|
||||
default: query.orderBy('user.id', 'ASC'); break;
|
||||
}
|
||||
|
||||
|
@ -88,6 +105,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
query.offset(ps.offset);
|
||||
|
||||
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;
|
||||
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;
|
||||
return aPv - bPv;
|
||||
});
|
||||
}
|
||||
|
||||
return await this.userEntityService.packMany(users, me, { schema: 'UserDetailed' });
|
||||
});
|
||||
|
|
|
@ -14,6 +14,7 @@ import { GetterService } from '@/server/api/GetterService.js';
|
|||
import { CacheService } from '@/core/CacheService.js';
|
||||
import { isUserRelated } from '@/misc/is-user-related.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { Packed } from '@/misc/json-schema.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['users'],
|
||||
|
@ -131,10 +132,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit);
|
||||
|
||||
// Make replies object (includes weights)
|
||||
const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({
|
||||
const repliesObj = (await Promise.allSettled(topRepliedUsers.map(async (user) => ({
|
||||
user: await this.userEntityService.pack(user, me, { schema: 'UserDetailed' }),
|
||||
weight: repliedUsers[user] / peak,
|
||||
})));
|
||||
}))))
|
||||
.filter((result): result is PromiseFulfilledResult<{ user: Packed<'UserDetailed'>; weight: number }> => result.status === 'fulfilled')
|
||||
.map(result => result.value);
|
||||
|
||||
return repliesObj;
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue