import { In } from "typeorm"; import create from "./create.js"; import { Users, DriveFiles, Channels, Blockings, UserGroups, UserGroupJoinings } from "../../models/index.js"; import { getNote } from "../../server/api/common/getters.js"; import { ApiError } from "../../server/api/error.js"; const errors = { noSuchRenoteTarget: { message: "No such renote target.", code: "NO_SUCH_RENOTE_TARGET", id: "b5c90186-4ab0-49c8-9bba-a1f76c282ba4" }, cannotReRenote: { message: "You can not Renote a pure Renote.", code: "CANNOT_RENOTE_TO_A_PURE_RENOTE", id: "fd4cc33e-2a37-48dd-99cc-9b806eb2031a" }, noSuchReplyTarget: { message: "No such reply target.", code: "NO_SUCH_REPLY_TARGET", id: "749ee0f6-d3da-459a-bf02-282e2da4292c" }, cannotReplyToPureRenote: { message: "You can not reply to a pure Renote.", code: "CANNOT_REPLY_TO_A_PURE_RENOTE", id: "3ac74a84-8fd5-4bb0-870f-01804f82ce15" }, cannotCreateAlreadyExpiredPoll: { message: "Poll is already expired.", code: "CANNOT_CREATE_ALREADY_EXPIRED_POLL", id: "04da457d-b083-4055-9082-955525eda5a5" }, noSuchChannel: { message: "No such channel.", code: "NO_SUCH_CHANNEL", id: "b1653923-5453-4edc-b786-7c4f39bb0bbb" }, youHaveBeenBlocked: { message: "You have been blocked by this user.", code: "YOU_HAVE_BEEN_BLOCKED", id: "b390d7e1-8a5e-46ed-b625-06271cafd3d3" }, noSuchGroup: { message: "No such group.", code: "NO_SUCH_GROUP", id: "b6344dfc-7c1d-4238-8cc0-0f719c4f9d91" } }; export async function createNoteFromApiData(user, data, createdAt = new Date()) { let visibleUsers = []; if (data.visibleUserIds) { visibleUsers = await Users.findBy({ id: In(data.visibleUserIds) }); } let files = []; const fileIds = data.fileIds != null ? data.fileIds : data.mediaIds != null ? data.mediaIds : null; if (fileIds != null) { files = await DriveFiles.createQueryBuilder("file").where("file.userId = :userId AND file.id IN (:...fileIds)", { userId: user.id, fileIds }).orderBy('array_position(ARRAY[:...fileIds], "id"::text)').setParameters({ fileIds }).getMany(); } let renote = null; if (data.renoteId != null) { renote = await getNote(data.renoteId, user).catch((e)=>{ if (e.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") throw new ApiError(errors.noSuchRenoteTarget); throw e; }); if (renote.renoteId && !renote.text && !renote.fileIds && !renote.hasPoll) { throw new ApiError(errors.cannotReRenote); } if (renote.userId !== user.id) { const isBlocked = await Blockings.exist({ where: [ { blockerId: renote.userId, blockeeId: user.id, groupId: null }, ...renote.groupId ? [ { groupId: renote.groupId, blockeeId: user.id } ] : [] ] }); if (isBlocked) { throw new ApiError(errors.youHaveBeenBlocked); } } } let reply = null; if (data.replyId != null) { reply = await getNote(data.replyId, user).catch((e)=>{ if (e.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") throw new ApiError(errors.noSuchReplyTarget); throw e; }); if (reply.renoteId && !reply.text && !reply.fileIds && !reply.hasPoll) { throw new ApiError(errors.cannotReplyToPureRenote); } if (reply.userId !== user.id) { const isBlocked = await Blockings.exist({ where: [ { blockerId: reply.userId, blockeeId: user.id, groupId: null }, ...reply.groupId ? [ { groupId: reply.groupId, blockeeId: user.id } ] : [] ] }); if (isBlocked) { throw new ApiError(errors.youHaveBeenBlocked); } } } const poll = data.poll ? { ...data.poll } : null; if (poll) { if (typeof poll.expiresAt === "number") { if (poll.expiresAt < createdAt.getTime()) { throw new ApiError(errors.cannotCreateAlreadyExpiredPoll); } } else if (typeof poll.expiredAfter === "number") { poll.expiresAt = createdAt.getTime() + poll.expiredAfter; } } let channel = null; if (data.channelId != null) { channel = await Channels.findOneBy({ id: data.channelId }); if (channel == null) { throw new ApiError(errors.noSuchChannel); } } let group = null; if (data.groupId != null) { group = await UserGroups.findOneBy({ id: data.groupId }); if (group == null) { throw new ApiError(errors.noSuchGroup); } if (group.userId !== user.id) { const joining = await UserGroupJoinings.findOneBy({ userId: user.id, userGroupId: group.id }); if (joining == null) { throw new ApiError(errors.noSuchGroup); } } } return await create(user, { createdAt, files, poll: poll ? { choices: poll.choices, multiple: poll.multiple, expiresAt: poll.expiresAt ? new Date(poll.expiresAt) : null } : undefined, text: data.text || undefined, reply, renote, cw: data.cw, localOnly: data.localOnly, visibility: data.visibility ?? "public", visibleUsers, channel, group, apMentions: data.noExtractMentions ? [] : undefined, apHashtags: data.noExtractHashtags ? [] : undefined, apEmojis: data.noExtractEmojis ? [] : undefined }); }