feat: support ChatMessage type (a.k.a. Pleroma chat)

Co-authored-by: naskya <m@naskya.net>
This commit is contained in:
Lhcfl 2024-01-05 07:03:30 +09:00 committed by naskya
parent 21aa6b097b
commit 8d044c617d
Signed by: naskya
GPG key ID: 712D413B3A9FED5C
5 changed files with 56 additions and 3 deletions

View file

@ -38,6 +38,7 @@
## 細かい変更点
- Pleroma のチャットに対応Catodon から取り込み)
- 翻訳機能にて、投稿言語が指定されていない場合にのみ言語の自動検出を用いるように変更
- アップデート時に更新内容を確認できる機能を追加
- 依存ライブラリを最新版にアップデート

View file

@ -129,6 +129,12 @@ export async function createNote(
throw new Error(`unexpected schema of note.id: ${note.id}`);
}
// ChatMessage only have id
// TODO: split into a separate validate function
if (note.type === "ChatMessage") {
note.url = note.id;
}
const url = getOneApHrefNullable(note.url);
if (url && !url.startsWith("https://")) {
@ -183,7 +189,9 @@ export async function createNote(
}
}
let isTalk = note._misskey_talk && visibility === "specified";
let isTalk =
(note.type === "ChatMessage" || note._misskey_talk) &&
visibility === "specified";
const apMentions = await extractApMentions(note.tag);
const apHashtags = await extractApHashtags(note.tag);

View file

@ -49,6 +49,10 @@ export const renderActivity = (x: any): IActivity | null => {
fedibird: "http://fedibird.com/ns#",
// vcard
vcard: "http://www.w3.org/2006/vcard/ns#",
// ChatMessage
litepub: "http://litepub.social/ns#",
ChatMessage: "litepub:ChatMessage",
directMessage: "litepub:directMessage",
},
],
},

View file

@ -115,6 +115,7 @@ export const validPost = [
"Page",
"Video",
"Event",
"ChatMessage", // TODO: move it to vaildMessage
];
export const isPost = (object: IObject): object is IPost =>
@ -130,6 +131,7 @@ export interface IPost extends IObject {
| "Image"
| "Page"
| "Video"
| "ChatMessage" // TODO: move it to IChatMessage
| "Event";
source?: {
content: string;

View file

@ -22,6 +22,8 @@ import renderNote from "@/remote/activitypub/renderer/note.js";
import renderCreate from "@/remote/activitypub/renderer/create.js";
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
import { deliver } from "@/queue/index.js";
import { toPuny } from "@/misc/convert-host.js";
import { Instances } from "@/models/index.js";
export async function createMessage(
user: { id: User["id"]; host: User["host"] },
@ -121,6 +123,9 @@ export async function createMessage(
Users.isLocalUser(user) &&
Users.isRemoteUser(recipientUser)
) {
const instance = await Instances.findOneBy({
host: toPuny(recipientUser.host),
});
const note = {
id: message.id,
createdAt: message.createdAt,
@ -138,10 +143,43 @@ export async function createMessage(
),
} as Note;
const activity = renderActivity(
renderCreate(await renderNote(note, false, true), note),
let renderedNote: Record<string, unknown> = await renderNote(
note,
false,
true,
);
// TODO: For pleroma and its fork instances, the actor will have a boolean "capabilities": { acceptsChatMessages: boolean } property. May use that instead of checking instance.softwareName. https://kazv.moe/objects/ca5c0b88-88ce-48a7-bf88-54d45f6ce781
// ChatMessage document from Pleroma: https://docs.pleroma.social/backend/development/ap_extensions/#chatmessages
// Note: LitePub has been stalled since 2019-06-29 and is incomplete as a specification
if (
instance?.softwareName &&
["akkoma", "pleroma", "lemmy"].includes(
instance.softwareName.toLowerCase(),
)
) {
const tmp_note = renderedNote;
renderedNote = {
type: "ChatMessage",
attributedTo: tmp_note.attributedTo,
content: tmp_note.content,
id: tmp_note.id,
published: tmp_note.published,
to: tmp_note.to,
tag: tmp_note.tag,
cc: [],
};
// A recently fixed bug, empty arrays will be rejected by pleroma
if (
Array.isArray(tmp_note.attachment) &&
tmp_note.attachment.length !== 0
) {
renderedNote.attachment = tmp_note.attachment;
}
}
const activity = renderActivity(renderCreate(renderedNote, note));
deliver(user, activity, recipientUser.inbox);
}
return messageObj;