comparison src/services/anilist.cc @ 304:2115488eb302

*: add very early season searcher
author Paper <paper@paper.us.eu.org>
date Mon, 13 May 2024 17:02:35 -0400
parents 9a88e1725fd2
children 91ac90a34003
comparison
equal deleted inserted replaced
303:ab7ff259b4ca 304:2115488eb302
1 #include "services/anilist.h" 1 #include "services/anilist.h"
2 #include "core/anime.h" 2 #include "core/anime.h"
3 #include "core/anime_db.h" 3 #include "core/anime_db.h"
4 #include "core/date.h"
4 #include "core/config.h" 5 #include "core/config.h"
5 #include "core/http.h" 6 #include "core/http.h"
6 #include "core/json.h" 7 #include "core/json.h"
7 #include "core/session.h" 8 #include "core/session.h"
8 #include "core/strings.h" 9 #include "core/strings.h"
26 27
27 namespace Services { 28 namespace Services {
28 namespace AniList { 29 namespace AniList {
29 30
30 static constexpr std::string_view CLIENT_ID = "13706"; 31 static constexpr std::string_view CLIENT_ID = "13706";
32 #define MEDIA_FIELDS \
33 "coverImage {\n" \
34 " large\n" \
35 "}\n" \
36 "id\n" \
37 "title {\n" \
38 " romaji\n" \
39 " english\n" \
40 " native\n" \
41 "}\n" \
42 "format\n" \
43 "status\n" \
44 "averageScore\n" \
45 "season\n" \
46 "startDate {\n" \
47 " year\n" \
48 " month\n" \
49 " day\n" \
50 "}\n" \
51 "genres\n" \
52 "episodes\n" \
53 "duration\n" \
54 "synonyms\n" \
55 "description(asHtml: false)\n"
31 56
32 class Account { 57 class Account {
33 public: 58 public:
34 int UserId() const { return session.config.auth.anilist.user_id; } 59 int UserId() const { return session.config.auth.anilist.user_id; }
35 void SetUserId(const int id) { session.config.auth.anilist.user_id = id; } 60 void SetUserId(const int id) { session.config.auth.anilist.user_id = id; }
213 " month\n" 238 " month\n"
214 " day\n" 239 " day\n"
215 " }\n" 240 " }\n"
216 " updatedAt\n" 241 " updatedAt\n"
217 " media {\n" 242 " media {\n"
218 " coverImage {\n" 243 MEDIA_FIELDS
219 " large\n"
220 " }\n"
221 " id\n"
222 " title {\n"
223 " romaji\n"
224 " english\n"
225 " native\n"
226 " }\n"
227 " format\n"
228 " status\n"
229 " averageScore\n"
230 " season\n"
231 " startDate {\n"
232 " year\n"
233 " month\n"
234 " day\n"
235 " }\n"
236 " genres\n"
237 " episodes\n"
238 " duration\n"
239 " synonyms\n"
240 " description(asHtml: false)\n"
241 " }\n" 244 " }\n"
242 " }\n" 245 " }\n"
243 " }\n" 246 " }\n"
244 " }\n" 247 " }\n"
245 "}\n"; 248 "}\n";
252 }; 255 };
253 // clang-format on 256 // clang-format on
254 257
255 auto res = SendJSONRequest(json); 258 auto res = SendJSONRequest(json);
256 259
257 for (const auto& list : res["data"]["MediaListCollection"]["lists"].items()) { 260 for (const auto& list : res["data"]["MediaListCollection"]["lists"].items())
258 ParseList(list.value()); 261 ParseList(list.value());
259 } 262
260 return 1; 263 return 1;
261 } 264 }
262 265
263 /* return is a vector of anime ids */ 266 /* return is a vector of anime ids */
264 std::vector<int> Search(const std::string& search) { 267 std::vector<int> Search(const std::string& search) {
265 constexpr std::string_view query = "query ($search: String) {\n" 268 constexpr std::string_view query = "query ($search: String) {\n"
266 " Page (page: 1, perPage: 50) {\n" 269 " Page (page: 1, perPage: 50) {\n"
267 " media (search: $search, type: ANIME) {\n" 270 " media (search: $search, type: ANIME) {\n"
268 " coverImage {\n" 271 MEDIA_FIELDS
269 " large\n"
270 " }\n"
271 " id\n"
272 " id_mal\n"
273 " title {\n"
274 " romaji\n"
275 " english\n"
276 " native\n"
277 " }\n"
278 " format\n"
279 " status\n"
280 " averageScore\n"
281 " season\n"
282 " startDate {\n"
283 " year\n"
284 " month\n"
285 " day\n"
286 " }\n"
287 " genres\n"
288 " episodes\n"
289 " duration\n"
290 " synonyms\n"
291 " description(asHtml: false)\n"
292 " }\n" 272 " }\n"
293 " }\n" 273 " }\n"
294 "}\n"; 274 "}\n";
295 275
296 // clang-format off 276 // clang-format off
302 }; 282 };
303 // clang-format on 283 // clang-format on
304 284
305 auto res = SendJSONRequest(json); 285 auto res = SendJSONRequest(json);
306 286
287 /* FIXME: error handling here */
307 std::vector<int> ret; 288 std::vector<int> ret;
308 ret.reserve(res["data"]["Page"]["media"].size()); 289 ret.reserve(res["data"]["Page"]["media"].size());
309 290
310 for (const auto& media : res["data"]["Page"]["media"].items()) 291 for (const auto& media : res["data"]["Page"]["media"].items())
311 ret.push_back(ParseMediaJson(media.value())); 292 ret.push_back(ParseMediaJson(media.value()));
293
294 return ret;
295 }
296
297 std::vector<int> GetSeason(Anime::SeriesSeason season, Date::Year year) {
298 constexpr std::string_view query = "query ($season: MediaSeason!, $season_year: Int!, $page: Int) {\n"
299 " Page(page: $page) {\n"
300 " media(season: $season, seasonYear: $season_year, type: ANIME, sort: START_DATE) {\n"
301 MEDIA_FIELDS
302 " }\n"
303 " pageInfo {\n"
304 " total\n"
305 " perPage\n"
306 " currentPage\n"
307 " lastPage\n"
308 " hasNextPage\n"
309 " }\n"
310 " }\n"
311 "}\n";
312 std::vector<int> ret;
313
314 int page = 0;
315 bool has_next_page = true;
316 while (has_next_page) {
317 nlohmann::json json = {
318 {"query", query},
319 {"variables", {
320 {"season", Translate::AniList::ToString(season)},
321 {"season_year", Strings::ToUtf8String(year)},
322 {"page", page}
323 }}
324 };
325
326 auto res = SendJSONRequest(json);
327 ret.reserve(ret.capacity() + res["data"]["Page"]["media"].size());
328
329 for (const auto& media : res["data"]["Page"]["media"].items())
330 ret.push_back(ParseMediaJson(media.value()));
331
332 has_next_page = JSON::GetBoolean(res, "/data/Page/pageInfo/hasNextPage"_json_pointer, false);
333 if (has_next_page)
334 page++;
335 }
312 336
313 return ret; 337 return ret;
314 } 338 }
315 339
316 int UpdateAnimeEntry(int id) { 340 int UpdateAnimeEntry(int id) {