Hentai-Downloader/source/config/downloaderconfig.d
2020-04-13 19:19:14 +02:00

220 lines
6.0 KiB
D

module config.downloaderconfig;
/++
+ This struct represents the config of this
+ programm and is used by the other classes
+ to configure stuff
+/
struct Config
{
/++
+ This variable holds the folder/path into which
+ mangas are downloaded by default
+/
string standard_download_folder;
/++
+ This variable determins if mangas should be downloaded
+ again even if they already are downloaded
+/
bool redownload_mangas_regardless;
/++
+ This variable determins if the downloader should output debug infos
+/
bool enable_debug_output;
}
/++
+ This class handles reading and creating the config files
+/
class DownloaderConfig
{
static private:
import std.stdio : writeln;
import std.json : JSONValue, parseJSON;
import std.file : exists, mkdir, readText, copy;
import std.stdio : toFile;
import std.string: strip;
import std.array : replace;
/++
+ This specifies the default path to the config
+/
string default_config_path = "/.config/hentai_downloader/config.json";
/++
+ This specifies the default path to the template file config file
+/
immutable string default_config_template_path = "./default_config_template.json";
/++
+ This holds the text of the `default_config_template.json` file in case it
+ doesn't exist in the default path anymore
+/
immutable string default_config_template_text =
`
{
"standard_download_folder" : "~/Downloads/Lewds/",
"redownload_mangas_regardless" : false,
"enable_debug_output" : false
}
`;
/++
+ This function checks the config in `config_path` exists
+/
bool configExists(string config_path)
{
return exists(config_path);
}
/++
+ This function creates a new default config at `config_path`
+/
void createNewConfig(string config_path)
{
writeln("[*] Creating new config file in ", config_path);
// The folder that holds the config file
immutable string config_dir = "/home/" ~ getUsername() ~ "/.config/hentai_downloader";
/* writeln("Config folder:", config_dir); */
// if the folder ~/.config/hentai_downloader doesnt exist
if(!exists(config_dir))
mkdir(config_dir); // Create it
/* writeln("Config file: ", config_path); */
// Write to template file into the config folder
if(!exists(config_path))
{
/* writeln("Saving default config to file: ", config_path); */
default_config_template_text.toFile(config_path);
}
}
/++
+ Turns a relative path e.g. "~/.config" into an absolute path "/home/user/.config"
+/
string makeRelativePathAbsolute(string path)
{
return path.replace("~", "/home/"~getUsername());
}
/++
+ This function checks if the folder specified in the config file exists
+ and if not creates it
+/
void checkStandardFolder(Config config)
{
// Replace the relative path
string absolutePath = makeRelativePathAbsolute(config.standard_download_folder);
if(!exists(absolutePath))
{
// If the `standard_download_folder` doesnt exist, create it!
absolutePath.mkdir();
}
}
/++
+ Gets the username of the current user
+/
string getUsername()
{
import std.process : executeShell;
import core.stdc.stdlib : exit, EXIT_FAILURE;
// Execute whoami to get the current username
auto whoami = executeShell(`whoami`);
if(whoami.status != 0)
{
// If whoami fails exit the program
// FIXME: raise an exception or something
writeln("[!] Failed to get the current username");
exit(EXIT_FAILURE);
}
// Return the stripped username
return whoami.output.strip();
}
/++
+ Get the users .config path
+/
string getUserConfigPath()
{
// Return the combined path to the .config folder of the user
return "/home/" ~ getUsername() ~ default_config_path;
}
/++
+ This function trys to parse the config file
+ given in `config_path`, and return a Config struct
+/
Config parseConfig(string config_path)
{
import std.conv : to;
// Read the config file
string config_text = to!string(readText(config_path));
// Parse the config as JSON
auto config_json = parseJSON(config_text);
// Create a new config
Config _config;
// Assign the values that were parsed from the config file
_config.standard_download_folder = config_json["standard_download_folder"].str();
_config.redownload_mangas_regardless = config_json["redownload_mangas_regardless"].boolean();
_config.enable_debug_output = config_json["enable_debug_output"].boolean();
// Adjust the foler path
_config.standard_download_folder = makeRelativePathAbsolute(_config.standard_download_folder);
return _config;
}
/++
+ Loads and checks the given config
+/
Config loadMyConfig(string config_path)
{
// Get the cofig path for this user
config_path = getUserConfigPath();
// Check if the given config exists
if(!configExists(config_path))
createNewConfig(config_path); // If it doesn't, create it!
// Parse the config
Config _config = parseConfig(config_path);
// Check the download folder
checkStandardFolder(_config);
return _config;
}
public:
/++
+ This loads and parses the default config at `default_config_path`
+ into a `Config` struct
+/
static Config loadConfig()
{
return loadMyConfig(this.default_config_path);
}
/++
+ This loads and parses a custom config from `custom_config_path`
+ into a `Config` struct
+/
static Config loadConfig(string custom_config_path)
{
return loadMyConfig(custom_config_path);
}
}