Mercurial > minori
comparison src/services/anilist.cc @ 325:78929794e7d8
pages/seasons: run seasons search in a separate thread
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Thu, 13 Jun 2024 00:36:41 -0400 |
parents | 5d3c9b31aa6e |
children | b5d6c27c308f |
comparison
equal
deleted
inserted
replaced
324:5d3c9b31aa6e | 325:78929794e7d8 |
---|---|
21 #include <exception> | 21 #include <exception> |
22 #include <string_view> | 22 #include <string_view> |
23 | 23 |
24 #include <iostream> | 24 #include <iostream> |
25 | 25 |
26 /* This file really sucks because it was made when I was first | |
27 * really "learning" C++ */ | |
28 | |
29 using namespace nlohmann::literals::json_literals; | |
30 | |
31 namespace Services { | 26 namespace Services { |
32 namespace AniList { | 27 namespace AniList { |
33 | 28 |
34 static constexpr std::string_view CLIENT_ID = "13706"; | 29 static constexpr std::string_view CLIENT_ID = "13706"; |
30 | |
31 /* This is used in multiple queries, so just put it here I guess. */ | |
35 #define MEDIA_FIELDS \ | 32 #define MEDIA_FIELDS \ |
36 "coverImage {\n" \ | 33 "coverImage {\n" \ |
37 " large\n" \ | 34 " large\n" \ |
38 "}\n" \ | 35 "}\n" \ |
39 "id\n" \ | 36 "id\n" \ |
196 Translate::AniList::ToSeriesStatus(JSON::GetString<std::string>(json, "/status"_json_pointer, ""))); | 193 Translate::AniList::ToSeriesStatus(JSON::GetString<std::string>(json, "/status"_json_pointer, ""))); |
197 | 194 |
198 if (json.contains("/startDate"_json_pointer) && json["/startDate"_json_pointer].is_object()) | 195 if (json.contains("/startDate"_json_pointer) && json["/startDate"_json_pointer].is_object()) |
199 anime.SetStartedDate(Date(json["/startDate"_json_pointer])); | 196 anime.SetStartedDate(Date(json["/startDate"_json_pointer])); |
200 | 197 |
201 if (json.contains("/endDate"_json_pointer) && json["/endDate"_json_pointer].is_object()) | 198 anime.SetCompletedDate(json.contains("/endDate"_json_pointer) && json["/endDate"_json_pointer].is_object() |
202 anime.SetCompletedDate(Date(json["/endDate"_json_pointer])); | 199 ? Date(json["/endDate"_json_pointer]) |
203 else | 200 : anime.GetStartedDate()); |
204 anime.SetCompletedDate(anime.GetStartedDate()); | |
205 | 201 |
206 anime.SetPosterUrl(JSON::GetString<std::string>(json, "/coverImage/large"_json_pointer, "")); | 202 anime.SetPosterUrl(JSON::GetString<std::string>(json, "/coverImage/large"_json_pointer, "")); |
207 | 203 |
208 anime.SetAudienceScore(JSON::GetNumber(json, "/averageScore"_json_pointer, 0)); | 204 anime.SetAudienceScore(JSON::GetNumber(json, "/averageScore"_json_pointer, 0)); |
209 // anime.SetSeason(Translate::AniList::ToSeriesSeason(JSON::GetString<std::string>(json, "/season"_json_pointer, ""))); | 205 // anime.SetSeason(Translate::AniList::ToSeriesSeason(JSON::GetString<std::string>(json, "/season"_json_pointer, ""))); |
263 } | 259 } |
264 | 260 |
265 int GetAnimeList() { | 261 int GetAnimeList() { |
266 auto& auth = session.config.auth.anilist; | 262 auto& auth = session.config.auth.anilist; |
267 | 263 |
268 /* NOTE: these really ought to be in the qrc file */ | 264 static constexpr std::string_view query = |
269 constexpr std::string_view query = "query ($id: Int) {\n" | 265 "query ($id: Int) {\n" |
270 " MediaListCollection (userId: $id, type: ANIME) {\n" | 266 " MediaListCollection (userId: $id, type: ANIME) {\n" |
271 " lists {\n" | 267 " lists {\n" |
272 " name\n" | 268 " name\n" |
273 " entries {\n" | 269 " entries {\n" |
274 " score\n" | 270 " score\n" |
275 " notes\n" | 271 " notes\n" |
276 " status\n" | 272 " status\n" |
277 " progress\n" | 273 " progress\n" |
278 " startedAt {\n" | 274 " startedAt {\n" |
279 " year\n" | 275 " year\n" |
280 " month\n" | 276 " month\n" |
281 " day\n" | 277 " day\n" |
282 " }\n" | 278 " }\n" |
283 " completedAt {\n" | 279 " completedAt {\n" |
284 " year\n" | 280 " year\n" |
285 " month\n" | 281 " month\n" |
286 " day\n" | 282 " day\n" |
287 " }\n" | 283 " }\n" |
288 " updatedAt\n" | 284 " updatedAt\n" |
289 " media {\n" | 285 " media {\n" |
290 MEDIA_FIELDS | 286 MEDIA_FIELDS |
291 " }\n" | 287 " }\n" |
292 " }\n" | 288 " }\n" |
293 " }\n" | 289 " }\n" |
294 " }\n" | 290 " }\n" |
295 "}\n"; | 291 "}\n"; |
292 | |
296 // clang-format off | 293 // clang-format off |
297 nlohmann::json request = { | 294 nlohmann::json request = { |
298 {"query", query}, | 295 {"query", query}, |
299 {"variables", { | 296 {"variables", { |
300 {"id", auth.user_id} | 297 {"id", auth.user_id} |
324 return 1; | 321 return 1; |
325 } | 322 } |
326 | 323 |
327 /* return is a vector of anime ids */ | 324 /* return is a vector of anime ids */ |
328 std::vector<int> Search(const std::string& search) { | 325 std::vector<int> Search(const std::string& search) { |
329 constexpr std::string_view query = "query ($search: String) {\n" | 326 static constexpr std::string_view query = |
330 " Page (page: 1, perPage: 50) {\n" | 327 "query ($search: String) {\n" |
331 " media (search: $search, type: ANIME) {\n" | 328 " Page (page: 1, perPage: 50) {\n" |
332 MEDIA_FIELDS | 329 " media (search: $search, type: ANIME) {\n" |
333 " }\n" | 330 MEDIA_FIELDS |
334 " }\n" | 331 " }\n" |
335 "}\n"; | 332 " }\n" |
333 "}\n"; | |
336 | 334 |
337 // clang-format off | 335 // clang-format off |
338 nlohmann::json json = { | 336 nlohmann::json json = { |
339 {"query", query}, | 337 {"query", query}, |
340 {"variables", { | 338 {"variables", { |
357 ret.push_back(ParseMediaJson(media.value())); | 355 ret.push_back(ParseMediaJson(media.value())); |
358 | 356 |
359 return ret; | 357 return ret; |
360 } | 358 } |
361 | 359 |
362 std::vector<int> GetSeason(Anime::SeriesSeason season, Date::Year year) { | 360 bool GetSeason(Anime::SeriesSeason season, Date::Year year) { |
363 constexpr std::string_view query = "query ($season: MediaSeason!, $season_year: Int!, $page: Int) {\n" | 361 static constexpr std::string_view query = |
364 " Page(page: $page) {\n" | 362 "query ($season: MediaSeason!, $season_year: Int!, $page: Int) {\n" |
365 " media(season: $season, seasonYear: $season_year, type: ANIME, sort: START_DATE) {\n" | 363 " Page(page: $page) {\n" |
366 MEDIA_FIELDS | 364 " media(season: $season, seasonYear: $season_year, type: ANIME, sort: START_DATE) {\n" |
367 " }\n" | 365 MEDIA_FIELDS |
368 " pageInfo {\n" | 366 " }\n" |
369 " total\n" | 367 " pageInfo {\n" |
370 " perPage\n" | 368 " total\n" |
371 " currentPage\n" | 369 " perPage\n" |
372 " lastPage\n" | 370 " currentPage\n" |
373 " hasNextPage\n" | 371 " lastPage\n" |
374 " }\n" | 372 " hasNextPage\n" |
375 " }\n" | 373 " }\n" |
376 "}\n"; | 374 " }\n" |
377 std::vector<int> ret; | 375 "}\n"; |
378 | 376 |
379 int page = 0; | 377 int page = 0; |
380 bool has_next_page = true; | 378 bool has_next_page = true; |
379 | |
381 while (has_next_page) { | 380 while (has_next_page) { |
382 nlohmann::json json = { | 381 nlohmann::json json = { |
383 {"query", query}, | 382 {"query", query}, |
384 {"variables", { | 383 {"variables", { |
385 {"season", Translate::AniList::ToString(season)}, | 384 {"season", Translate::AniList::ToString(season)}, |
386 {"season_year", Strings::ToUtf8String(year)}, | 385 {"season_year", Strings::ToUtf8String(year)}, |
387 {"page", page} | 386 {"page", page}, |
388 }} | 387 }}, |
389 }; | 388 }; |
390 | 389 |
391 const std::optional<nlohmann::json> res = SendJSONRequest(json); | 390 const std::optional<nlohmann::json> res = SendJSONRequest(json); |
392 if (!res) | 391 if (!res) |
393 return {}; | 392 return false; |
394 | 393 |
395 const nlohmann::json& result = res.value(); | 394 const nlohmann::json& result = res.value(); |
396 | 395 |
397 ret.reserve(ret.capacity() + result["data"]["Page"]["media"].size()); | 396 for (const auto& media : result["/data/Page/media"_json_pointer].items()) |
398 | 397 ParseMediaJson(media.value()); |
399 for (const auto& media : result["data"]["Page"]["media"].items()) | |
400 ret.push_back(ParseMediaJson(media.value())); | |
401 | 398 |
402 has_next_page = JSON::GetBoolean(result, "/data/Page/pageInfo/hasNextPage"_json_pointer, false); | 399 has_next_page = JSON::GetBoolean(result, "/data/Page/pageInfo/hasNextPage"_json_pointer, false); |
403 if (has_next_page) | 400 if (has_next_page) |
404 page++; | 401 page++; |
405 } | 402 } |
406 | 403 |
407 return ret; | 404 return true; |
408 } | 405 } |
409 | 406 |
410 int UpdateAnimeEntry(int id) { | 407 int UpdateAnimeEntry(int id) { |
411 /** | |
412 * possible values: | |
413 * | |
414 * int mediaId, | |
415 * MediaListStatus status, | |
416 * float score, | |
417 * int scoreRaw, | |
418 * int progress, | |
419 * int progressVolumes, // manga-specific. | |
420 * int repeat, // rewatch | |
421 * int priority, | |
422 * bool private, | |
423 * string notes, | |
424 * bool hiddenFromStatusLists, | |
425 * string[] customLists, | |
426 * float[] advancedScores, | |
427 * Date startedAt, | |
428 * Date completedAt | |
429 **/ | |
430 Anime::Anime& anime = Anime::db.items[id]; | 408 Anime::Anime& anime = Anime::db.items[id]; |
431 if (!anime.IsInUserList()) | 409 if (!anime.IsInUserList()) |
432 return 0; | 410 return 0; |
433 | 411 |
434 std::optional<std::string> service_id = anime.GetServiceId(Anime::Service::AniList); | 412 std::optional<std::string> service_id = anime.GetServiceId(Anime::Service::AniList); |
435 if (!service_id) | 413 if (!service_id) |
436 return 0; | 414 return 0; |
437 | 415 |
438 session.SetStatusBar("AniList: Updating anime entry..."); | 416 static constexpr std::string_view query = |
439 | 417 "mutation ($media_id: Int, $progress: Int, $status: MediaListStatus, $score: Int, $notes: String," |
440 constexpr std::string_view query = | 418 " $start: FuzzyDateInput, $comp: FuzzyDateInput, $repeat: Int) {\n" |
441 "mutation ($media_id: Int, $progress: Int, $status: MediaListStatus, $score: Int, $notes: String, $start: " | 419 " SaveMediaListEntry (mediaId: $media_id, progress: $progress, status: $status, scoreRaw: $score," |
442 "FuzzyDateInput, $comp: FuzzyDateInput, $repeat: Int) {\n" | 420 " notes: $notes, startedAt: $start, completedAt: $comp, repeat: $repeat) {\n" |
443 " SaveMediaListEntry (mediaId: $media_id, progress: $progress, status: $status, scoreRaw: $score, notes: " | |
444 "$notes, startedAt: $start, completedAt: $comp, repeat: $repeat) {\n" | |
445 " id\n" | 421 " id\n" |
446 " }\n" | 422 " }\n" |
447 "}\n"; | 423 "}\n"; |
448 // clang-format off | 424 // clang-format off |
449 nlohmann::json json = { | 425 nlohmann::json json = { |
495 | 471 |
496 auth.auth_token = Strings::ToUtf8String(token); | 472 auth.auth_token = Strings::ToUtf8String(token); |
497 | 473 |
498 session.SetStatusBar("AniList: Requesting user ID..."); | 474 session.SetStatusBar("AniList: Requesting user ID..."); |
499 | 475 |
500 constexpr std::string_view query = "query {\n" | 476 static constexpr std::string_view query = |
501 " Viewer {\n" | 477 "query {\n" |
502 " id\n" | 478 " Viewer {\n" |
503 " }\n" | 479 " id\n" |
504 "}\n"; | 480 " }\n" |
481 "}\n"; | |
482 | |
505 nlohmann::json json = { | 483 nlohmann::json json = { |
506 {"query", query} | 484 {"query", query} |
507 }; | 485 }; |
508 | 486 |
509 /* SendJSONRequest handles status errors */ | 487 /* SendJSONRequest handles status errors */ |