diff src/services/anilist.cpp @ 15:cde8f67a7c7d

*: update, megacommit :)
author Paper <mrpapersonic@gmail.com>
date Tue, 19 Sep 2023 22:36:08 -0400
parents fc1bf97c528b
children 2743011a6042
line wrap: on
line diff
--- a/src/services/anilist.cpp	Tue Sep 19 16:33:07 2023 -0400
+++ b/src/services/anilist.cpp	Tue Sep 19 22:36:08 2023 -0400
@@ -5,6 +5,7 @@
 #include "core/json.h"
 #include "core/session.h"
 #include "core/strings.h"
+#include "gui/translate/anilist.h"
 #include <QDesktopServices>
 #include <QInputDialog>
 #include <QLineEdit>
@@ -16,20 +17,24 @@
 #include <format>
 #define CLIENT_ID "13706"
 
-using nlohmann::literals::operator "" _json_pointer;
+using nlohmann::literals::operator"" _json_pointer;
 
 namespace Services::AniList {
 
 class Account {
 	public:
 		std::string Username() const { return session.config.anilist.username; }
-		void SetUsername(std::string const& username) { session.config.anilist.username = username; }
+		void SetUsername(std::string const& username) {
+			session.config.anilist.username = username;
+		}
 
 		int UserId() const { return session.config.anilist.user_id; }
 		void SetUserId(const int id) { session.config.anilist.user_id = id; }
 
 		std::string AuthToken() const { return session.config.anilist.auth_token; }
-		void SetAuthToken(std::string const& auth_token) { session.config.anilist.auth_token = auth_token; }
+		void SetAuthToken(std::string const& auth_token) {
+			session.config.anilist.auth_token = auth_token;
+		}
 
 		bool Authenticated() const { return !AuthToken().empty(); }
 };
@@ -47,9 +52,9 @@
 	std::string userdata;
 	CURL* curl = curl_easy_init();
 	if (curl) {
+		std::string bearer = "Authorization: Bearer " + account.AuthToken();
 		list = curl_slist_append(list, "Accept: application/json");
 		list = curl_slist_append(list, "Content-Type: application/json");
-		std::string bearer = "Authorization: Bearer " + account.AuthToken();
 		list = curl_slist_append(list, bearer.c_str());
 		curl_easy_setopt(curl, CURLOPT_URL, "https://graphql.anilist.co");
 		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
@@ -63,7 +68,8 @@
 		curl_easy_cleanup(curl);
 		if (res != CURLE_OK) {
 			QMessageBox box(QMessageBox::Icon::Critical, "",
-							QString("curl_easy_perform(curl) failed!: ") + QString(curl_easy_strerror(res)));
+			                QString("curl_easy_perform(curl) failed!: ") +
+			                    QString(curl_easy_strerror(res)));
 			box.exec();
 			return "";
 		}
@@ -72,52 +78,45 @@
 	return "";
 }
 
-/* TODO: Move to Translate */
+void ParseListStatus(std::string status, Anime::Anime& anime) {
+	std::unordered_map<std::string, Anime::ListStatus> map = {
+	    {"CURRENT",   Anime::ListStatus::CURRENT  },
+	    {"PLANNING",  Anime::ListStatus::PLANNING },
+	    {"COMPLETED", Anime::ListStatus::COMPLETED},
+	    {"DROPPED",   Anime::ListStatus::DROPPED  },
+	    {"PAUSED",    Anime::ListStatus::PAUSED   }
+    };
 
-std::map<std::string, Anime::ListStatus> AniListStringToAnimeWatchingMap = {
-	{"CURRENT",	Anime::ListStatus::CURRENT  },
-	  {"PLANNING",  Anime::ListStatus::PLANNING },
-	  {"COMPLETED", Anime::ListStatus::COMPLETED},
-	{"DROPPED",	Anime::ListStatus::DROPPED  },
-	  {"PAUSED",	 Anime::ListStatus::PAUSED   },
-	  {"REPEATING", Anime::ListStatus::CURRENT}
-};
+	if (status == "REPEATING") {
+		anime.SetUserIsRewatching(true);
+		anime.SetUserStatus(Anime::ListStatus::CURRENT);
+		return;
+	}
 
-std::map<Anime::ListStatus, std::string> AniListAnimeWatchingToStringMap = {
-	{Anime::ListStatus::CURRENT,	  "CURRENT"  },
-	  {Anime::ListStatus::PLANNING,	 "PLANNING" },
-	  {Anime::ListStatus::COMPLETED, "COMPLETED"},
-	{Anime::ListStatus::DROPPED,	  "DROPPED"  },
-	  {Anime::ListStatus::PAUSED,	   "PAUSED"   }
-};
+	if (!map.contains(status)) {
+		anime.SetUserStatus(Anime::ListStatus::NOT_IN_LIST);
+		return;
+	}
 
-std::map<std::string, Anime::SeriesStatus> AniListStringToAnimeAiringMap = {
-	{"FINISHED",		 Anime::SeriesStatus::FINISHED		 },
-	{"RELEASING",		  Anime::SeriesStatus::RELEASING	   },
-	{"NOT_YET_RELEASED", Anime::SeriesStatus::NOT_YET_RELEASED},
-	{"CANCELLED",		  Anime::SeriesStatus::CANCELLED	   },
-	{"HIATUS",		   Anime::SeriesStatus::HIATUS			 }
-};
+	anime.SetUserStatus(map[status]);
+}
 
-std::map<std::string, Anime::SeriesSeason> AniListStringToAnimeSeasonMap = {
-	{"WINTER", Anime::SeriesSeason::WINTER},
-	{"SPRING", Anime::SeriesSeason::SPRING},
-	{"SUMMER", Anime::SeriesSeason::SUMMER},
-	{"FALL",	 Anime::SeriesSeason::FALL	 }
-};
+std::string ListStatusToString(const Anime::Anime& anime) {
+	std::unordered_map<Anime::ListStatus, std::string> map = {
+	    {Anime::ListStatus::CURRENT,   "CURRENT"  },
+	    {Anime::ListStatus::PLANNING,  "PLANNING" },
+	    {Anime::ListStatus::COMPLETED, "COMPLETED"},
+	    {Anime::ListStatus::DROPPED,   "DROPPED"  },
+	    {Anime::ListStatus::PAUSED,    "PAUSED"   }
+    };
 
-std::map<std::string, enum Anime::SeriesFormat> AniListStringToAnimeFormatMap = {
-	{"TV",	   Anime::SeriesFormat::TV		 },
-	  {"TV_SHORT", Anime::SeriesFormat::TV_SHORT},
-	  {"MOVIE",	Anime::SeriesFormat::MOVIE	 },
-	{"SPECIAL",	Anime::SeriesFormat::SPECIAL },
-	  {"OVA",	  Anime::SeriesFormat::OVA	 },
-	{"ONA",		Anime::SeriesFormat::ONA	   },
-	  {"MUSIC",	Anime::SeriesFormat::MUSIC	 },
-	  {"MANGA",	Anime::SeriesFormat::MANGA	 },
-	{"NOVEL",	  Anime::SeriesFormat::NOVEL   },
-	  {"ONE_SHOT", Anime::SeriesFormat::ONE_SHOT}
-};
+	if (anime.GetUserIsRewatching())
+		return "REWATCHING";
+
+	if (!map.contains(anime.GetUserStatus()))
+		return "CURRENT";
+	return map[anime.GetUserStatus()];
+}
 
 Date ParseDate(const nlohmann::json& json) {
 	Date date;
@@ -154,14 +153,14 @@
 	ParseTitle(json.at("/title"_json_pointer), anime);
 
 	anime.SetEpisodes(JSON::GetInt(json, "/episodes"_json_pointer));
-	anime.SetFormat(AniListStringToAnimeFormatMap[JSON::GetString(json, "/format"_json_pointer)]);
+	anime.SetFormat(Translate::AniList::ToSeriesFormat(JSON::GetString(json, "/format"_json_pointer)));
 
-	anime.SetAiringStatus(AniListStringToAnimeAiringMap[JSON::GetString(json, "/status"_json_pointer)]);
+	anime.SetAiringStatus(Translate::AniList::ToSeriesStatus(JSON::GetString(json, "/status"_json_pointer)));
 
 	anime.SetAirDate(ParseDate(json["/startDate"_json_pointer]));
 
 	anime.SetAudienceScore(JSON::GetInt(json, "/averageScore"_json_pointer));
-	anime.SetSeason(AniListStringToAnimeSeasonMap[JSON::GetString(json, "/season"_json_pointer)]);
+	anime.SetSeason(Translate::AniList::ToSeriesSeason(JSON::GetString(json, "/season"_json_pointer)));
 	anime.SetDuration(JSON::GetInt(json, "/duration"_json_pointer));
 	anime.SetSynopsis(Strings::TextifySynopsis(JSON::GetString(json, "/description"_json_pointer)));
 
@@ -181,7 +180,7 @@
 
 	anime.SetUserScore(JSON::GetInt(json, "/score"_json_pointer));
 	anime.SetUserProgress(JSON::GetInt(json, "/progress"_json_pointer));
-	anime.SetUserStatus(AniListStringToAnimeWatchingMap[JSON::GetString(json, "/status"_json_pointer)]);
+	ParseListStatus(JSON::GetString(json, "/status"_json_pointer), anime);
 	anime.SetUserNotes(JSON::GetString(json, "/notes"_json_pointer));
 
 	anime.SetUserDateStarted(ParseDate(json["/startedAt"_json_pointer]));
@@ -202,51 +201,51 @@
 int GetAnimeList() {
 	/* NOTE: these should be in the qrc file */
 	const std::string query = "query ($id: Int) {\n"
-							  "  MediaListCollection (userId: $id, type: ANIME) {\n"
-							  "    lists {\n"
-							  "      name\n"
-							  "      entries {\n"
-							  "        score\n"
-							  "        notes\n"
-							  "        status\n"
-							  "        progress\n"
-							  "        startedAt {\n"
-							  "          year\n"
-							  "          month\n"
-							  "          day\n"
-							  "        }\n"
-							  "        completedAt {\n"
-							  "          year\n"
-							  "          month\n"
-							  "          day\n"
-							  "        }\n"
-							  "        updatedAt\n"
-							  "        media {\n"
-							  "          id\n"
-							  "          title {\n"
-							  "            romaji\n"
-							  "            english\n"
-							  "            native\n"
-							  "          }\n"
-							  "          format\n"
-							  "          status\n"
-							  "          averageScore\n"
-							  "          season\n"
-							  "          startDate {\n"
-							  "            year\n"
-							  "            month\n"
-							  "            day\n"
-							  "          }\n"
-							  "          genres\n"
-							  "          episodes\n"
-							  "          duration\n"
-							  "          synonyms\n"
-							  "          description(asHtml: false)\n"
-							  "        }\n"
-							  "      }\n"
-							  "    }\n"
-							  "  }\n"
-							  "}\n";
+	                          "  MediaListCollection (userId: $id, type: ANIME) {\n"
+	                          "    lists {\n"
+	                          "      name\n"
+	                          "      entries {\n"
+	                          "        score\n"
+	                          "        notes\n"
+	                          "        status\n"
+	                          "        progress\n"
+	                          "        startedAt {\n"
+	                          "          year\n"
+	                          "          month\n"
+	                          "          day\n"
+	                          "        }\n"
+	                          "        completedAt {\n"
+	                          "          year\n"
+	                          "          month\n"
+	                          "          day\n"
+	                          "        }\n"
+	                          "        updatedAt\n"
+	                          "        media {\n"
+	                          "          id\n"
+	                          "          title {\n"
+	                          "            romaji\n"
+	                          "            english\n"
+	                          "            native\n"
+	                          "          }\n"
+	                          "          format\n"
+	                          "          status\n"
+	                          "          averageScore\n"
+	                          "          season\n"
+	                          "          startDate {\n"
+	                          "            year\n"
+	                          "            month\n"
+	                          "            day\n"
+	                          "          }\n"
+	                          "          genres\n"
+	                          "          episodes\n"
+	                          "          duration\n"
+	                          "          synonyms\n"
+	                          "          description(asHtml: false)\n"
+	                          "        }\n"
+	                          "      }\n"
+	                          "    }\n"
+	                          "  }\n"
+	                          "}\n";
 	// clang-format off
 	nlohmann::json json = {
 		{"query", query},
@@ -269,7 +268,7 @@
 int UpdateAnimeEntry(const Anime::Anime& anime) {
 	/**
 	 * possible values:
-	 * 
+	 *
 	 * int mediaId,
 	 * MediaListStatus status,
 	 * float score,
@@ -285,21 +284,22 @@
 	 * float[] advancedScores,
 	 * Date startedAt,
 	 * Date completedAt
-	**/
-	const std::string query =
-		"mutation ($media_id: Int, $progress: Int, $status: MediaListStatus, $score: Int, $notes: String) {\n"
-		"  SaveMediaListEntry (mediaId: $media_id, progress: $progress, status: $status, scoreRaw: $score, notes: "
-		"$notes) {\n"
-		"    id\n"
-		"  }\n"
-		"}\n";
+	 **/
+	const std::string query = "mutation ($media_id: Int, $progress: Int, $status: MediaListStatus, "
+	                          "$score: Int, $notes: String) {\n"
+	                          "  SaveMediaListEntry (mediaId: $media_id, progress: $progress, "
+	                          "status: $status, scoreRaw: $score, notes: "
+	                          "$notes) {\n"
+	                          "    id\n"
+	                          "  }\n"
+	                          "}\n";
 	// clang-format off
 	nlohmann::json json = {
 		{"query", query},
 		{"variables", {
 			{"media_id", anime.GetId()},
 			{"progress", anime.GetUserProgress()},
-			{"status",   AniListAnimeWatchingToStringMap[anime.GetUserStatus()]},
+			{"status",   ListStatusToString(anime)},
 			{"score",    anime.GetUserScore()},
 			{"notes",    anime.GetUserNotes()}
 		}}
@@ -317,29 +317,29 @@
 
 int AuthorizeUser() {
 	/* Prompt for PIN */
-	QDesktopServices::openUrl(
-		QUrl("https://anilist.co/api/v2/oauth/authorize?client_id=" CLIENT_ID "&response_type=token"));
+	QDesktopServices::openUrl(QUrl("https://anilist.co/api/v2/oauth/authorize?client_id=" CLIENT_ID
+	                               "&response_type=token"));
 	bool ok;
 	QString token = QInputDialog::getText(
-		0, "Credentials needed!", "Please enter the code given to you after logging in to AniList:", QLineEdit::Normal,
-		"", &ok);
+	    0, "Credentials needed!",
+	    "Please enter the code given to you after logging in to AniList:", QLineEdit::Normal, "",
+	    &ok);
 	if (ok && !token.isEmpty())
 		account.SetAuthToken(token.toStdString());
-	else { // fail
+	else // fail
 		return 0;
-	}
 	const std::string query = "query {\n"
-							  "  Viewer {\n"
-							  "    id\n"
-							  "    name\n"
-							  "    mediaListOptions {\n"
-							  "      scoreFormat\n"
-							  "    }\n"
-							  "  }\n"
-							  "}\n";
+	                          "  Viewer {\n"
+	                          "    id\n"
+	                          "    name\n"
+	                          "    mediaListOptions {\n"
+	                          "      scoreFormat\n"
+	                          "    }\n"
+	                          "  }\n"
+	                          "}\n";
 	nlohmann::json json = {
-		{"query", query}
-	};
+	    {"query", query}
+    };
 	auto ret = nlohmann::json::parse(SendRequest(json.dump()));
 	ParseUser(json["Viewer"]);
 	return 1;