Mercurial > minori
diff src/services/kitsu.cc @ 389:1e5d922fe82b default tip
kitsu: implement UpdateAnimeEntry
yay... i guess
| author | Paper <paper@tflc.us> |
|---|---|
| date | Thu, 06 Nov 2025 12:21:35 -0500 |
| parents | 83aa0ddd1a46 |
| children |
line wrap: on
line diff
--- a/src/services/kitsu.cc Thu Nov 06 09:53:06 2025 -0500 +++ b/src/services/kitsu.cc Thu Nov 06 12:21:35 2025 -0500 @@ -139,7 +139,9 @@ /* ----------------------------------------------------------------------------- */ static std::optional<nlohmann::json> SendJSONAPIRequest(const std::string &path, - const std::map<std::string, std::string> ¶ms = {}) + const std::map<std::string, std::string> ¶ms = {}, + const std::string &data = "", + HTTP::Type type = HTTP::Type::Get) { std::optional<std::string> token = AccountAccessToken(); if (!token) @@ -151,7 +153,7 @@ const std::string url = HTTP::EncodeParamsList(std::string(BASE_API_PATH) + path, params); - const std::string response = Strings::ToUtf8String(HTTP::Request(url, headers, "", HTTP::Type::Get)); + const std::string response = Strings::ToUtf8String(HTTP::Request(url, headers, data, type)); if (response.empty()) return std::nullopt; @@ -165,9 +167,12 @@ } if (json.contains("/errors"_json_pointer)) { + std::cout << json["/errors"_json_pointer] << '\n'; +#if 0 for (const auto &item : json["/errors"]) std::cerr << "Kitsu: API returned error \"" << json["/errors/title"_json_pointer] << "\" with detail \"" << json["/errors/detail"] << std::endl; +#endif session.SetStatusBar(Strings::Translate("Kitsu: Request failed with errors!")); return std::nullopt; @@ -608,9 +613,91 @@ return true; } +static std::string UserStatusToString(Anime::ListStatus status) +{ + switch (status) { + case Anime::ListStatus::Planning: return "planned"; + case Anime::ListStatus::Completed: return "completed"; + case Anime::ListStatus::Dropped: return "dropped"; + case Anime::ListStatus::Paused: return "on_hold"; + default: break; + } + + return "current"; +} + int UpdateAnimeEntry(int id) { - return 0; + const Anime::Anime &anime = Anime::db.items[id]; + int score; + + if (!anime.IsInUserList()) + return 0; /* WTF */ + + nlohmann::json json = { + {"data", { + {"type", "libraryEntries"}, + {"attributes", { + {"status", UserStatusToString(anime.GetUserStatus())}, + {"progress", anime.GetUserProgress()}, + {"reconsuming", anime.GetUserIsRewatching()}, + {"reconsumeCount", anime.GetUserRewatchedTimes()}, + {"notes", anime.GetUserNotes()}, + {"private", anime.GetUserIsPrivate()}, + // WTF is reactionSkipped? + {"startedAt", anime.GetUserDateStarted().GetAsISO8601()}, + {"finishedAt", anime.GetUserDateCompleted().GetAsISO8601()}, + }}, + {"relationships", { + {"anime", { + {"data", { + {"type", "anime"}, + {"id", anime.GetServiceId(Anime::Service::Kitsu)}, + }} + }}, + {"user", { + {"data", { + {"type", "users"}, + {"id", session.config.auth.kitsu.user_id}, + }} + }} + }} + }} + }; + + nlohmann::json &attributes = json["data"]["attributes"]; + + score = anime.GetUserScore() / 5; + if (score > 0) { + attributes["ratingTwenty"] = score; + } else { + attributes["ratingTwenty"] = nullptr; + } + + /* I really don't like this */ + std::string uid = anime.GetUserId(); + + std::string path = "/library-entries"; + HTTP::Type type; + + if (!uid.empty()) { + json["data"]["id"] = uid; + path = path + "/" + uid; + type = HTTP::Type::Patch; + } else { + type = HTTP::Type::Post; + } + + std::optional<nlohmann::json> res = SendJSONAPIRequest(path, {}, json.dump(), type); + if (!res) + return 0; + + /* TODO parse result; can reduces races */ + + session.SetStatusBar(Strings::Translate("Kitsu: Anime entry updated successfully!")); + + /* I guess? */ + return Strings::ToInt<int>(anime.GetUserId()); } bool AuthorizeUser(const std::string &email, const std::string &password)
