diff --git a/api/v1/src/release.ts b/api/v1/src/release.ts
new file mode 100644
index 0000000..bdf80f3
--- /dev/null
+++ b/api/v1/src/release.ts
@@ -0,0 +1,106 @@
+import { serve } from "https://deno.land/std@0.140.0/http/server.ts";
+
+const baseHeaders = {
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
+ "Accept": "application/json",
+};
+
+async function getShikimoriData(search, year) {
+ if (!search) {
+ return { score: "N/A", characters: [] };
+ }
+
+ const animeUrl = `https://shikimori.one/api/animes?search=${encodeURIComponent(search)}&limit=1${year ? `&year=${year}` : ""}`;
+
+ try {
+ const animeRes = await fetch(animeUrl, { headers: baseHeaders });
+ const animeData = await animeRes.json();
+ const anime = animeData?.[0];
+
+ if (!anime || !anime.id) {
+ return { score: "N/A", characters: [] };
+ }
+
+ const rolesUrl = `https://shikimori.one/api/animes/${anime.id}/roles`;
+ const rolesRes = await fetch(rolesUrl, { headers: baseHeaders });
+ const roles = await rolesRes.json();
+
+ const mainCharacters = roles
+ .filter((c) => c.roles.includes("Main"))
+ .slice(0, 5)
+ .map((c) => ({
+ name: c.character.russian,
+ url: `https://shikimori.one${c.character.url}`,
+ }));
+
+ return {
+ score: anime.score || "N/A",
+ characters: mainCharacters,
+ };
+ } catch {
+ return { score: "N/A", characters: [] };
+ }
+}
+
+async function getReleaseFromAnixart(releaseId, token = "") {
+ const url = `https://api.anixart.tv/release/${releaseId}${token ? `?token=${token}` : ""}`;
+
+ try {
+ const response = await fetch(url, { headers: baseHeaders });
+ const data = await response.json();
+ const release = data?.release;
+
+ if (!release) {
+ return { code: 2, release: null };
+ }
+
+ const title = release.title_original || release.title_ru || "";
+ const year = release.year || "";
+ let noteExtra = "";
+
+ try {
+ const shikiData = await getShikimoriData(title, year);
+ const score = shikiData.score || "N/A";
+ const characters = shikiData.characters.length
+ ? shikiData.characters.map((c) => `${c.name}`).join(", ")
+ : "N/A";
+
+ noteExtra = `Оценки из Shikimori: ${score}
Главные персонажи: ${characters}
`;
+ } catch {
+ noteExtra = `Оценки из Shikimori: N/A
Главные персонажи: N/A
`;
+ }
+
+ const originalNote = release.note?.trim();
+ let finalNote = noteExtra;
+ if (originalNote) {
+ finalNote += `
Примечание от Anixart:
${originalNote}`;
+ }
+
+ release.note = finalNote;
+
+ return { code: 0, release };
+ } catch {
+ return { code: 2, release: null };
+ }
+}
+
+serve(async (req) => {
+ const url = new URL(req.url);
+ const path = url.pathname;
+ const token = url.searchParams.get("token");
+
+ // Эндпоинт: /api/release/{releaseId}
+ const releaseMatch = path.match(/^\/api\/release\/([^\/]+)/);
+ if (releaseMatch) {
+ const releaseId = releaseMatch[1];
+ const result = await getReleaseFromAnixart(releaseId, token);
+ return new Response(JSON.stringify(result), {
+ headers: {
+ "Content-Type": "application/json",
+ "Access-Control-Allow-Origin": "*",
+ },
+ });
+ }
+
+ return new Response("Invalid endpoint", { status: 404 });
+});