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