Mercurial > minori
comparison src/services/anilist.cc @ 315:34347fd2a2de
session: allow printing status messages
...!
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Tue, 11 Jun 2024 14:16:40 -0400 |
parents | 91ac90a34003 |
children | b1f4d1867ab1 |
comparison
equal
deleted
inserted
replaced
314:76d7315504c4 | 315:34347fd2a2de |
---|---|
72 std::vector<std::string> headers = {"Authorization: Bearer " + account.AuthToken(), "Accept: application/json", | 72 std::vector<std::string> headers = {"Authorization: Bearer " + account.AuthToken(), "Accept: application/json", |
73 "Content-Type: application/json"}; | 73 "Content-Type: application/json"}; |
74 return Strings::ToUtf8String(HTTP::Request("https://graphql.anilist.co", headers, data, HTTP::Type::Post)); | 74 return Strings::ToUtf8String(HTTP::Request("https://graphql.anilist.co", headers, data, HTTP::Type::Post)); |
75 } | 75 } |
76 | 76 |
77 static nlohmann::json SendJSONRequest(const nlohmann::json& data) { | 77 static bool SendJSONRequest(const nlohmann::json& data, nlohmann::json& out) { |
78 std::string request = SendRequest(data.dump()); | 78 std::string request = SendRequest(data.dump()); |
79 if (request.empty()) { | 79 if (request.empty()) { |
80 std::cerr << "[AniList] JSON Request returned an empty result!" << std::endl; | 80 session.SetStatusBar("AniList: JSON request returned an empty result!"); |
81 return {}; | 81 return false; |
82 } | 82 } |
83 | 83 |
84 auto ret = nlohmann::json::parse(request, nullptr, false); | 84 out = nlohmann::json::parse(request, nullptr, false); |
85 if (ret.is_discarded()) { | 85 if (out.is_discarded()) { |
86 std::cerr << "[AniList] Failed to parse request JSON!" << std::endl; | 86 session.SetStatusBar("AniList: Failed to parse request JSON!"); |
87 return {}; | 87 return false; |
88 } | 88 } |
89 | 89 |
90 if (ret.contains("/errors"_json_pointer) && ret.at("/errors"_json_pointer).is_array()) { | 90 if (out.contains("/errors"_json_pointer) && out.at("/errors"_json_pointer).is_array()) { |
91 for (const auto& error : ret.at("/errors"_json_pointer)) | 91 for (const auto& error : out.at("/errors"_json_pointer)) |
92 std::cerr << "[AniList] Received an error in response: " | 92 std::cerr << "[AniList] Received an error in response: " |
93 << JSON::GetString<std::string>(error, "/message"_json_pointer, "") << std::endl; | 93 << JSON::GetString<std::string>(error, "/message"_json_pointer, "") << std::endl; |
94 | 94 |
95 return {}; | 95 session.SetStatusBar("AniList: Received an error in response!"); |
96 } | 96 return false; |
97 | 97 } |
98 return ret; | 98 |
99 return true; | |
99 } | 100 } |
100 | 101 |
101 static void ParseListStatus(std::string status, Anime::Anime& anime) { | 102 static void ParseListStatus(std::string status, Anime::Anime& anime) { |
102 static const std::unordered_map<std::string, Anime::ListStatus> map = { | 103 static const std::unordered_map<std::string, Anime::ListStatus> map = { |
103 {"CURRENT", Anime::ListStatus::Current }, | 104 {"CURRENT", Anime::ListStatus::Current }, |
210 return 1; | 211 return 1; |
211 } | 212 } |
212 | 213 |
213 int GetAnimeList() { | 214 int GetAnimeList() { |
214 if (!account.IsValid()) { | 215 if (!account.IsValid()) { |
215 std::cerr << "AniList: Account isn't valid!" << std::endl; | 216 session.SetStatusBar("AniList: Account isn't valid!"); |
216 return 0; | 217 return 0; |
217 } | 218 } |
219 | |
220 session.SetStatusBar("AniList: Retrieving anime list..."); | |
218 | 221 |
219 /* NOTE: these really ought to be in the qrc file */ | 222 /* NOTE: these really ought to be in the qrc file */ |
220 constexpr std::string_view query = "query ($id: Int) {\n" | 223 constexpr std::string_view query = "query ($id: Int) {\n" |
221 " MediaListCollection (userId: $id, type: ANIME) {\n" | 224 " MediaListCollection (userId: $id, type: ANIME) {\n" |
222 " lists {\n" | 225 " lists {\n" |
251 {"id", account.UserId()} | 254 {"id", account.UserId()} |
252 }} | 255 }} |
253 }; | 256 }; |
254 // clang-format on | 257 // clang-format on |
255 | 258 |
256 auto res = SendJSONRequest(json); | 259 session.SetStatusBar("AniList: Parsing anime list..."); |
257 | 260 |
258 for (const auto& list : res["data"]["MediaListCollection"]["lists"].items()) | 261 nlohmann::json result; |
262 const bool res = SendJSONRequest(json, result); | |
263 if (!res) | |
264 return 0; | |
265 | |
266 for (const auto& list : result["data"]["MediaListCollection"]["lists"].items()) | |
259 ParseList(list.value()); | 267 ParseList(list.value()); |
268 | |
269 session.SetStatusBar("AniList: Retrieved anime list successfully!"); | |
260 | 270 |
261 return 1; | 271 return 1; |
262 } | 272 } |
263 | 273 |
264 /* return is a vector of anime ids */ | 274 /* return is a vector of anime ids */ |
278 {"search", search} | 288 {"search", search} |
279 }} | 289 }} |
280 }; | 290 }; |
281 // clang-format on | 291 // clang-format on |
282 | 292 |
283 auto res = SendJSONRequest(json); | 293 nlohmann::json result; |
294 const bool res = SendJSONRequest(json, result); | |
295 if (!res) | |
296 return {}; | |
284 | 297 |
285 /* FIXME: error handling here */ | 298 /* FIXME: error handling here */ |
286 std::vector<int> ret; | 299 std::vector<int> ret; |
287 ret.reserve(res["data"]["Page"]["media"].size()); | 300 ret.reserve(result["/data/Page/media"_json_pointer].size()); |
288 | 301 |
289 for (const auto& media : res["data"]["Page"]["media"].items()) | 302 for (const auto& media : result["/data/Page/media"_json_pointer].items()) |
290 ret.push_back(ParseMediaJson(media.value())); | 303 ret.push_back(ParseMediaJson(media.value())); |
291 | 304 |
292 return ret; | 305 return ret; |
293 } | 306 } |
294 | 307 |
319 {"season_year", Strings::ToUtf8String(year)}, | 332 {"season_year", Strings::ToUtf8String(year)}, |
320 {"page", page} | 333 {"page", page} |
321 }} | 334 }} |
322 }; | 335 }; |
323 | 336 |
324 auto res = SendJSONRequest(json); | 337 nlohmann::json result; |
325 ret.reserve(ret.capacity() + res["data"]["Page"]["media"].size()); | 338 const bool res = SendJSONRequest(json, result); |
326 | 339 if (!res) |
327 for (const auto& media : res["data"]["Page"]["media"].items()) | 340 return {}; |
341 | |
342 ret.reserve(ret.capacity() + result["data"]["Page"]["media"].size()); | |
343 | |
344 for (const auto& media : result["data"]["Page"]["media"].items()) | |
328 ret.push_back(ParseMediaJson(media.value())); | 345 ret.push_back(ParseMediaJson(media.value())); |
329 | 346 |
330 has_next_page = JSON::GetBoolean(res, "/data/Page/pageInfo/hasNextPage"_json_pointer, false); | 347 has_next_page = JSON::GetBoolean(result, "/data/Page/pageInfo/hasNextPage"_json_pointer, false); |
331 if (has_next_page) | 348 if (has_next_page) |
332 page++; | 349 page++; |
333 } | 350 } |
334 | 351 |
335 return ret; | 352 return ret; |
360 return 0; | 377 return 0; |
361 | 378 |
362 std::optional<std::string> service_id = anime.GetServiceId(Anime::Service::AniList); | 379 std::optional<std::string> service_id = anime.GetServiceId(Anime::Service::AniList); |
363 if (!service_id) | 380 if (!service_id) |
364 return 0; | 381 return 0; |
382 | |
383 session.SetStatusBar("AniList: Updating anime entry..."); | |
365 | 384 |
366 constexpr std::string_view query = | 385 constexpr std::string_view query = |
367 "mutation ($media_id: Int, $progress: Int, $status: MediaListStatus, $score: Int, $notes: String, $start: " | 386 "mutation ($media_id: Int, $progress: Int, $status: MediaListStatus, $score: Int, $notes: String, $start: " |
368 "FuzzyDateInput, $comp: FuzzyDateInput, $repeat: Int) {\n" | 387 "FuzzyDateInput, $comp: FuzzyDateInput, $repeat: Int) {\n" |
369 " SaveMediaListEntry (mediaId: $media_id, progress: $progress, status: $status, scoreRaw: $score, notes: " | 388 " SaveMediaListEntry (mediaId: $media_id, progress: $progress, status: $status, scoreRaw: $score, notes: " |
385 {"repeat", anime.GetUserRewatchedTimes()} | 404 {"repeat", anime.GetUserRewatchedTimes()} |
386 }} | 405 }} |
387 }; | 406 }; |
388 // clang-format on | 407 // clang-format on |
389 | 408 |
390 auto ret = SendJSONRequest(json); | 409 nlohmann::json result; |
391 | 410 const bool ret = SendJSONRequest(json, result); |
392 return JSON::GetNumber(ret, "/data/SaveMediaListEntry/id"_json_pointer, 0); | 411 if (!ret) |
412 return 0; | |
413 | |
414 session.SetStatusBar("AniList: Anime entry updated successfully!"); | |
415 | |
416 return JSON::GetNumber(result, "/data/SaveMediaListEntry/id"_json_pointer, 0); | |
393 } | 417 } |
394 | 418 |
395 static int ParseUser(const nlohmann::json& json) { | 419 static int ParseUser(const nlohmann::json& json) { |
396 account.SetUserId(JSON::GetNumber(json, "/id"_json_pointer, 0)); | 420 account.SetUserId(JSON::GetNumber(json, "/id"_json_pointer, 0)); |
397 return account.UserId(); | 421 return account.UserId(); |
409 | 433 |
410 if (!ok || token.isEmpty()) | 434 if (!ok || token.isEmpty()) |
411 return false; | 435 return false; |
412 | 436 |
413 account.SetAuthToken(Strings::ToUtf8String(token)); | 437 account.SetAuthToken(Strings::ToUtf8String(token)); |
438 | |
439 session.SetStatusBar("AniList: Requesting user ID..."); | |
414 | 440 |
415 constexpr std::string_view query = "query {\n" | 441 constexpr std::string_view query = "query {\n" |
416 " Viewer {\n" | 442 " Viewer {\n" |
417 " id\n" | 443 " id\n" |
418 " name\n" | 444 " name\n" |
423 "}\n"; | 449 "}\n"; |
424 nlohmann::json json = { | 450 nlohmann::json json = { |
425 {"query", query} | 451 {"query", query} |
426 }; | 452 }; |
427 | 453 |
428 auto ret = SendJSONRequest(json); | 454 /* SendJSONRequest handles status errors */ |
455 nlohmann::json result; | |
456 const bool ret = SendJSONRequest(json, result); | |
457 if (!ret) | |
458 return 0; | |
459 | |
460 session.SetStatusBar("AniList: Successfully retrieved user data!"); | |
429 | 461 |
430 ParseUser(ret["data"]["Viewer"]); | 462 ParseUser(ret["data"]["Viewer"]); |
431 return true; | 463 return true; |
432 } | 464 } |
433 | 465 |