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 |