Files
FrozenFriendsYume/packages/backend/built/services/create-bite.js
T
2026-07-26 18:25:37 +09:00

98 lines
3.4 KiB
JavaScript

import { genId } from "../misc/gen-id.js";
import { Bites, Users } from "../models/index.js";
import { renderActivity } from "../remote/activitypub/renderer/index.js";
import renderBite from "../remote/activitypub/renderer/bite.js";
import { deliverToUser } from "../remote/activitypub/deliver-manager.js";
import { createNotification } from "./create-notification.js";
import { tickBiteLocal, tickBiteOutgoing } from "../metrics.js";
import { getNote } from "../server/api/common/getters.js";
import { IdentifiableError } from "../misc/identifiable-error.js";
export async function createBite(sender, targetType, targetId, remoteUri = null, createdAt = null) {
const id = genId();
const insert = {
id,
createdAt: createdAt ?? new Date(),
userId: sender.id,
userHost: sender.host,
targetType,
replied: false,
uri: remoteUri
};
let targetUser;
switch(targetType){
case "user":
insert.targetUserId = targetId;
targetUser = await Users.findOneByOrFail({
id: targetId
});
break;
case "bite":
insert.targetBiteId = targetId;
const bite = await Bites.findOneOrFail({
where: {
id: targetId
},
relations: [
"user"
]
});
targetUser = bite.user;
break;
case "note":
insert.targetNoteId = targetId;
const note = await getNote(targetId, sender);
targetUser = await Users.findOneByOrFail({
id: note.userId
});
break;
}
if (targetUser.canBite === "nobody") throw new IdentifiableError("92ce0141-760d-4163-a7a2-73b349e3d133", "Bites disabled");
const relations = await Users.getRelation(sender.id, targetUser.id);
if (targetUser.canBite === "followers" && !relations.isFollowing) throw new IdentifiableError("35363f14-f489-45e2-81a9-558450710dfe", "Not following");
if (relations.isBlocked) throw new IdentifiableError("f82d8d34-beaf-42f3-9135-477d32288213", "Blocked");
await Bites.insert(insert);
const bite1 = await Bites.findOneOrFail({
where: {
id
},
relations: [
"targetUser",
"targetBite",
"targetNote"
]
});
let deliverTarget;
switch(targetType){
case "user":
deliverTarget = bite1.targetUser;
break;
case "bite":
await Bites.update({
id: bite1.targetBiteId
}, {
replied: true
});
deliverTarget = bite1.targetBite.user ?? await Users.findOneByOrFail({
id: bite1.targetBite.userId
});
break;
case "note":
deliverTarget = bite1.targetNote.user ?? await Users.findOneByOrFail({
id: bite1.targetNote.userId
});
break;
}
if (Users.isLocalUser(sender) && Users.isRemoteUser(deliverTarget)) {
await deliverToUser(sender, renderActivity(await renderBite(bite1)), deliverTarget);
tickBiteOutgoing();
}
if (Users.isLocalUser(deliverTarget)) {
await createNotification(deliverTarget.id, "bite", {
notifierId: sender.id,
biteId: bite1.id
});
if (Users.isLocalUser(sender)) tickBiteLocal();
}
return id;
}