This commit is contained in:
syuilo 2025-09-16 22:42:04 +09:00 committed by GitHub
commit 84e7629780
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 92 additions and 1 deletions

View File

@ -28,6 +28,8 @@ import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { emojiRegex } from '@/misc/emoji-regex.js';
import { NotificationService } from '@/core/NotificationService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
import { trackPromise } from '@/misc/promise-tracker.js';
const MAX_ROOM_MEMBERS = 50;
const MAX_REACTIONS_PER_MESSAGE = 100;
@ -81,6 +83,7 @@ export class ChatService {
private chatEntityService: ChatEntityService,
private idService: IdService,
private globalEventService: GlobalEventService,
private apDeliverManagerService: ApDeliverManagerService,
private apRendererService: ApRendererService,
private queueService: QueueService,
private pushNotificationService: PushNotificationService,
@ -236,6 +239,19 @@ export class ChatService {
}, 3000);
}
//#region AP deliver
if (this.userEntityService.isLocalUser(fromUser) && this.userEntityService.isRemoteUser(toUser)) {
(async () => {
const content = await this.apRendererService.renderChatMessage(inserted, false);
const activity = this.apRendererService.addContext(content);
const dm = this.apDeliverManagerService.createDeliverManager(fromUser, activity);
dm.addDirectRecipe(toUser);
trackPromise(dm.execute());
})();
}
//#endregion
return packedMessage;
}

View File

@ -457,6 +457,36 @@ export class ApInboxService {
}
}
@bindThis
private async chatMessage(resolver: Resolver, actor: MiRemoteUser, message: IObject): Promise<string> {
const uri = getApId(message);
if (typeof message === 'object') {
if (actor.uri !== message.attributedTo) {
return 'skip: actor.uri !== message.attributedTo';
}
if (typeof message.id === 'string') {
if (this.utilityService.extractDbHost(actor.uri) !== this.utilityService.extractDbHost(message.id)) {
return 'skip: host in actor.uri !== message.id';
}
} else {
return 'skip: message.id is not a string';
}
}
try {
await this.chatService.createMessageViaAp(message, actor, resolver);
return 'ok';
} catch (err) {
if (err instanceof StatusError && !err.isRetryable) {
return `skip ${err.statusCode}`;
} else {
throw err;
}
}
}
@bindThis
private async delete(actor: MiRemoteUser, activity: IDelete): Promise<string> {
if (actor.uri !== activity.actor) {

View File

@ -23,7 +23,7 @@ import { MfmService, type Appender } from '@/core/MfmService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import type { MiUserKeypair } from '@/models/UserKeypair.js';
import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, PollsRepository, MiMeta } from '@/models/_.js';
import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, PollsRepository, MiMeta, MiChatMessage } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { IdService } from '@/core/IdService.js';
@ -502,6 +502,31 @@ export class ApRendererService {
};
}
@bindThis
public async renderChatMessage(message: MiChatMessage, dive = true): Promise<IPost> {
const attributedTo = this.userEntityService.genLocalUserUri(message.fromUserId);
const file = message.fileId ? await this.driveFilesRepository.findOneBy({ id: message.fileId }) : null;
const emojis = await this.getEmojis(message.emojis);
const apemojis = emojis.filter(emoji => !emoji.localOnly).map(emoji => this.renderEmoji(emoji));
const tag = [
...apemojis,
];
return {
id: `${this.config.url}/chat-messages/${message.id}`,
type: 'Misskey:ChatMessage',
attributedTo,
text: message.text,
published: this.idService.parse(message.id).date.toISOString(),
to: message.toUserId,
attachment: file ? [this.renderDocument(file)] : [],
tag,
};
}
@bindThis
public async renderPerson(user: MiLocalUser) {
const id = this.userEntityService.genLocalUserUri(user.id);

View File

@ -55,6 +55,8 @@ export class MiChatMessage {
})
public text: string | null;
// 連合用
// ローカルはnull
@Column('varchar', {
length: 512, nullable: true,
})
@ -82,4 +84,22 @@ export class MiChatMessage {
length: 1024, array: true, default: '{}',
})
public reactions: string[];
// 連合用
@Column('varchar', {
length: 128, array: true, default: '{}',
})
public emojis: string[];
// 連合用
@Column('boolean', {
default: false,
})
public isDelivering: boolean;
// 連合用
@Column('boolean', {
default: false,
})
public isDeliverFailed: boolean;
}