Naming: Updated to Use a Format With Numbers When Possible
Now using the format: <series>/<season>/<series> - S<season #>E<episode #> - <episode>.mp4
This commit is contained in:
parent
0e8ad8c44d
commit
4b9d4bf7f5
|
@ -101,16 +101,17 @@ namespace dropout_dl {
|
||||||
for (int i = 0; i < str.size(); i++) {
|
for (int i = 0; i < str.size(); i++) {
|
||||||
char c = str[i];
|
char c = str[i];
|
||||||
|
|
||||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '/' || c == '-' || c == '_') {
|
// Skip these
|
||||||
out += c;
|
if (c == '?' || c == ':') {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (c == ',' && str[i + 1] == ' ') {
|
// Replace these with dashes
|
||||||
out+= '-';
|
else if (c == '/') {
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if (c == ',' || c == '\'' || c == ' ') {
|
|
||||||
out += '-';
|
out += '-';
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
out += c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
@ -143,7 +144,8 @@ namespace dropout_dl {
|
||||||
|
|
||||||
current_time = time_ms();
|
current_time = time_ms();
|
||||||
if (current_time - 50 > last_progress_timestamp) {
|
if (current_time - 50 > last_progress_timestamp) {
|
||||||
double percent_done = (downloaded / total_to_download) * number_chars;
|
// Percent of the file downloadede. Adding one to round up so that when its done it shows as a full bar rather than missing one.
|
||||||
|
double percent_done = ((downloaded / total_to_download) * number_chars) + 1;
|
||||||
double percent_done_clone = percent_done;
|
double percent_done_clone = percent_done;
|
||||||
std::cout << *(std::string*)filename << " [";
|
std::cout << *(std::string*)filename << " [";
|
||||||
while (percent_done_clone-- > 0) {
|
while (percent_done_clone-- > 0) {
|
||||||
|
@ -210,8 +212,6 @@ namespace dropout_dl {
|
||||||
|
|
||||||
std::string series_data = meta_data.substr(i, j);
|
std::string series_data = meta_data.substr(i, j);
|
||||||
|
|
||||||
std::cout << "series_data: " << series_data << '\n';
|
|
||||||
|
|
||||||
for (j = 0; j < series_data.size(); j++) {
|
for (j = 0; j < series_data.size(); j++) {
|
||||||
if (substr_is(series_data, j, series_title_title)) {
|
if (substr_is(series_data, j, series_title_title)) {
|
||||||
// Skip "name", the following colon, and the opening quotation mark.
|
// Skip "name", the following colon, and the opening quotation mark.
|
||||||
|
@ -502,8 +502,20 @@ namespace dropout_dl {
|
||||||
|
|
||||||
void episode::download(const std::string& quality, const std::string& series_directory, std::string filename) {
|
void episode::download(const std::string& quality, const std::string& series_directory, std::string filename) {
|
||||||
if (filename.empty()) {
|
if (filename.empty()) {
|
||||||
|
if (this->episode_number != 0) {
|
||||||
|
if (this->season_number != 0) {
|
||||||
|
filename = this->series + " - S" + ((this->season_number < 10) ? "0" : "") + std::to_string(this->season_number) + "E" + ((this->episode_number < 10) ? "0" : "") + std::to_string(this->episode_number) + " - " + this->name + ".mp4";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filename = this->series + " - " + this->season + " Episode " + std::to_string(this->episode_number) + " - " + this->name + ".mp4";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
filename = this->series + " - " + this->season + " - " + this->name + ".mp4";
|
filename = this->series + " - " + this->season + " - " + this->name + ".mp4";
|
||||||
}
|
}
|
||||||
|
filename = format_filename(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (quality == "all") {
|
if (quality == "all") {
|
||||||
for (const auto &possible_quality: this->qualities) {
|
for (const auto &possible_quality: this->qualities) {
|
||||||
|
@ -531,6 +543,8 @@ namespace dropout_dl {
|
||||||
|
|
||||||
out << this->get_video_data(quality, series_directory + "/" + filename) << std::endl;
|
out << this->get_video_data(quality, series_directory + "/" + filename) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -258,10 +258,14 @@ namespace dropout_dl {
|
||||||
std::string series_directory;
|
std::string series_directory;
|
||||||
/// The name of the season that the episode belongs to
|
/// The name of the season that the episode belongs to
|
||||||
std::string season;
|
std::string season;
|
||||||
|
/// The number of the season (only set when downloading a season or series)
|
||||||
|
int season_number;
|
||||||
/// The json metadata of the episode
|
/// The json metadata of the episode
|
||||||
std::string metadata;
|
std::string metadata;
|
||||||
/// The name of the episode
|
/// The name of the episode
|
||||||
std::string name;
|
std::string name;
|
||||||
|
/// The number of the episode (only set when downloading a season or series)
|
||||||
|
int episode_number;
|
||||||
/// The url for the main episode page
|
/// The url for the main episode page
|
||||||
std::string episode_url;
|
std::string episode_url;
|
||||||
/// The data of the main episode page
|
/// The data of the main episode page
|
||||||
|
|
58
src/main.cpp
58
src/main.cpp
|
@ -1,6 +1,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "series.h"
|
#include "series.h"
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#ifdef DROPOUT_DL_SQLITE
|
#ifdef DROPOUT_DL_SQLITE
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
@ -17,8 +18,9 @@ namespace dropout_dl {
|
||||||
std::string url;
|
std::string url;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool cookies_forced = false;
|
bool cookies_forced = false;
|
||||||
bool series = false;
|
bool is_series = false;
|
||||||
bool season = false;
|
bool is_season = false;
|
||||||
|
bool is_episode = false;
|
||||||
std::string quality;
|
std::string quality;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::string output_directory;
|
std::string output_directory;
|
||||||
|
@ -92,10 +94,13 @@ namespace dropout_dl {
|
||||||
output_directory = args[++i];
|
output_directory = args[++i];
|
||||||
}
|
}
|
||||||
else if (arg == "series") {
|
else if (arg == "series") {
|
||||||
series = true;
|
is_series = true;
|
||||||
}
|
}
|
||||||
else if (arg == "season") {
|
else if (arg == "season") {
|
||||||
season = true;
|
is_season = true;
|
||||||
|
}
|
||||||
|
else if (arg == "episode") {
|
||||||
|
is_episode = true;
|
||||||
}
|
}
|
||||||
else if (arg == "help") {
|
else if (arg == "help") {
|
||||||
std::cout << "Usage: dropout-dl [OPTIONS] <url> [OPTIONS]\n"
|
std::cout << "Usage: dropout-dl [OPTIONS] <url> [OPTIONS]\n"
|
||||||
|
@ -120,12 +125,29 @@ namespace dropout_dl {
|
||||||
output_directory = ".";
|
output_directory = ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (season && series) {
|
if ((is_season && is_series) || (is_season && is_episode) || (is_series && is_episode)) {
|
||||||
std::cerr << "ARGUMENT PARSE ERROR: Season and Series arguments used\n";
|
std::cerr << "ARGUMENT PARSE ERROR: Mulitple parse type arguments used\n";
|
||||||
}
|
}
|
||||||
if (quality.empty()) {
|
if (quality.empty()) {
|
||||||
quality = "1080p";
|
quality = "1080p";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(is_season || is_series || is_episode)) {
|
||||||
|
std::regex season_regex("season:\\d+\\/?$", std::regex::ECMAScript);
|
||||||
|
std::regex episode_regex("season:\\d+\\/.+$", std::regex::ECMAScript);
|
||||||
|
if (std::regex_search(url, season_regex)) {
|
||||||
|
is_season = true;
|
||||||
|
}
|
||||||
|
else if (std::regex_search(url, episode_regex)) {
|
||||||
|
is_episode = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is_series = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << is_season << is_series << is_episode << '\n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -341,21 +363,26 @@ int main(int argc, char** argv) {
|
||||||
options.cookies = get_cookies(options.verbose);
|
options.cookies = get_cookies(options.verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.series) {
|
if (options.is_series) {
|
||||||
|
if (options.verbose) {
|
||||||
|
std::cout << "Getting series\n";
|
||||||
|
}
|
||||||
dropout_dl::series series(options.url, options.cookies);
|
dropout_dl::series series(options.url, options.cookies);
|
||||||
|
|
||||||
series.download(options.quality, options.output_directory);
|
series.download(options.quality, options.output_directory);
|
||||||
}
|
}
|
||||||
else if (options.season) {
|
else if (options.is_season) {
|
||||||
|
if (options.verbose) {
|
||||||
|
std::cout << "Getting season\n";
|
||||||
|
}
|
||||||
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 = dropout_dl::format_filename(season.series_name);
|
season.download(options.quality, options.output_directory + "/" + season.series_name);
|
||||||
|
}
|
||||||
std::cout << "ser: " << season.series_name << "\ndir: " << series_directory << '\n';
|
else if (options.is_episode) {
|
||||||
|
if (options.verbose) {
|
||||||
season.download(options.quality, options.output_directory + "/" + series_directory);
|
std::cout << "Getting episode\n";
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
dropout_dl::episode ep(options.url, options.cookies, options.verbose);
|
dropout_dl::episode ep(options.url, options.cookies, options.verbose);
|
||||||
|
|
||||||
if (options.verbose) {
|
if (options.verbose) {
|
||||||
|
@ -371,6 +398,9 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
ep.download(options.quality, options.output_directory, options.filename);
|
ep.download(options.quality, options.output_directory, options.filename);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "ERROR: Could not determine parsing type\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -33,18 +33,20 @@ namespace dropout_dl {
|
||||||
exit(8);
|
exit(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<episode> season::get_episodes(const std::string &html_data, const std::vector<cookie>& cookies) {
|
std::vector<episode> season::get_episodes(const std::vector<cookie>& cookies) {
|
||||||
std::vector<episode> out;
|
std::vector<episode> out;
|
||||||
|
|
||||||
std::string site_video(R"(class="browse-item-link" data-track-event="site_video")");
|
std::string site_video(R"(class="browse-item-link" data-track-event="site_video")");
|
||||||
|
|
||||||
|
int number_of_episodes = 0;
|
||||||
for (int i = 0; i < html_data.size(); i++) {
|
for (int i = 0; i < this->page_data.size(); i++) {
|
||||||
if (substr_is(html_data, i, site_video)) {
|
if (substr_is(this->page_data, i, site_video)) {
|
||||||
episode e = get_episode(html_data, i, cookies);
|
episode e = get_episode(this->page_data, i, cookies);
|
||||||
if (e.episode_url.empty()) {
|
if (e.episode_url.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
e.episode_number = ++number_of_episodes;
|
||||||
|
e.season_number = this->season_number;
|
||||||
std::cout << '\t' << e.name << '\n';
|
std::cout << '\t' << e.name << '\n';
|
||||||
out.push_back(e);
|
out.push_back(e);
|
||||||
}
|
}
|
||||||
|
@ -53,13 +55,28 @@ namespace dropout_dl {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int season::get_season_number(const std::string& url) {
|
||||||
|
std::string reversed_number;
|
||||||
|
for (int i = url.length() - 1; i >= 0 && url[i] != ':'; i--) {
|
||||||
|
if (isdigit(url[i])) {
|
||||||
|
reversed_number += url[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string number;
|
||||||
|
for (int i = reversed_number.length() - 1, j = 0; i >= 0; i--, j++) {
|
||||||
|
number[j] += reversed_number[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::stoi(number);
|
||||||
|
}
|
||||||
|
|
||||||
void season::download(const std::string &quality, const std::string &series_directory) {
|
void season::download(const std::string &quality, const std::string &series_directory) {
|
||||||
if (!std::filesystem::is_directory(series_directory)) {
|
if (!std::filesystem::is_directory(series_directory)) {
|
||||||
std::filesystem::create_directories(series_directory);
|
std::filesystem::create_directories(series_directory);
|
||||||
std::cout << "Creating series directory" << '\n';
|
std::cout << "Creating series directory" << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dir = format_filename(series_directory + "/" + this->name);
|
std::string dir = series_directory + "/" + this->name;
|
||||||
|
|
||||||
for (auto& ep : episodes) {
|
for (auto& ep : episodes) {
|
||||||
ep.download(quality, dir);
|
ep.download(quality, dir);
|
||||||
|
|
16
src/season.h
16
src/season.h
|
@ -16,6 +16,8 @@ namespace dropout_dl {
|
||||||
std::string name;
|
std::string name;
|
||||||
/// The name of the series
|
/// The name of the series
|
||||||
std::string series_name;
|
std::string series_name;
|
||||||
|
/// The number of the season
|
||||||
|
int season_number;
|
||||||
/// The link to the season page
|
/// The link to the season page
|
||||||
std::string url;
|
std::string url;
|
||||||
/// The season page data
|
/// The season page data
|
||||||
|
@ -31,7 +33,16 @@ namespace dropout_dl {
|
||||||
*
|
*
|
||||||
* Gets all the episodes of the season and returns in a vector
|
* Gets all the episodes of the season and returns in a vector
|
||||||
*/
|
*/
|
||||||
static std::vector<episode> get_episodes(const std::string& html_data, const std::vector<cookie>& cookies);
|
std::vector<episode> get_episodes(const std::vector<cookie>& cookies);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param url - The url of the season
|
||||||
|
* @return The number of the season
|
||||||
|
*
|
||||||
|
* Gets the canonical number of the season for the url. This is sometimes different from the displayed number because of special seasons.
|
||||||
|
*/
|
||||||
|
static int get_season_number(const std::string& url);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -53,11 +64,12 @@ namespace dropout_dl {
|
||||||
*/
|
*/
|
||||||
season(const std::string& url, const std::string& name, const std::vector<cookie>& cookies, const std::string& series_name = "") {
|
season(const std::string& url, const std::string& name, const std::vector<cookie>& cookies, const std::string& series_name = "") {
|
||||||
this->url = url;
|
this->url = url;
|
||||||
|
this->season_number = get_season_number(this->url);
|
||||||
this->name = name;
|
this->name = name;
|
||||||
this->series_name = series_name;
|
this->series_name = series_name;
|
||||||
std::cout << series_name << ": " << name << ": " << "\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(cookies);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue