PageSourceSearch

https://an0ncer.github.io/javascript/modules/api.jikan.js

js an0ncer.github.io collected 2026-10-03 08:37:41 UTC 6,972 bytes, 206 lines download raw bytes

1import { md5 } from "../library/md5.wasm.min.js";
2import { Sleep } from "./functions.js";
3import { TCache } from "./tun.cache.js";
4
5// const BASE_URL = 'https://api.jikan.moe/v4' //TODO: Переделать
6const BASE_URL = 'https://api.tunime.app/v4';
7
8class JikanControls {
9    static instance = null;
10
11    constructor() {
12        if (JikanControls.instance) return JikanControls.instance;
13
14        this.cache = new TCache();
15        JikanControls.instance = this;
16    }
17
18    async hash(url) {
19        return await md5(url);
20    }
21
22    async fetch(url, init, cache, ttl, e) {
23        const hash = await this.hash(url.href);
24
25        if (cache) {
26            const cachedData = await this.cache.get("requests", hash);
27            if (cachedData) {
28                e(cachedData);
29                return cachedData;
30            }
31        }
32
33        return _fetch.bind(this)();
34
35        function _fetch() {
36            return new Promise((resolve) => {
37                fetch(url, { ...init }).then(async (response) => {
38                    if (!response.ok) {
39                        if (response.status == 429) {
40                            await Sleep(1200);
41                            return _fetch();
42                        }
43                        return new Error(`Ошибка API: ${response.status}`);
44                    }
45
46                    response.json().then(async value => {
47                        if (cache) {
48                            await this.cache.put("requests", hash, value, ttl);
49                        }
50                        e(value);
51                        resolve(value);
52                    });
53                }).catch(err => {
54                    if (err?.name === "tabort") return;
55                    throw err;
56                });
57            });
58        }
59    }
60}
61
62export const Jikan = {
63    anime: {
64        getAnimeFullById: (id, e = () => { }) => {
65            const control = new JikanControls();
66            const url = new URL(`${BASE_URL}/anime/${id}/full`);
67
68            return {
69                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
70                    return control.fetch(url, init, cache, ttl, e);
71                }
72            }
73        },
74        getAnimeSearch: (params = {}, e = () => { }) => {
75            const control = new JikanControls();
76            const url = new URL(`${BASE_URL}/anime`);
77
78            Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value));
79
80            return {
81                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
82                    return control.fetch(url, init, cache, ttl, e);
83                }
84            }
85        },
86        getAnimeCharacters: (id, e = () => { }) => {
87            const control = new JikanControls();
88            const url = new URL(`${BASE_URL}/anime/${id}/characters`);
89
90            return {
91                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
92                    return control.fetch(url, init, cache, ttl, e);
93                }
94            }
95        }
96    },
97    producers: {
98        getProducerById: (id, e = () => { }) => {
99            const control = new JikanControls();
100            const url = new URL(`${BASE_URL}/producers/${id}`);
101
102            return {
103                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
104                    return control.fetch(url, init, cache, ttl, e);
105                }
106            }
107        },
108        getProducers: (params = {}, e = () => { }) => {
109            const control = new JikanControls();
110            const url = new URL(`${BASE_URL}/producers`);
111
112            Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value));
113
114            return {
115                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
116                    return control.fetch(url, init, cache, ttl, e);
117                }
118            }
119        }
120    },
121    seasons: {
122        getSeasonNow: (params = {}, e = () => { }) => {
123            const control = new JikanControls();
124            const url = new URL(`${BASE_URL}/seasons/now`);
125
126            Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value));
127
128            return {
129                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
130                    return control.fetch(url, init, cache, ttl, e);
131                }
132            }
133        },
134        getSeason: (year, season, params = {}, e = () => { }) => {
135            const control = new JikanControls();
136            const url = new URL(`${BASE_URL}/seasons/${year}/${season}`);
137
138            Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value));
139
140            return {
141                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
142                    return control.fetch(url, init, cache, ttl, e);
143                }
144            }
145        },
146        getSeasonsList: (e = () => { }) => {
147            const control = new JikanControls();
148            const url = new URL(`${BASE_URL}/seasons`);
149
150            return {
151                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
152                    return control.fetch(url, init, cache, ttl, e);
153                }
154            }
155        }
156    },
157    random: {
158        getRandomAnime: (e = () => { }) => {
159            const control = new JikanControls();
160            const url = new URL(`${BASE_URL}/random/anime`);
161
162            return {
163                GET: (init = {}, cache = false, ttl = 0) => {
164                    return control.fetch(url, init, cache, ttl, e);
165                }
166            }
167        }
168    },
169    recommendations: {
170        getRecentAnimeRecommendations: (params = {}, e = () => { }) => {
171            const control = new JikanControls();
172            const url = new URL(`${BASE_URL}/recommendations/anime`);
173
174            Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value));
175
176            return {
177                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
178                    return control.fetch(url, init, cache, ttl, e);
179                }
180            }
181        }
182    },
183    characters: {
184        getCharacterFullById: (id, e = () => { }) => {
185            const control = new JikanControls();
186            const url = new URL(`${BASE_URL}/characters/${id}/full`);
187
188            return {
189                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
190                    return control.fetch(url, init, cache, ttl, e);
191                }
192            }
193        },
194
195        getCharacterPictures: (id, e = () => { }) => {
196            const control = new JikanControls();
197            const url = new URL(`${BASE_URL}/characters/${id}/pictures`);
198
199            return {
200                GET: (init = {}, cache = true, ttl = 60 * 60 * 1000) => {
201                    return control.fetch(url, init, cache, ttl, e);
202                }
203            }
204        }
205    }
206}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.