refactor (backend): port renderLike to backend-rs

This commit is contained in:
naskya 2024-08-10 07:43:28 +09:00
parent 9cf691eebd
commit 9604093a95
No known key found for this signature in database
GPG key ID: 712D413B3A9FED5C
13 changed files with 105 additions and 19 deletions

View file

@ -146,6 +146,15 @@ export interface ApHashtag {
name: string
}
export interface ApLike {
id: string
type: ApObject
actor: string
object: string
content: string
tag?: Array<ApEmoji>
}
export interface ApMention {
type: ApObject
href: string
@ -158,6 +167,7 @@ export type ApObject = 'Accept'|
'Flag'|
'Follow'|
'Hashtag'|
'Like'|
'Mention'|
'Image'|
'Read'|
@ -1356,6 +1366,8 @@ export declare function renderFollowRelay(relayId: string): Promise<ApFollow>
export declare function renderHashtag(tagName: string): ApHashtag
export declare function renderLike(reaction: Model): Promise<ApLike>
export declare function renderMention(user: UserLike): ApMention
export declare function renderRead(userId: string, messageUri: string): ApRead

View file

@ -445,6 +445,7 @@ module.exports.renderFlag = nativeBinding.renderFlag
module.exports.renderFollow = nativeBinding.renderFollow
module.exports.renderFollowRelay = nativeBinding.renderFollowRelay
module.exports.renderHashtag = nativeBinding.renderHashtag
module.exports.renderLike = nativeBinding.renderLike
module.exports.renderMention = nativeBinding.renderMention
module.exports.renderRead = nativeBinding.renderRead
module.exports.renderRemove = nativeBinding.renderRemove

View file

@ -21,8 +21,7 @@ pub struct Icon {
impl ActivityPubObject for ApEmoji {}
impl ApEmoji {
#[allow(dead_code)] // TODO: remove this line
fn new(emoji: emoji::Model) -> Self {
pub fn new(emoji: emoji::Model) -> Self {
Self {
id: misc::emoji::local_uri(&emoji.name),
r#type: ApObject::Emoji,

View file

@ -0,0 +1,74 @@
use super::{emoji::ApEmoji, *};
use crate::{
config::CONFIG,
database::db_conn,
misc::{self, user},
model::entity::{emoji, note, note_reaction},
};
use sea_orm::{ColumnTrait, DbErr, EntityTrait, QueryFilter, QuerySelect, SelectColumns};
#[macros::errors]
pub enum Error {
#[doc = "nonexistent note"]
#[error("note {0} not found")]
NoteNotFound(String),
#[doc = "database error"]
#[error(transparent)]
Db(#[from] DbErr),
}
#[macros::export(object, use_nullable = false)]
pub struct ApLike {
pub id: String,
pub r#type: ApObject,
pub actor: String,
pub object: String,
pub content: String,
pub tag: Option<Vec<ApEmoji>>,
}
impl ActivityPubObject for ApLike {}
impl ApLike {
#[allow(dead_code)] // TODO: remove this line
async fn new(reaction: note_reaction::Model) -> Result<Self, Error> {
let db = db_conn().await?;
let note_uri = {
let note_uri = note::Entity::find()
.select_only()
.select_column(note::Column::Uri)
.filter(note::Column::Id.eq(&reaction.note_id))
.into_tuple::<Option<String>>()
.one(db)
.await?;
match note_uri {
Some(Some(uri)) => uri,
Some(None) => misc::note::local_uri(reaction.note_id),
None => return Err(Error::NoteNotFound(reaction.note_id)),
}
};
let tag = emoji::Entity::find()
.filter(emoji::Column::Name.eq(reaction.reaction.replace(':', "")))
.filter(emoji::Column::Host.is_null())
.one(db)
.await?
.map(|emoji| vec![ApEmoji::new(emoji)]);
Ok(Self {
id: format!("{}/likes/{}", CONFIG.url, reaction.id),
r#type: ApObject::Like,
actor: user::local_uri(reaction.user_id),
object: note_uri,
content: reaction.reaction,
tag,
})
}
}
#[macros::ts_export]
pub async fn render_like(reaction: note_reaction::Model) -> Result<ApLike, Error> {
ApLike::new(reaction).await
}

View file

@ -4,6 +4,7 @@ pub mod emoji;
pub mod flag;
pub mod follow;
pub mod hashtag;
pub mod like;
pub mod mention;
pub mod read;
pub mod remove;
@ -19,6 +20,7 @@ pub enum ApObject {
Flag,
Follow,
Hashtag,
Like,
Mention,
Image,
Read,

View file

@ -12,11 +12,7 @@ export default async (actor: CacheableRemoteUser, activity: ILike) => {
await extractEmojis(activity.tag || [], actor.host).catch(() => null);
return await create(
actor,
note,
activity._misskey_reaction || activity.content || activity.name,
)
return await create(actor, note, activity.content || activity.name)
.catch((e) => {
if (e.id === "51c42bb4-931a-456b-bff7-e5a8a70dd298") {
return "skip: already reacted";

View file

@ -550,7 +550,6 @@ export const WellKnownContext = {
// Misskey
misskey: "https://misskey-hub.net/ns#",
_misskey_talk: "misskey:_misskey_talk",
_misskey_reaction: "misskey:_misskey_reaction",
_misskey_votes: "misskey:_misskey_votes",
_misskey_summary: "misskey:_misskey_summary",
isCat: "misskey:isCat",

View file

@ -14,7 +14,6 @@ export const renderLike = async (noteReaction: NoteReaction, note: Note) => {
actor: `${config.url}/users/${noteReaction.userId}`,
object: note.uri ? note.uri : `${config.url}/notes/${noteReaction.noteId}`,
content: reaction,
_misskey_reaction: reaction,
} as any;
if (reaction.startsWith(":")) {

View file

@ -7,6 +7,7 @@ import {
isBlockedServer,
isSelfHost,
renderFollow,
renderLike,
} from "backend-rs";
import { apGet } from "./request.js";
import type { IObject, ICollection, IOrderedCollection } from "./type.js";
@ -20,7 +21,6 @@ import {
} from "@/models/index.js";
import { parseUri } from "./db-resolver.js";
import renderNote from "@/remote/activitypub/renderer/note.js";
import { renderLike } from "@/remote/activitypub/renderer/like.js";
import { renderPerson } from "@/remote/activitypub/renderer/person.js";
import renderQuestion from "@/remote/activitypub/renderer/question.js";
import renderCreate from "@/remote/activitypub/renderer/create.js";
@ -181,7 +181,7 @@ export default class Resolver {
}
case "likes": {
const reaction = await NoteReactions.findOneByOrFail({ id: parsed.id });
return renderActivity(renderLike(reaction, { uri: null }));
return renderActivity(await renderLike(reaction));
}
case "follows": {
// if rest is a <followee id>

View file

@ -303,7 +303,7 @@ export interface IRemove extends IActivity {
export interface ILike extends IActivity {
type: "Like" | "EmojiReaction" | "EmojiReact";
_misskey_reaction?: string;
content?: string;
}
export interface IAnnounce extends IActivity {

View file

@ -14,6 +14,7 @@ import {
isSelfHost,
renderEmoji,
renderFollow,
renderLike,
} from "backend-rs";
import {
Notes,
@ -23,7 +24,6 @@ import {
FollowRequests,
} from "@/models/index.js";
import type { ILocalUser, User } from "@/models/entities/user.js";
import { renderLike } from "@/remote/activitypub/renderer/like.js";
import { getUserKeypair } from "@/misc/keypair-store.js";
import {
checkFetch,
@ -466,7 +466,7 @@ router.get("/likes/:like", async (ctx) => {
return;
}
ctx.body = renderActivity(await renderLike(reaction, note));
ctx.body = renderActivity(await renderLike(reaction));
const instanceMeta = await fetchMeta();
if (instanceMeta.secureMode || instanceMeta.privateMode) {
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");

View file

@ -1,4 +1,3 @@
import { renderLike } from "@/remote/activitypub/renderer/like.js";
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
import type { User, IRemoteUser } from "@/models/entities/user.js";
@ -17,6 +16,7 @@ import {
genIdAt,
NoteEvent,
publishToNoteStream,
renderLike,
toDbReaction,
} from "backend-rs";
import { createNotification } from "@/services/create-notification.js";
@ -152,7 +152,7 @@ export default async (
!note.localOnly &&
note.visibility !== "hidden"
) {
const content = renderActivity(await renderLike(record, note));
const content = renderActivity(await renderLike(record));
const dm = new DeliverManager(user, content);
if (note.userHost != null) {
const reactee = await Users.findOneBy({ id: note.userId });

View file

@ -1,4 +1,3 @@
import { renderLike } from "@/remote/activitypub/renderer/like.js";
import { renderUndo } from "@/remote/activitypub/renderer/undo.js";
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
@ -6,7 +5,12 @@ import { IdentifiableError } from "@/misc/identifiable-error.js";
import type { User, IRemoteUser } from "@/models/entities/user.js";
import type { Note } from "@/models/entities/note.js";
import { NoteReactions, Users, Notes } from "@/models/index.js";
import { decodeReaction, NoteEvent, publishToNoteStream } from "backend-rs";
import {
decodeReaction,
NoteEvent,
publishToNoteStream,
renderLike,
} from "backend-rs";
export default async (
user: { id: User["id"]; host: User["host"] },
@ -55,7 +59,7 @@ export default async (
//#region 配信
if (Users.isLocalUser(user) && !note.localOnly) {
const content = renderActivity(
renderUndo(await renderLike(reaction, note), user.id),
renderUndo(await renderLike(reaction), user.id),
);
const dm = new DeliverManager(user, content);
if (note.userHost != null) {