220 lines
6.0 KiB
D
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);
|
||
|
}
|
||
|
}
|