Mercurial > minori
comparison src/services/anilist.cc @ 304:2115488eb302
*: add very early season searcher
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Mon, 13 May 2024 17:02:35 -0400 |
| parents | 9a88e1725fd2 |
| children | 91ac90a34003 |
comparison
equal
deleted
inserted
replaced
| 303:ab7ff259b4ca | 304:2115488eb302 |
|---|---|
| 1 #include "services/anilist.h" | 1 #include "services/anilist.h" |
| 2 #include "core/anime.h" | 2 #include "core/anime.h" |
| 3 #include "core/anime_db.h" | 3 #include "core/anime_db.h" |
| 4 #include "core/date.h" | |
| 4 #include "core/config.h" | 5 #include "core/config.h" |
| 5 #include "core/http.h" | 6 #include "core/http.h" |
| 6 #include "core/json.h" | 7 #include "core/json.h" |
| 7 #include "core/session.h" | 8 #include "core/session.h" |
| 8 #include "core/strings.h" | 9 #include "core/strings.h" |
| 26 | 27 |
| 27 namespace Services { | 28 namespace Services { |
| 28 namespace AniList { | 29 namespace AniList { |
| 29 | 30 |
| 30 static constexpr std::string_view CLIENT_ID = "13706"; | 31 static constexpr std::string_view CLIENT_ID = "13706"; |
| 32 #define MEDIA_FIELDS \ | |
| 33 "coverImage {\n" \ | |
| 34 " large\n" \ | |
| 35 "}\n" \ | |
| 36 "id\n" \ | |
| 37 "title {\n" \ | |
| 38 " romaji\n" \ | |
| 39 " english\n" \ | |
| 40 " native\n" \ | |
| 41 "}\n" \ | |
| 42 "format\n" \ | |
| 43 "status\n" \ | |
| 44 "averageScore\n" \ | |
| 45 "season\n" \ | |
| 46 "startDate {\n" \ | |
| 47 " year\n" \ | |
| 48 " month\n" \ | |
| 49 " day\n" \ | |
| 50 "}\n" \ | |
| 51 "genres\n" \ | |
| 52 "episodes\n" \ | |
| 53 "duration\n" \ | |
| 54 "synonyms\n" \ | |
| 55 "description(asHtml: false)\n" | |
| 31 | 56 |
| 32 class Account { | 57 class Account { |
| 33 public: | 58 public: |
| 34 int UserId() const { return session.config.auth.anilist.user_id; } | 59 int UserId() const { return session.config.auth.anilist.user_id; } |
| 35 void SetUserId(const int id) { session.config.auth.anilist.user_id = id; } | 60 void SetUserId(const int id) { session.config.auth.anilist.user_id = id; } |
| 213 " month\n" | 238 " month\n" |
| 214 " day\n" | 239 " day\n" |
| 215 " }\n" | 240 " }\n" |
| 216 " updatedAt\n" | 241 " updatedAt\n" |
| 217 " media {\n" | 242 " media {\n" |
| 218 " coverImage {\n" | 243 MEDIA_FIELDS |
| 219 " large\n" | |
| 220 " }\n" | |
| 221 " id\n" | |
| 222 " title {\n" | |
| 223 " romaji\n" | |
| 224 " english\n" | |
| 225 " native\n" | |
| 226 " }\n" | |
| 227 " format\n" | |
| 228 " status\n" | |
| 229 " averageScore\n" | |
| 230 " season\n" | |
| 231 " startDate {\n" | |
| 232 " year\n" | |
| 233 " month\n" | |
| 234 " day\n" | |
| 235 " }\n" | |
| 236 " genres\n" | |
| 237 " episodes\n" | |
| 238 " duration\n" | |
| 239 " synonyms\n" | |
| 240 " description(asHtml: false)\n" | |
| 241 " }\n" | 244 " }\n" |
| 242 " }\n" | 245 " }\n" |
| 243 " }\n" | 246 " }\n" |
| 244 " }\n" | 247 " }\n" |
| 245 "}\n"; | 248 "}\n"; |
| 252 }; | 255 }; |
| 253 // clang-format on | 256 // clang-format on |
| 254 | 257 |
| 255 auto res = SendJSONRequest(json); | 258 auto res = SendJSONRequest(json); |
| 256 | 259 |
| 257 for (const auto& list : res["data"]["MediaListCollection"]["lists"].items()) { | 260 for (const auto& list : res["data"]["MediaListCollection"]["lists"].items()) |
| 258 ParseList(list.value()); | 261 ParseList(list.value()); |
| 259 } | 262 |
| 260 return 1; | 263 return 1; |
| 261 } | 264 } |
| 262 | 265 |
| 263 /* return is a vector of anime ids */ | 266 /* return is a vector of anime ids */ |
| 264 std::vector<int> Search(const std::string& search) { | 267 std::vector<int> Search(const std::string& search) { |
| 265 constexpr std::string_view query = "query ($search: String) {\n" | 268 constexpr std::string_view query = "query ($search: String) {\n" |
| 266 " Page (page: 1, perPage: 50) {\n" | 269 " Page (page: 1, perPage: 50) {\n" |
| 267 " media (search: $search, type: ANIME) {\n" | 270 " media (search: $search, type: ANIME) {\n" |
| 268 " coverImage {\n" | 271 MEDIA_FIELDS |
| 269 " large\n" | |
| 270 " }\n" | |
| 271 " id\n" | |
| 272 " id_mal\n" | |
| 273 " title {\n" | |
| 274 " romaji\n" | |
| 275 " english\n" | |
| 276 " native\n" | |
| 277 " }\n" | |
| 278 " format\n" | |
| 279 " status\n" | |
| 280 " averageScore\n" | |
| 281 " season\n" | |
| 282 " startDate {\n" | |
| 283 " year\n" | |
| 284 " month\n" | |
| 285 " day\n" | |
| 286 " }\n" | |
| 287 " genres\n" | |
| 288 " episodes\n" | |
| 289 " duration\n" | |
| 290 " synonyms\n" | |
| 291 " description(asHtml: false)\n" | |
| 292 " }\n" | 272 " }\n" |
| 293 " }\n" | 273 " }\n" |
| 294 "}\n"; | 274 "}\n"; |
| 295 | 275 |
| 296 // clang-format off | 276 // clang-format off |
| 302 }; | 282 }; |
| 303 // clang-format on | 283 // clang-format on |
| 304 | 284 |
| 305 auto res = SendJSONRequest(json); | 285 auto res = SendJSONRequest(json); |
| 306 | 286 |
| 287 /* FIXME: error handling here */ | |
| 307 std::vector<int> ret; | 288 std::vector<int> ret; |
| 308 ret.reserve(res["data"]["Page"]["media"].size()); | 289 ret.reserve(res["data"]["Page"]["media"].size()); |
| 309 | 290 |
| 310 for (const auto& media : res["data"]["Page"]["media"].items()) | 291 for (const auto& media : res["data"]["Page"]["media"].items()) |
| 311 ret.push_back(ParseMediaJson(media.value())); | 292 ret.push_back(ParseMediaJson(media.value())); |
| 293 | |
| 294 return ret; | |
| 295 } | |
| 296 | |
| 297 std::vector<int> GetSeason(Anime::SeriesSeason season, Date::Year year) { | |
| 298 constexpr std::string_view query = "query ($season: MediaSeason!, $season_year: Int!, $page: Int) {\n" | |
| 299 " Page(page: $page) {\n" | |
| 300 " media(season: $season, seasonYear: $season_year, type: ANIME, sort: START_DATE) {\n" | |
| 301 MEDIA_FIELDS | |
| 302 " }\n" | |
| 303 " pageInfo {\n" | |
| 304 " total\n" | |
| 305 " perPage\n" | |
| 306 " currentPage\n" | |
| 307 " lastPage\n" | |
| 308 " hasNextPage\n" | |
| 309 " }\n" | |
| 310 " }\n" | |
| 311 "}\n"; | |
| 312 std::vector<int> ret; | |
| 313 | |
| 314 int page = 0; | |
| 315 bool has_next_page = true; | |
| 316 while (has_next_page) { | |
| 317 nlohmann::json json = { | |
| 318 {"query", query}, | |
| 319 {"variables", { | |
| 320 {"season", Translate::AniList::ToString(season)}, | |
| 321 {"season_year", Strings::ToUtf8String(year)}, | |
| 322 {"page", page} | |
| 323 }} | |
| 324 }; | |
| 325 | |
| 326 auto res = SendJSONRequest(json); | |
| 327 ret.reserve(ret.capacity() + res["data"]["Page"]["media"].size()); | |
| 328 | |
| 329 for (const auto& media : res["data"]["Page"]["media"].items()) | |
| 330 ret.push_back(ParseMediaJson(media.value())); | |
| 331 | |
| 332 has_next_page = JSON::GetBoolean(res, "/data/Page/pageInfo/hasNextPage"_json_pointer, false); | |
| 333 if (has_next_page) | |
| 334 page++; | |
| 335 } | |
| 312 | 336 |
| 313 return ret; | 337 return ret; |
| 314 } | 338 } |
| 315 | 339 |
| 316 int UpdateAnimeEntry(int id) { | 340 int UpdateAnimeEntry(int id) { |
