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; }