import { Notes } from "../../../../models/index.js"; import { MINUTE } from "../../../../const.js"; import { getIpHash } from "../../../../misc/get-ip-hash.js"; import define from "../../define.js"; import { getNote } from "../../common/getters.js"; import { ApiError } from "../../error.js"; import { limiter } from "../../limiter.js"; const serviceTags = { video: "videoservice", audio: "audioservice", lua4frozen: "lua4frozen", karaoke: "karaokeservice" }; export const meta = { tags: [ "notes" ], requireCredential: false, requireCredentialPrivateMode: true, errors: { noSuchNote: { message: "No such note.", code: "NO_SUCH_NOTE", id: "438ff599-8b8b-45d1-a72d-7e94d3476bd6", httpStatusCode: 404 } } }; export const paramDef = { type: "object", properties: { noteId: { type: "string", format: "misskey:id" }, service: { type: "string", enum: [ "video", "audio", "lua4frozen", "karaoke" ] } }, required: [ "noteId", "service" ] }; export default define(meta, paramDef, async (ps, user, token, file, cleanup, ip)=>{ const note = await getNote(ps.noteId, user, { allowAdservice: true }).catch((err)=>{ if (err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") throw new ApiError(meta.errors.noSuchNote); throw err; }); if (!note.tags.includes(serviceTags[ps.service])) { throw new ApiError(meta.errors.noSuchNote); } const actor = user ? user.id : getIpHash(ip ?? ""); const counted = await limiter({ key: `service-view:${ps.service}:${note.id}`, duration: MINUTE, max: 1 }, actor).then(()=>true, ()=>false); if (counted) { await Notes.increment({ id: note.id }, "viewCount", 1); } return { counted }; });