view src/core/config.cc @ 327:b5d6c27c308f

anime: refactor Anime::SeriesSeason to Season class ToLocalString has also been altered to take in both season and year because lots of locales actually treat formatting seasons differently! most notably is Russian which adds a suffix at the end to notate seasons(??)
author Paper <paper@paper.us.eu.org>
date Thu, 13 Jun 2024 01:49:18 -0400
parents 1b5c04268d6a
children a7d4e5107531
line wrap: on
line source

#include "core/config.h"
#include "core/anime.h"
#include "core/filesystem.h"
#include "core/json.h"
#include "core/strings.h"
#include "gui/translate/anime.h"
#include "gui/translate/config.h"

#include "animone/player.h"

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <limits.h>

#include <toml11/toml.hpp>

#include <QFile>
#include <QTextStream>

#include <iostream>

/* NOTE: This config file is prone to breakage, as Minori is alpha software and
 * as such nothing is constant. */

int Config::Load() {
	std::filesystem::path cfg_path = Filesystem::GetConfigPath();

	std::ifstream ifs(cfg_path, std::ios_base::binary);
	if (!ifs.good())
		return 0;

	toml::value data;

	try {
		data = toml::parse(ifs);
	} catch (const std::exception& ex) {
		std::cerr << "config: failed to parse toml with error " << ex.what() << std::endl;
		return 0;
	}

	service = Translate::ToService(toml::find_or(data, "General", "Service", "None"));
	locale.RefreshAvailableLocales();
	locale.SetActiveLocale(QLocale(Strings::ToQString(toml::find_or(data, "General", "Locale", "en_US"))));


	anime_list.score_format = Translate::ToScoreFormat(toml::find_or(data, "Anime List", "Score format", "100-point"));
	anime_list.language = Translate::ToLanguage(toml::find_or(data, "Anime List", "Title language", "Romaji"));
	anime_list.display_aired_episodes = toml::find_or(data, "Anime List", "Display only aired episodes", true);
	anime_list.display_available_episodes = toml::find_or(data, "Anime List", "Display only available episodes in library", true);
	anime_list.highlight_anime_if_available = toml::find_or(data, "Anime List", "Highlight anime if available", true);
	anime_list.highlighted_anime_above_others =
		(anime_list.highlight_anime_if_available)
		? toml::find_or(data, "Anime List", "Display highlighted anime above others", false)
		: false;

	auth.anilist.auth_token = toml::find_or(data, "Authentication/AniList", "Auth Token", "");
	auth.anilist.user_id = toml::find_or(data, "Authentication/AniList", "User ID", 0);

	auth.kitsu.access_token = toml::find_or(data, "Authentication/Kitsu", "Access Token", "");
	auth.kitsu.access_token_expiration = toml::find_or(data, "Authentication/Kitsu", "Access Token Expiration", static_cast<Time::Timestamp>(0));
	auth.kitsu.refresh_token = toml::find_or(data, "Authentication/Kitsu", "Refresh Token", "");
	auth.kitsu.user_id = toml::find_or(data, "Authentication/Kitsu", "User ID", "");

	torrents.feed_link = toml::find_or(data, "Torrents", "RSS feed", "https://www.tokyotosho.info/rss.php?filter=1,11&zwnj=0");

	recognition.detect_media_players = toml::find_or(data, "Recognition", "Detect media players", true);

	{
		QFile f(":/players.anisthesia");
		if (!f.exists())
			return false;

		f.open(QFile::ReadOnly | QFile::Text);
		QTextStream ts(&f);

		std::vector<animone::Player> players;

		if (!animone::ParsePlayersData(Strings::ToUtf8String(ts.readAll()), players))
			return false;

		recognition.players.reserve(players.size());
		for (const auto& player : players)
			recognition.players.push_back({true, player});
	}

	for (auto& [enabled, player] : recognition.players) {
		switch (player.type) {
			default:
			case animone::PlayerType::Default:
				enabled = toml::find_or(data, "Recognition/Players", player.name, true);
				break;
			case animone::PlayerType::WebBrowser:
				enabled = toml::find_or(data, "Recognition/Browsers", player.name, true);
				break;
		}
	}


	theme.SetTheme(Translate::ToTheme(toml::find_or(data, "Appearance", "Theme", "Default")));

	if (data.contains("Library") && data["Library"].contains("Folders")) {
		const toml::value& folders = toml::find(data, "Library", "Folders");
		std::vector<std::string> v = toml::get_or<std::vector<std::string>>(folders, {});
		for (const auto& s : v)
			if (!library.paths.count(s))
				library.paths.insert(s);
	}

	library.real_time_monitor = toml::find_or(data, "Library", "Real-time monitor", true);

	return 0;
}

int Config::Save() {
	std::filesystem::path cfg_path = Filesystem::GetConfigPath();
	Filesystem::CreateDirectories(cfg_path);

	std::ofstream file(cfg_path);
	if (!file.good())
		return 0;

	toml::value data;

	data["Library"]["Folders"] = library.paths;
	data["Library"]["Real-time monitor"] = library.real_time_monitor;

	for (const auto& [enabled, player] : recognition.players) {
		const std::string section = (player.type == animone::PlayerType::WebBrowser) ? "Recognition/Players" : "Recognition/Browsers";
		data[section][player.name] = enabled;
	}

	data["Recognition"]["Detect media players"] = recognition.detect_media_players;

	data["Torrents"]["RSS feed"] = torrents.feed_link;

	data["Authentication/Kitsu"]["Access Token"] = auth.kitsu.access_token;
	data["Authentication/Kitsu"]["Access Token Expiration"] = auth.kitsu.access_token_expiration;
	data["Authentication/Kitsu"]["Refresh Token"] = auth.kitsu.refresh_token;
	data["Authentication/Kitsu"]["User ID"] = auth.kitsu.user_id;

	data["Authentication/AniList"]["Auth Token"] = auth.anilist.auth_token;
	data["Authentication/AniList"]["User ID"] = auth.anilist.user_id;

	data["Anime List"]["Score format"] = Translate::ToString(anime_list.score_format);
	data["Anime List"]["Title language"] = Translate::ToString(anime_list.language);
	data["Anime List"]["Display only aired episodes"] = anime_list.display_aired_episodes;
	data["Anime List"]["Display only available episodes in library"] = anime_list.display_available_episodes;
	data["Anime List"]["Highlight anime if available"] = anime_list.highlight_anime_if_available;
	data["Anime List"]["Display highlighted anime above others"] = anime_list.highlighted_anime_above_others;

	data["Appearance"]["Theme"] = Translate::ToString(theme.GetTheme());

	data["General"]["Service"] = Translate::ToString(service);
	data["General"]["Locale"] = Strings::ToUtf8String(locale.GetLocale().name());

	file << std::setw(0) << data;

	return 0;
}