Mercurial > minori
comparison src/services/anilist.cc @ 317:b1f4d1867ab1
services: VERY initial Kitsu support
it only supports user authentication for now, but it's definitely
a start.
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Wed, 12 Jun 2024 04:07:10 -0400 |
| parents | 34347fd2a2de |
| children | d928ec7b6a0d |
comparison
equal
deleted
inserted
replaced
| 316:180714442770 | 317:b1f4d1867ab1 |
|---|---|
| 20 #include <chrono> | 20 #include <chrono> |
| 21 #include <exception> | 21 #include <exception> |
| 22 #include <string_view> | 22 #include <string_view> |
| 23 | 23 |
| 24 #include <iostream> | 24 #include <iostream> |
| 25 | |
| 26 /* This file really sucks because it was made when I was first | |
| 27 * really "learning" C++ */ | |
| 25 | 28 |
| 26 using namespace nlohmann::literals::json_literals; | 29 using namespace nlohmann::literals::json_literals; |
| 27 | 30 |
| 28 namespace Services { | 31 namespace Services { |
| 29 namespace AniList { | 32 namespace AniList { |
| 52 "episodes\n" \ | 55 "episodes\n" \ |
| 53 "duration\n" \ | 56 "duration\n" \ |
| 54 "synonyms\n" \ | 57 "synonyms\n" \ |
| 55 "description(asHtml: false)\n" | 58 "description(asHtml: false)\n" |
| 56 | 59 |
| 57 class Account { | 60 /* FIXME: why is this here */ |
| 58 public: | 61 |
| 62 static struct { | |
| 59 int UserId() const { return session.config.auth.anilist.user_id; } | 63 int UserId() const { return session.config.auth.anilist.user_id; } |
| 60 void SetUserId(const int id) { session.config.auth.anilist.user_id = id; } | 64 void SetUserId(const int id) { session.config.auth.anilist.user_id = id; } |
| 61 | 65 |
| 62 std::string AuthToken() const { return session.config.auth.anilist.auth_token; } | 66 std::string AuthToken() const { return session.config.auth.anilist.auth_token; } |
| 63 void SetAuthToken(const std::string& auth_token) { session.config.auth.anilist.auth_token = auth_token; } | 67 void SetAuthToken(const std::string& auth_token) { session.config.auth.anilist.auth_token = auth_token; } |
| 64 | 68 |
| 65 bool Authenticated() const { return !AuthToken().empty(); } | 69 bool IsValid() const { return UserId() && !AuthToken().empty(); } |
| 66 bool IsValid() const { return UserId() && Authenticated(); } | 70 } account; |
| 67 }; | |
| 68 | |
| 69 static Account account; | |
| 70 | 71 |
| 71 static std::string SendRequest(const std::string& data) { | 72 static std::string SendRequest(const std::string& data) { |
| 72 std::vector<std::string> headers = {"Authorization: Bearer " + account.AuthToken(), "Accept: application/json", | 73 std::vector<std::string> headers = {"Authorization: Bearer " + account.AuthToken(), "Accept: application/json", |
| 73 "Content-Type: application/json"}; | 74 "Content-Type: application/json"}; |
| 74 return Strings::ToUtf8String(HTTP::Request("https://graphql.anilist.co", headers, data, HTTP::Type::Post)); | 75 return Strings::ToUtf8String(HTTP::Request("https://graphql.anilist.co", headers, data, HTTP::Type::Post)); |
| 87 return false; | 88 return false; |
| 88 } | 89 } |
| 89 | 90 |
| 90 if (out.contains("/errors"_json_pointer) && out.at("/errors"_json_pointer).is_array()) { | 91 if (out.contains("/errors"_json_pointer) && out.at("/errors"_json_pointer).is_array()) { |
| 91 for (const auto& error : out.at("/errors"_json_pointer)) | 92 for (const auto& error : out.at("/errors"_json_pointer)) |
| 92 std::cerr << "[AniList] Received an error in response: " | 93 std::cerr << "AniList: Received an error in response: " |
| 93 << JSON::GetString<std::string>(error, "/message"_json_pointer, "") << std::endl; | 94 << JSON::GetString<std::string>(error, "/message"_json_pointer, "") << std::endl; |
| 94 | 95 |
| 95 session.SetStatusBar("AniList: Received an error in response!"); | 96 session.SetStatusBar("AniList: Received an error in response!"); |
| 96 return false; | 97 return false; |
| 97 } | 98 } |
| 147 if (json.contains(ptr) && json[ptr].is_string()) | 148 if (json.contains(ptr) && json[ptr].is_string()) |
| 148 anime.SetTitle(language, json[ptr]); | 149 anime.SetTitle(language, json[ptr]); |
| 149 } | 150 } |
| 150 | 151 |
| 151 static int ParseMediaJson(const nlohmann::json& json) { | 152 static int ParseMediaJson(const nlohmann::json& json) { |
| 152 int id = JSON::GetNumber(json, "/id"_json_pointer); | 153 if (!json.contains("/id"_json_pointer) || !json["/id"_json_pointer].is_number()) |
| 153 if (!id) | 154 return 0; |
| 154 return 0; | 155 |
| 156 std::string service_id = Strings::ToUtf8String(json["/id"_json_pointer].get<int>()); | |
| 157 | |
| 158 int id = Anime::db.LookupServiceIdOrUnused(Anime::Service::AniList, service_id); | |
| 155 | 159 |
| 156 Anime::Anime& anime = Anime::db.items[id]; | 160 Anime::Anime& anime = Anime::db.items[id]; |
| 157 anime.SetId(id); | 161 anime.SetId(id); |
| 158 anime.SetServiceId(Anime::Service::AniList, Strings::ToUtf8String(id)); | 162 anime.SetServiceId(Anime::Service::AniList, service_id); |
| 159 anime.SetServiceId(Anime::Service::MyAnimeList, Strings::ToUtf8String(JSON::GetNumber(json, "/id_mal"_json_pointer))); | 163 |
| 164 if (json.contains("/id_mal"_json_pointer)) | |
| 165 anime.SetServiceId(Anime::Service::MyAnimeList, json["/id_mal"_json_pointer].get<std::string>()); | |
| 160 | 166 |
| 161 ParseTitle(json.at("/title"_json_pointer), anime); | 167 ParseTitle(json.at("/title"_json_pointer), anime); |
| 162 | 168 |
| 163 anime.SetEpisodes(JSON::GetNumber(json, "/episodes"_json_pointer, 0)); | 169 anime.SetEpisodes(JSON::GetNumber(json, "/episodes"_json_pointer, 0)); |
| 164 anime.SetFormat(Translate::AniList::ToSeriesFormat(JSON::GetString<std::string>(json, "/format"_json_pointer, ""))); | 170 anime.SetFormat(Translate::AniList::ToSeriesFormat(JSON::GetString<std::string>(json, "/format"_json_pointer, ""))); |
| 183 | 189 |
| 184 return id; | 190 return id; |
| 185 } | 191 } |
| 186 | 192 |
| 187 static int ParseListItem(const nlohmann::json& json) { | 193 static int ParseListItem(const nlohmann::json& json) { |
| 188 int id = ParseMediaJson(json["media"]); | 194 int id = ParseMediaJson(json); |
| 195 if (!id) | |
| 196 return 0; | |
| 189 | 197 |
| 190 Anime::Anime& anime = Anime::db.items[id]; | 198 Anime::Anime& anime = Anime::db.items[id]; |
| 191 | 199 |
| 192 anime.AddToUserList(); | 200 anime.AddToUserList(); |
| 193 | 201 |
| 203 | 211 |
| 204 return id; | 212 return id; |
| 205 } | 213 } |
| 206 | 214 |
| 207 static int ParseList(const nlohmann::json& json) { | 215 static int ParseList(const nlohmann::json& json) { |
| 208 for (const auto& entry : json["entries"].items()) { | 216 for (const auto& entry : json["entries"].items()) |
| 209 ParseListItem(entry.value()); | 217 ParseListItem(entry.value()); |
| 210 } | 218 |
| 211 return 1; | 219 return 1; |
| 212 } | 220 } |
| 213 | 221 |
| 214 int GetAnimeList() { | 222 int GetAnimeList() { |
| 215 if (!account.IsValid()) { | 223 if (!account.IsValid()) { |
| 216 session.SetStatusBar("AniList: Account isn't valid!"); | 224 session.SetStatusBar("AniList: Account isn't valid! (unauthorized?)"); |
| 217 return 0; | 225 return 0; |
| 218 } | 226 } |
| 219 | 227 |
| 220 session.SetStatusBar("AniList: Retrieving anime list..."); | 228 session.SetStatusBar("AniList: Retrieving anime list..."); |
| 221 | 229 |
