comparison src/core/anime_db.cc @ 174:f88eda79c60a

anime/db: add some more json functionality, still doesn't compile :/
author Paper <mrpapersonic@gmail.com>
date Wed, 29 Nov 2023 13:53:56 -0500
parents de0a8d2f28b3
children 9b10175be389
comparison
equal deleted inserted replaced
173:de0a8d2f28b3 174:f88eda79c60a
1 #include "core/anime_db.h" 1 #include "core/anime_db.h"
2 #include "core/anime.h" 2 #include "core/anime.h"
3 #include "core/strings.h" 3 #include "core/strings.h"
4 #include "core/json.h" 4 #include "core/json.h"
5 5 #include "core/filesystem.h"
6 #include <QDebug> 6
7 #include "gui/translate/anime.h"
8 #include "gui/translate/anilist.h"
9
10 #include <fstream>
7 11
8 namespace Anime { 12 namespace Anime {
9 13
10 int Database::GetTotalAnimeAmount() { 14 int Database::GetTotalAnimeAmount() {
11 int total = 0; 15 int total = 0;
156 160
157 json = { 161 json = {
158 {"status", Translate::ToString(anime.GetUserStatus())}, 162 {"status", Translate::ToString(anime.GetUserStatus())},
159 {"progress", anime.GetUserProgress()}, 163 {"progress", anime.GetUserProgress()},
160 {"score", anime.GetUserScore()}, 164 {"score", anime.GetUserScore()},
161 //{"started", anime.GetUserDateStarted()}, 165 {"started", anime.GetUserDateStarted().GetAsAniListJson()},
162 //{"completed", anime.GetUserDateCompleted()}, 166 {"completed", anime.GetUserDateCompleted().GetAsAniListJson()},
163 {"private", anime.GetUserIsPrivate()}, 167 {"private", anime.GetUserIsPrivate()},
164 {"rewatched_times", anime.GetUserRewatchedTimes()}, 168 {"rewatched_times", anime.GetUserRewatchedTimes()},
165 {"rewatching", anime.GetUserIsRewatching()}, 169 {"rewatching", anime.GetUserIsRewatching()},
166 {"updated", anime.GetUserTimeUpdated()}, 170 {"updated", anime.GetUserTimeUpdated()},
167 {"notes", anime.GetUserNotes()} 171 {"notes", anime.GetUserNotes()}
168 }; 172 };
173
174 return true;
169 } 175 }
170 176
171 static bool GetAnimeAsJSON(const Anime& anime, nlohmann::json& json) { 177 static bool GetAnimeAsJSON(const Anime& anime, nlohmann::json& json) {
172 json = { 178 json = {
173 {"id", anime.GetId()}, 179 {"id", anime.GetId()},
176 {"romaji", anime.GetRomajiTitle()}, 182 {"romaji", anime.GetRomajiTitle()},
177 {"english", anime.GetEnglishTitle()} 183 {"english", anime.GetEnglishTitle()}
178 }}, 184 }},
179 {"synonyms", anime.GetTitleSynonyms()}, 185 {"synonyms", anime.GetTitleSynonyms()},
180 {"episodes", anime.GetEpisodes()}, 186 {"episodes", anime.GetEpisodes()},
181 {"airing_status", anime.GetAiringStatus()}, 187 {"airing_status", Translate::ToString(anime.GetAiringStatus())},
182 {"air_date", anime.GetAirDate()}, 188 {"air_date", anime.GetAirDate().GetAsAniListJson()},
183 {"genres", anime.GetGenres()}, 189 {"genres", anime.GetGenres()},
184 {"producers", anime.GetProducers()}, 190 {"producers", anime.GetProducers()},
185 {"format", anime.GetFormat()}, 191 {"format", Translate::ToString(anime.GetFormat())},
186 {"season", anime.GetSeason()}, 192 {"season", Translate::ToString(anime.GetSeason())},
187 {"audience_score", anime.GetAudienceScore()}, 193 {"audience_score", anime.GetAudienceScore()},
188 {"synopsis", anime.GetSynopsis()}, 194 {"synopsis", anime.GetSynopsis()},
189 {"duration", anime.GetDuration()}, 195 {"duration", anime.GetDuration()},
190 {"poster_url", anime.GetPosterUrl()}, 196 {"poster_url", anime.GetPosterUrl()}
191 {"service_url", anime.GetServiceUrl()}
192 }; 197 };
193 198
194 nlohmann::json user; 199 nlohmann::json user;
195 if (GetListDataAsJSON(anime, user)) 200 if (GetListDataAsJSON(anime, user))
196 json.push_back({"list_data", user}); 201 json.push_back({"list_data", user});
198 return true; 203 return true;
199 } 204 }
200 205
201 bool Database::GetDatabaseAsJSON(nlohmann::json& json) { 206 bool Database::GetDatabaseAsJSON(nlohmann::json& json) {
202 for (const auto& [id, anime] : items) { 207 for (const auto& [id, anime] : items) {
203 nlohmann::json anime_json; 208 nlohmann::json anime_json = {};
204 GetAnimeAsJSON(anime, anime_json); 209 GetAnimeAsJSON(anime, anime_json);
205 json.push_back(anime_json); 210 json.push_back(anime_json);
206 } 211 }
212
213 return true;
214 }
215
216 bool Database::SaveDatabaseToDisk() {
217 std::filesystem::path db_path = Filesystem::GetAnimeDBPath();
218 Filesystem::CreateDirectories(db_path);
219
220 std::ofstream db_file(db_path);
221 if (!db_file)
222 return false;
223
224 nlohmann::json json = {};
225 if (!GetDatabaseAsJSON(json))
226 return false;
227
228 db_file << std::setw(4) << json << std::endl;
229 return true;
230 }
231
232 static bool ParseAnimeUserInfoJSON(const nlohmann::json& json, Anime& anime) {
233 if (!anime.IsInUserList())
234 anime.AddToUserList();
235
236 anime.SetUserStatus(Translate::ToListStatus(JSON::GetString<std::string>(json, "/status"_json_pointer, "")));
237 anime.SetUserStatus(JSON::GetNumber(json, "/progress"_json_pointer, 0));
238 anime.SetUserScore(JSON::GetNumber(json, "/score"_json_pointer, 0));
239 anime.SetUserDateStarted(Date(JSON::GetValue(json, "/started"_json_pointer)));
240 anime.SetUserDateStarted(Date(JSON::GetValue(json, "/completed"_json_pointer)));
241 anime.SetUserIsPrivate(JSON::GetBoolean(json, "/private"_json_pointer, false));
242 anime.SetUserRewatchedTimes(JSON::GetNumber(json, "/rewatched_times"_json_pointer, ""));
243 anime.SetUserIsRewatching(JSON::GetBoolean(json, "/rewatching"_json_pointer, false));
244 anime.SetUserTimeUpdated(JSON::GetNumber(json, "/updated"_json_pointer, 0));
245 anime.SetUserNotes(JSON::GetString<std::string>(json, "/notes"_json_pointer, ""));
246
247 return true;
248 }
249
250 bool Database::ParseAnimeInfoJSON(const nlohmann::json& json) {
251 int id = JSON::GetNumber(json, "/id"_json_pointer, 0);
252 if (!id)
253 return false;
254
255 Anime& anime = items[id];
256
257 anime.SetId(id);
258 anime.SetNativeTitle(JSON::GetString<std::string>(json, "/title/native"_json_pointer, ""));
259 anime.SetRomajiTitle(JSON::GetString<std::string>(json, "/title/romaji"_json_pointer, ""));
260 anime.SetEnglishTitle(JSON::GetString<std::string>(json, "/title/english"_json_pointer, ""));
261 anime.SetTitleSynonyms(JSON::GetArray<std::vector<std::string>>(json, "/synonyms"_json_pointer, {}));
262 anime.SetEpisodes(JSON::GetNumber(json, "/episodes"_json_pointer, 0));
263 anime.SetAiringStatus(Translate::AniList::ToSeriesStatus(JSON::GetString<std::string>(json, "/airing_status"_json_pointer, "")));
264 anime.SetAirDate(Date(JSON::GetValue(json, "/air_date"_json_pointer)));
265 anime.SetGenres(JSON::GetArray<std::vector<std::string>>(json, "/genres"_json_pointer, {}));
266 anime.SetProducers(JSON::GetArray<std::vector<std::string>>(json, "/producers"_json_pointer, {}));
267 anime.SetFormat(Translate::AniList::ToSeriesFormat(JSON::GetString<std::string>(json, "/format"_json_pointer, "")));
268 anime.SetSeason(Translate::AniList::ToSeriesSeason(JSON::GetString<std::string>(json, "/season"_json_pointer, "")));
269 anime.SetAudienceScore(JSON::GetNumber(json, "/audience_score"_json_pointer, 0));
270 anime.SetSynopsis(JSON::GetString<std::string>(json, "/synopsis"_json_pointer, ""));
271 anime.SetDuration(JSON::GetNumber(json, "/duration"_json_pointer, 0));
272 anime.SetPosterUrl(JSON::GetString<std::string>(json, "/poster_url"_json_pointer, ""));
273
274 if (json.contains("/list_data") && json.at("/list_data").is_dictionary())
275 ParseAnimeUserInfoJSON(json, anime);
276
277 return true;
278 }
279
280 bool Database::ParseDatabaseJSON(const nlohmann::json& json) {
281 for (const auto& anime_json : json)
282 ParseAnimeInfoJSON(anime_json);
283
284 return true;
285 }
286
287 bool Database::LoadDatabaseFromFile() {
288 std::filesystem::path db_path = Filesystem::GetAnimeDBPath();
289 Filesystem::CreateDirectories(db_path);
290
291 std::ifstream db_file(db_path);
292 if (!db_file)
293 return false;
294
295 /* When parsing, do NOT throw exceptions */
296 nlohmann::json json = json.parse(db_file, nullptr, false);
297 if (json.is_discarded())
298 return false; /* Give up */
299
300 if (!ParseDatabaseJSON(json)) /* How */
301 return false;
302
207 return true; 303 return true;
208 } 304 }
209 305
210 Database db; 306 Database db;
211 307