Helpers: Added 'format_filename' Function

This function actually handles non-alphanumeric characters such as ','
and ';'. This means that files with possibly invalid names are no longer
created.
This commit is contained in:
Moss 2022-10-01 00:35:53 -04:00
parent 1749401745
commit 3c77375858
7 changed files with 51 additions and 26 deletions

View File

@ -51,7 +51,7 @@ By default, dropout-dl will download the episode in the format `<series>/S<seaso
## TODO ## TODO
- [x] Create tests - [x] Create tests
- [ ] Handle non-alphanumeric characters - [x] Handle non-alphanumeric characters
- [ ] Test build process on other setups with other OSs. - [ ] Test build process on other setups with other OSs.

View File

@ -94,6 +94,27 @@ namespace dropout_dl {
return replace_html_character_codes(remove_leading_and_following_whitespace(str)); return replace_html_character_codes(remove_leading_and_following_whitespace(str));
} }
std::string format_filename(const std::string& str) {
std::string out;
for (int i = 0; i < str.size(); i++) {
char c = str[i];
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '/' || c == '-' || c == '_') {
out += c;
}2
else if (c == ',' && str[i + 1] == ' ') {
out+= '-';
i++;
}
else if (c == ',' || c == '\'' || c == ' ') {
out += '-';
}
}
return out;
}
#if defined(__WIN32__) #if defined(__WIN32__)
#include <windows.h> #include <windows.h>
msec_t time_ms(void) msec_t time_ms(void)
@ -463,10 +484,7 @@ namespace dropout_dl {
filename = "E" + (this->episode_number.size() < 2 ? "0" + this->episode_number : this->episode_number) + this->name + filename = "E" + (this->episode_number.size() < 2 ? "0" + this->episode_number : this->episode_number) + this->name +
".mp4"; ".mp4";
std::replace(filename.begin(), filename.end(), ' ', '_'); filename = format_filename(filename);
std::replace(filename.begin(), filename.end(), ',', '_');
} }
if (quality == "all") { if (quality == "all") {
@ -504,8 +522,6 @@ namespace dropout_dl {
void cookie::get_value_from_db(sqlite3 *db, const std::string &sql_query_base, const std::string& value, bool verbose, int (*callback)(void*,int,char**,char**)) { void cookie::get_value_from_db(sqlite3 *db, const std::string &sql_query_base, const std::string& value, bool verbose, int (*callback)(void*,int,char**,char**)) {
std::string sql_mod_base = sql_query_base; std::string sql_mod_base = sql_query_base;
verbose = true;
if (sql_mod_base.find("WHERE") == std::string::npos) { if (sql_mod_base.find("WHERE") == std::string::npos) {
sql_mod_base += " WHERE "; sql_mod_base += " WHERE ";
} }

View File

@ -189,6 +189,15 @@ namespace dropout_dl {
*/ */
std::string format_name_string(const std::string& str); std::string format_name_string(const std::string& str);
/**
*
* @param str - A string
* @return <b>str</b> properly formatted to be a filename
*
* Removes non-alphanumeric characters and spaces
*/
std::string format_filename(const std::string& str);
#if defined(__WIN32__) #if defined(__WIN32__)
#include <windows.h> #include <windows.h>
msec_t time_ms(void); msec_t time_ms(void);
@ -245,6 +254,8 @@ namespace dropout_dl {
public: public:
/// The name of the series that the episode belongs to /// The name of the series that the episode belongs to
std::string series; std::string series;
/// The directory for the series
std::string series_directory;
/// The name of the episode /// The name of the episode
std::string name; std::string name;
/// The number of the episode in the season. This can be a number or a string /// The number of the episode in the season. This can be a number or a string
@ -405,9 +416,11 @@ namespace dropout_dl {
std::cout << "Got series: " << this->series << '\n'; std::cout << "Got series: " << this->series << '\n';
} }
std::replace(this->series.begin(), this->series.end(), ' ', '_'); this->series_directory = format_filename(this->series);
std::replace(this->series.begin(), this->series.end(), ',', '_'); if (verbose) {
std::cout << "Got series directory: " << this->series_directory << '\n';
}
this->embedded_url = get_embed_url(episode_data); this->embedded_url = get_embed_url(episode_data);

View File

@ -335,11 +335,9 @@ int main(int argc, char** argv) {
else if (options.season) { else if (options.season) {
dropout_dl::season season = dropout_dl::series::get_season(options.url, options.cookies); dropout_dl::season season = dropout_dl::series::get_season(options.url, options.cookies);
std::string series_directory = season.series_name; std::string series_directory = dropout_dl::format_filename(season.series_name);
std::replace(series_directory.begin(), series_directory.end(), ' ', '_'); std::cout << "ser: " << season.series_name << "\ndir: " << series_directory << '\n';
std::replace(series_directory.begin(), series_directory.end(), ',', '_');
season.download(options.quality, options.output_directory + "/" + series_directory); season.download(options.quality, options.output_directory + "/" + series_directory);
} }
@ -350,14 +348,18 @@ int main(int argc, char** argv) {
std::cout << "filename: " << options.filename << '\n'; std::cout << "filename: " << options.filename << '\n';
} }
if (!std::filesystem::is_directory(ep.series)) { if (!std::filesystem::is_directory(options.output_directory)) {
std::filesystem::create_directories(ep.series); std::filesystem::create_directories(options.output_directory);
if (options.verbose) { if (options.verbose) {
std::cout << "Creating series directory" << '\n'; std::cout << "Creating series directory" << '\n';
} }
} }
ep.download(options.quality, options.output_directory + "/" + ep.series, options.filename); if (options.filename.empty()) {
options.filename = dropout_dl::format_filename(ep.name + ".mp4");
}
ep.download(options.quality, options.output_directory, options.filename);
} }

View File

@ -45,7 +45,7 @@ namespace dropout_dl {
if (e.episode_url.empty()) { if (e.episode_url.empty()) {
continue; continue;
} }
std::cout << e.episode_number << ": " << e.name << ": " << e.episode_url << '\n'; std::cout << '\t' << e.episode_number << ": " << e.name << '\n';
out.push_back(e); out.push_back(e);
} }
} }
@ -59,11 +59,7 @@ namespace dropout_dl {
std::cout << "Creating series directory" << '\n'; std::cout << "Creating series directory" << '\n';
} }
std::string dir = series_directory + "/" + this->name; std::string dir = format_filename(series_directory + "/" + this->name);
std::replace(dir.begin(), dir.end(), ' ', '_');
std::replace(dir.begin(), dir.end(), ',', '_');
for (auto& ep : episodes) { for (auto& ep : episodes) {
ep.download(quality, dir); ep.download(quality, dir);

View File

@ -55,7 +55,7 @@ namespace dropout_dl {
this->url = url; this->url = url;
this->name = name; this->name = name;
this->series_name = series_name; this->series_name = series_name;
std::cout << series_name << ": " << name << ": " << url << "\n"; std::cout << series_name << ": " << name << ": " << "\n";
this->page_data = get_generic_page(url); this->page_data = get_generic_page(url);
this->episodes = get_episodes(page_data, cookies); this->episodes = get_episodes(page_data, cookies);
} }

View File

@ -81,9 +81,7 @@ namespace dropout_dl {
exit(10); exit(10);
} }
this->series_directory = name; this->series_directory = format_filename(name);
std::replace(this->series_directory.begin(), this->series_directory.end(), ' ', '_');
std::replace(this->series_directory.begin(), this->series_directory.end(), ',', '_');
this->seasons = get_seasons(page_data, cookies); this->seasons = get_seasons(page_data, cookies);
} }