mirror of
https://codeberg.org/yeentown/barkey.git
synced 2025-07-08 21:14:32 +00:00
copy changes to NoteEditService.ts
This commit is contained in:
parent
0e3f2a90cf
commit
ea0371de34
1 changed files with 17 additions and 91 deletions
|
@ -8,6 +8,7 @@ import * as mfm from '@transfem-org/sfm-js';
|
||||||
import { DataSource, In, IsNull, LessThan } from 'typeorm';
|
import { DataSource, In, IsNull, LessThan } from 'typeorm';
|
||||||
import * as Redis from 'ioredis';
|
import * as Redis from 'ioredis';
|
||||||
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
|
||||||
|
import { UnrecoverableError } from 'bullmq';
|
||||||
import { extractMentions } from '@/misc/extract-mentions.js';
|
import { extractMentions } from '@/misc/extract-mentions.js';
|
||||||
import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js';
|
import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js';
|
||||||
import { extractHashtags } from '@/misc/extract-hashtags.js';
|
import { extractHashtags } from '@/misc/extract-hashtags.js';
|
||||||
|
@ -36,7 +37,6 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
||||||
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
|
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
|
||||||
import { NoteReadService } from '@/core/NoteReadService.js';
|
|
||||||
import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
|
import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { RoleService } from '@/core/RoleService.js';
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
|
@ -203,7 +203,6 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
private globalEventService: GlobalEventService,
|
private globalEventService: GlobalEventService,
|
||||||
private queueService: QueueService,
|
private queueService: QueueService,
|
||||||
private fanoutTimelineService: FanoutTimelineService,
|
private fanoutTimelineService: FanoutTimelineService,
|
||||||
private noteReadService: NoteReadService,
|
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
private relayService: RelayService,
|
private relayService: RelayService,
|
||||||
private federatedInstanceService: FederatedInstanceService,
|
private federatedInstanceService: FederatedInstanceService,
|
||||||
|
@ -233,7 +232,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
noindex: MiUser['noindex'];
|
noindex: MiUser['noindex'];
|
||||||
}, editid: MiNote['id'], data: Option, silent = false): Promise<MiNote> {
|
}, editid: MiNote['id'], data: Option, silent = false): Promise<MiNote> {
|
||||||
if (!editid) {
|
if (!editid) {
|
||||||
throw new Error('fail');
|
throw new UnrecoverableError('edit failed: missing editid');
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldnote = await this.notesRepository.findOneBy({
|
const oldnote = await this.notesRepository.findOneBy({
|
||||||
|
@ -241,11 +240,11 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (oldnote == null) {
|
if (oldnote == null) {
|
||||||
throw new Error('no such note');
|
throw new UnrecoverableError('edit failed: missing oldnote');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldnote.userId !== user.id) {
|
if (oldnote.userId !== user.id) {
|
||||||
throw new Error('not the author');
|
throw new UnrecoverableError(`edit failed for ${oldnote.id}: user is not the note author`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we never want to change the replyId, so fetch the original "parent"
|
// we never want to change the replyId, so fetch the original "parent"
|
||||||
|
@ -276,12 +275,12 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
data.channel = await this.channelsRepository.findOneBy({ id: data.reply.channelId });
|
data.channel = await this.channelsRepository.findOneBy({ id: data.reply.channelId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.updatedAt == null) data.updatedAt = new Date();
|
||||||
if (data.visibility == null) data.visibility = 'public';
|
if (data.visibility == null) data.visibility = 'public';
|
||||||
if (data.localOnly == null) data.localOnly = false;
|
if (data.localOnly == null) data.localOnly = false;
|
||||||
if (data.channel != null) data.visibility = 'public';
|
if (data.channel != null) data.visibility = 'public';
|
||||||
if (data.channel != null) data.visibleUsers = [];
|
if (data.channel != null) data.visibleUsers = [];
|
||||||
if (data.channel != null) data.localOnly = true;
|
if (data.channel != null) data.localOnly = true;
|
||||||
if (data.updatedAt == null) data.updatedAt = new Date();
|
|
||||||
|
|
||||||
if (data.visibility === 'public' && data.channel == null) {
|
if (data.visibility === 'public' && data.channel == null) {
|
||||||
const sensitiveWords = this.meta.sensitiveWords;
|
const sensitiveWords = this.meta.sensitiveWords;
|
||||||
|
@ -310,7 +309,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
|
|
||||||
if (this.isRenote(data)) {
|
if (this.isRenote(data)) {
|
||||||
if (data.renote.id === oldnote.id) {
|
if (data.renote.id === oldnote.id) {
|
||||||
throw new Error('A note can\'t renote itself');
|
throw new UnrecoverableError(`edit failed for ${oldnote.id}: cannot renote itself`);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (data.renote.visibility) {
|
switch (data.renote.visibility) {
|
||||||
|
@ -406,10 +405,10 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
|
|
||||||
// Parse MFM if needed
|
// Parse MFM if needed
|
||||||
if (!tags || !emojis || !mentionedUsers) {
|
if (!tags || !emojis || !mentionedUsers) {
|
||||||
const tokens = data.text ? mfm.parse(data.text)! : [];
|
const tokens = data.text ? mfm.parse(data.text) : [];
|
||||||
const cwTokens = data.cw ? mfm.parse(data.cw)! : [];
|
const cwTokens = data.cw ? mfm.parse(data.cw) : [];
|
||||||
const choiceTokens = data.poll && data.poll.choices
|
const choiceTokens = data.poll && data.poll.choices
|
||||||
? concat(data.poll.choices.map(choice => mfm.parse(choice)!))
|
? concat(data.poll.choices.map(choice => mfm.parse(choice)))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const combinedTokens = tokens.concat(cwTokens).concat(choiceTokens);
|
const combinedTokens = tokens.concat(cwTokens).concat(choiceTokens);
|
||||||
|
@ -424,7 +423,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
// if the host is media-silenced, custom emojis are not allowed
|
// if the host is media-silenced, custom emojis are not allowed
|
||||||
if (this.utilityService.isMediaSilencedHost(this.meta.mediaSilencedHosts, user.host)) emojis = [];
|
if (this.utilityService.isMediaSilencedHost(this.meta.mediaSilencedHosts, user.host)) emojis = [];
|
||||||
|
|
||||||
tags = tags.filter(tag => Array.from(tag ?? '').length <= 128).splice(0, 32);
|
tags = tags.filter(tag => Array.from(tag).length <= 128).splice(0, 32);
|
||||||
|
|
||||||
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
|
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
|
||||||
mentionedUsers.push(await this.usersRepository.findOneByOrFail({ id: data.reply!.userId }));
|
mentionedUsers.push(await this.usersRepository.findOneByOrFail({ id: data.reply!.userId }));
|
||||||
|
@ -467,10 +466,8 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
update.hasPoll = !!data.poll;
|
update.hasPoll = !!data.poll;
|
||||||
}
|
}
|
||||||
|
|
||||||
// technically we should check if the two sets of files are
|
// TODO deep-compare files
|
||||||
// different, or if their descriptions have changed. In practice
|
const filesChanged = oldnote.fileIds.length || data.files?.length;
|
||||||
// this is good enough.
|
|
||||||
const filesChanged = oldnote.fileIds?.length || data.files?.length;
|
|
||||||
|
|
||||||
const poll = await this.pollsRepository.findOneBy({ noteId: oldnote.id });
|
const poll = await this.pollsRepository.findOneBy({ noteId: oldnote.id });
|
||||||
|
|
||||||
|
@ -564,7 +561,7 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
noteVisibility: note.visibility,
|
noteVisibility: note.visibility,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
userHost: user.host,
|
userHost: user.host,
|
||||||
channelId: data.channel ? data.channel.id : null,
|
channelId: data.channel?.id ?? null,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!oldnote.hasPoll) {
|
if (!oldnote.hasPoll) {
|
||||||
|
@ -628,44 +625,12 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
if (this.userEntityService.isLocalUser(user)) this.activeUsersChart.write(user);
|
if (this.userEntityService.isLocalUser(user)) this.activeUsersChart.write(user);
|
||||||
|
|
||||||
// 未読通知を作成
|
|
||||||
if (data.visibility === 'specified') {
|
|
||||||
if (data.visibleUsers == null) throw new Error('invalid param');
|
|
||||||
|
|
||||||
for (const u of data.visibleUsers) {
|
|
||||||
// ローカルユーザーのみ
|
|
||||||
if (!this.userEntityService.isLocalUser(u)) continue;
|
|
||||||
|
|
||||||
this.noteReadService.insertNoteUnread(u.id, note, {
|
|
||||||
isSpecified: true,
|
|
||||||
isMentioned: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (const u of mentionedUsers) {
|
|
||||||
// ローカルユーザーのみ
|
|
||||||
if (!this.userEntityService.isLocalUser(u)) continue;
|
|
||||||
|
|
||||||
this.noteReadService.insertNoteUnread(u.id, note, {
|
|
||||||
isSpecified: false,
|
|
||||||
isMentioned: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pack the note
|
// Pack the note
|
||||||
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
|
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
|
||||||
if (data.poll != null) {
|
this.globalEventService.publishNoteStream(note.id, 'updated', {
|
||||||
this.globalEventService.publishNoteStream(note.id, 'updated', {
|
cw: note.cw,
|
||||||
cw: note.cw,
|
text: note.text ?? '',
|
||||||
text: note.text!,
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.globalEventService.publishNoteStream(note.id, 'updated', {
|
|
||||||
cw: note.cw,
|
|
||||||
text: note.text!,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.roleService.addNoteToRoleTimeline(noteObj);
|
this.roleService.addNoteToRoleTimeline(noteObj);
|
||||||
|
|
||||||
|
@ -673,8 +638,6 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
|
|
||||||
const nm = new NotificationManager(this.mutingsRepository, this.notificationService, user, note);
|
const nm = new NotificationManager(this.mutingsRepository, this.notificationService, user, note);
|
||||||
|
|
||||||
//await this.createMentionedEvents(mentionedUsers, note, nm);
|
|
||||||
|
|
||||||
// If has in reply to note
|
// If has in reply to note
|
||||||
if (data.reply) {
|
if (data.reply) {
|
||||||
// 通知
|
// 通知
|
||||||
|
@ -697,7 +660,6 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
if (!isThreadMuted && !muted) {
|
if (!isThreadMuted && !muted) {
|
||||||
nm.push(data.reply.userId, 'edited');
|
nm.push(data.reply.userId, 'edited');
|
||||||
this.globalEventService.publishMainStream(data.reply.userId, 'edited', noteObj);
|
this.globalEventService.publishMainStream(data.reply.userId, 'edited', noteObj);
|
||||||
|
|
||||||
this.webhookService.enqueueUserWebhook(data.reply.userId, 'reply', { note: noteObj });
|
this.webhookService.enqueueUserWebhook(data.reply.userId, 'reply', { note: noteObj });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -803,42 +765,6 @@ export class NoteEditService implements OnApplicationShutdown {
|
||||||
(note.files != null && note.files.length > 0);
|
(note.files != null && note.files.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO why is this unused?
|
|
||||||
@bindThis
|
|
||||||
private async createMentionedEvents(mentionedUsers: MinimumUser[], note: MiNote, nm: NotificationManager) {
|
|
||||||
// FIXME only users the note is visible to should receive a notification, same as when a note is created
|
|
||||||
for (const u of mentionedUsers.filter(u => this.userEntityService.isLocalUser(u))) {
|
|
||||||
const isThreadMuted = await this.noteThreadMutingsRepository.exists({
|
|
||||||
where: {
|
|
||||||
userId: u.id,
|
|
||||||
threadId: note.threadId ?? note.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const [
|
|
||||||
userIdsWhoMeMuting,
|
|
||||||
] = u.id ? await Promise.all([
|
|
||||||
this.cacheService.userMutingsCache.fetch(u.id),
|
|
||||||
]) : [new Set<string>()];
|
|
||||||
|
|
||||||
const muted = isUserRelated(note, userIdsWhoMeMuting);
|
|
||||||
|
|
||||||
if (isThreadMuted || muted) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const detailPackedNote = await this.noteEntityService.pack(note, u, {
|
|
||||||
detail: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.globalEventService.publishMainStream(u.id, 'edited', detailPackedNote);
|
|
||||||
this.webhookService.enqueueUserWebhook(u.id, 'edited', { note: detailPackedNote });
|
|
||||||
|
|
||||||
// Create notification
|
|
||||||
nm.push(u.id, 'edited');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async renderNoteOrRenoteActivity(data: Option, note: MiNote, user: MiUser) {
|
private async renderNoteOrRenoteActivity(data: Option, note: MiNote, user: MiUser) {
|
||||||
if (data.localOnly) return null;
|
if (data.localOnly) return null;
|
||||||
|
|
Loading…
Add table
Reference in a new issue