mirror of
https://github.com/MisskeyIO/misskey
synced 2024-11-27 22:38:30 +09:00
Merge pull request MisskeyIO#600 from update-host
This commit is contained in:
commit
b8e2d2e1c3
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"version": "2024.3.1-host.5",
|
||||
"version": "2024.3.1-host.5b",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -4,86 +4,127 @@
|
||||
*/
|
||||
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Not, IsNull } from 'typeorm';
|
||||
import type { FollowingsRepository } from '@/models/_.js';
|
||||
import { Not, IsNull, Brackets, DataSource, EntityManager } from 'typeorm';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type Logger from '@/logger.js';
|
||||
import type { MiUser } from '@/models/User.js';
|
||||
import type { FollowingsRepository } from '@/models/_.js';
|
||||
import { QueueService } from '@/core/QueueService.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
|
||||
@Injectable()
|
||||
export class UserSuspendService {
|
||||
public logger: Logger;
|
||||
|
||||
constructor(
|
||||
@Inject(DI.db)
|
||||
private db: DataSource,
|
||||
|
||||
@Inject(DI.followingsRepository)
|
||||
private followingsRepository: FollowingsRepository,
|
||||
|
||||
private userEntityService: UserEntityService,
|
||||
private queueService: QueueService,
|
||||
private globalEventService: GlobalEventService,
|
||||
private apRendererService: ApRendererService,
|
||||
private userEntityService: UserEntityService,
|
||||
private loggerService: LoggerService,
|
||||
) {
|
||||
this.logger = this.loggerService.getLogger('account:suspend');
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async doPostSuspend(user: { id: MiUser['id']; host: MiUser['host'] }): Promise<void> {
|
||||
this.logger.warn(`doPostSuspend: ${user.id} (host: ${user.host})`);
|
||||
|
||||
this.globalEventService.publishInternalEvent('userChangeSuspendedState', { id: user.id, isSuspended: true });
|
||||
|
||||
if (this.userEntityService.isLocalUser(user)) {
|
||||
// 知り得る全SharedInboxにDelete配信
|
||||
const content = this.apRendererService.addContext(this.apRendererService.renderDelete(this.userEntityService.genLocalUserUri(user.id), user));
|
||||
|
||||
const queue: string[] = [];
|
||||
this.logger.info(`Delivering delete activity to all shared inboxes of ${user.id}`);
|
||||
await this.db.transaction(async (transactionalEntityManager: EntityManager) => {
|
||||
const inboxesCte = transactionalEntityManager.createQueryBuilder()
|
||||
.select('distinct coalesce(following.followerSharedInbox, following.followeeSharedInbox)', 'inbox')
|
||||
.from(this.followingsRepository.metadata.targetName, 'following')
|
||||
.where(new Brackets((qb) => qb.where({ followerHost: Not(IsNull()) }).orWhere({ followeeHost: Not(IsNull()) })))
|
||||
.andWhere(new Brackets((qb) => qb.where({ followerSharedInbox: Not(IsNull()) }).orWhere({ followeeSharedInbox: Not(IsNull()) })))
|
||||
.orderBy('inbox');
|
||||
|
||||
const followings = await this.followingsRepository.find({
|
||||
where: [
|
||||
{ followerSharedInbox: Not(IsNull()) },
|
||||
{ followeeSharedInbox: Not(IsNull()) },
|
||||
],
|
||||
select: ['followerSharedInbox', 'followeeSharedInbox'],
|
||||
let offset = 0;
|
||||
let cursor = '';
|
||||
while (true) { // eslint-disable-line @typescript-eslint/no-unnecessary-condition, no-constant-condition
|
||||
const inboxes = await transactionalEntityManager.createQueryBuilder().addCommonTableExpression(inboxesCte, 'inboxes')
|
||||
.select('inbox').from('inboxes', 'inboxes').where('inbox > :cursor', { cursor }).limit(500).getRawMany<{ inbox: string }>()
|
||||
.then((rows) => rows.map((row) => row.inbox));
|
||||
|
||||
if (inboxes.length === 0) break;
|
||||
|
||||
this.logger.info(`Delivering delete activity to ${offset} - ${offset + inboxes.length} shared inboxes of ${user.id}`);
|
||||
for (const inbox of inboxes) {
|
||||
try {
|
||||
this.queueService.deliver(user, content, inbox, true);
|
||||
} catch (err) {
|
||||
this.logger.error(`Failed to deliver delete activity to ${inbox}: ${err}`, { error: err, inbox });
|
||||
}
|
||||
}
|
||||
|
||||
offset += inboxes.length;
|
||||
cursor = inboxes[inboxes.length - 1];
|
||||
}
|
||||
});
|
||||
|
||||
const inboxes = followings.map(x => x.followerSharedInbox ?? x.followeeSharedInbox);
|
||||
|
||||
for (const inbox of inboxes) {
|
||||
if (inbox != null && !queue.includes(inbox)) queue.push(inbox);
|
||||
}
|
||||
|
||||
for (const inbox of queue) {
|
||||
this.queueService.deliver(user, content, inbox, true);
|
||||
}
|
||||
this.logger.info(`Scheduled delete activity delivery to all shared inboxes of ${user.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async doPostUnsuspend(user: MiUser): Promise<void> {
|
||||
this.logger.warn(`doPostUnsuspend: ${user.id}`);
|
||||
|
||||
this.globalEventService.publishInternalEvent('userChangeSuspendedState', { id: user.id, isSuspended: false });
|
||||
|
||||
if (this.userEntityService.isLocalUser(user)) {
|
||||
// 知り得る全SharedInboxにUndo Delete配信
|
||||
const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderDelete(this.userEntityService.genLocalUserUri(user.id), user), user));
|
||||
|
||||
const queue: string[] = [];
|
||||
this.logger.info(`Delivering undo delete activity to all shared inboxes of ${user.id}`);
|
||||
await this.db.transaction(async (transactionalEntityManager: EntityManager) => {
|
||||
const inboxesCte = transactionalEntityManager.createQueryBuilder()
|
||||
.select('distinct coalesce(following.followerSharedInbox, following.followeeSharedInbox)', 'inbox')
|
||||
.from(this.followingsRepository.metadata.targetName, 'following')
|
||||
.where(new Brackets((qb) => qb.where({ followerHost: Not(IsNull()) }).orWhere({ followeeHost: Not(IsNull()) })))
|
||||
.andWhere(new Brackets((qb) => qb.where({ followerSharedInbox: Not(IsNull()) }).orWhere({ followeeSharedInbox: Not(IsNull()) })))
|
||||
.orderBy('inbox');
|
||||
|
||||
const followings = await this.followingsRepository.find({
|
||||
where: [
|
||||
{ followerSharedInbox: Not(IsNull()) },
|
||||
{ followeeSharedInbox: Not(IsNull()) },
|
||||
],
|
||||
select: ['followerSharedInbox', 'followeeSharedInbox'],
|
||||
let offset = 0;
|
||||
let cursor = '';
|
||||
while (true) { // eslint-disable-line @typescript-eslint/no-unnecessary-condition, no-constant-condition
|
||||
const inboxes = await transactionalEntityManager.createQueryBuilder().addCommonTableExpression(inboxesCte, 'inboxes')
|
||||
.select('inbox').from('inboxes', 'inboxes').where('inbox > :cursor', { cursor }).limit(500).getRawMany<{ inbox: string }>()
|
||||
.then((rows) => rows.map((row) => row.inbox));
|
||||
|
||||
if (inboxes.length === 0) break;
|
||||
|
||||
this.logger.info(`Delivering undo delete activity to ${offset} - ${offset + inboxes.length} shared inboxes of ${user.id}`);
|
||||
for (const inbox of inboxes) {
|
||||
try {
|
||||
this.queueService.deliver(user, content, inbox, true);
|
||||
} catch (err) {
|
||||
this.logger.error(`Failed to deliver undo delete activity to ${inbox}: ${err}`, { error: err, inbox });
|
||||
}
|
||||
}
|
||||
|
||||
offset += inboxes.length;
|
||||
cursor = inboxes[inboxes.length - 1];
|
||||
}
|
||||
});
|
||||
|
||||
const inboxes = followings.map(x => x.followerSharedInbox ?? x.followeeSharedInbox);
|
||||
|
||||
for (const inbox of inboxes) {
|
||||
if (inbox != null && !queue.includes(inbox)) queue.push(inbox);
|
||||
}
|
||||
|
||||
for (const inbox of queue) {
|
||||
this.queueService.deliver(user as any, content, inbox, true);
|
||||
}
|
||||
this.logger.info(`Scheduled undo delete activity delivery to all shared inboxes of ${user.id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,16 +134,24 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
|
||||
if (res.status > 299 || (json.error ?? json.ban_reason)) {
|
||||
logger.error('Skeb status response error', { url: url.href, userId: ps.userId, status: res.status, statusText: res.statusText, error: json.error ?? json.ban_reason });
|
||||
if (res.status === 404 && hasSkebRole) await this.roleService.unassign(ps.userId, this.config.skebStatus.roleId);
|
||||
try {
|
||||
if (res.status === 404 && hasSkebRole) await this.roleService.unassign(ps.userId, this.config.skebStatus.roleId);
|
||||
} catch (err) {
|
||||
logger.error('Failed to unassign role', { userId: ps.userId, roleId: this.config.skebStatus.roleId, error: err });
|
||||
}
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
}
|
||||
|
||||
logger.info('Skeb status response', { url: url.href, userId: ps.userId, status: res.status, statusText: res.statusText, skebStatus: json });
|
||||
|
||||
if (json.is_acceptable) {
|
||||
if (!hasSkebRole) await this.roleService.assign(ps.userId, this.config.skebStatus.roleId);
|
||||
} else if (hasSkebRole) {
|
||||
await this.roleService.unassign(ps.userId, this.config.skebStatus.roleId);
|
||||
try {
|
||||
if (json.is_acceptable) {
|
||||
if (!hasSkebRole) await this.roleService.assign(ps.userId, this.config.skebStatus.roleId);
|
||||
} else if (hasSkebRole) {
|
||||
await this.roleService.unassign(ps.userId, this.config.skebStatus.roleId);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Failed to assign/unassign role', { userId: ps.userId, roleId: this.config.skebStatus.roleId, error: err });
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "module",
|
||||
"name": "misskey-js",
|
||||
"version": "2024.3.1-host.5",
|
||||
"version": "2024.3.1-host.5b",
|
||||
"description": "Misskey SDK for JavaScript",
|
||||
"types": "./built/dts/index.d.ts",
|
||||
"exports": {
|
||||
|
Loading…
Reference in New Issue
Block a user