Episode: Added Downloading Captions With "--captions"

This commit is contained in:
Moss 2023-02-07 21:33:49 -08:00
parent 2ade05b175
commit 3a8e904ebb
No known key found for this signature in database
GPG Key ID: F539D4A506C954F9
7 changed files with 74 additions and 16 deletions

View File

@ -249,6 +249,22 @@ namespace dropout_dl {
return qualities; return qualities;
} }
std::string episode::get_captions_url() {
std::string start = "\"lang\":\"en\",\"url\":\"";
std::string end = "\",\"kind\":\"captions\"";
if (this->config_data.find(end) == std::string::npos) {
return "";
}
std::string captions_url = dropout_dl::get_substring_in(this->config_data, start, end);
if (this->verbose) {
std::cout << "captions url: " << captions_url << "\n";
}
return captions_url;
}
std::string episode::get_video_url(const std::string& quality) { std::string episode::get_video_url(const std::string& quality) {
for (int i = 0; i < qualities.size(); i++) { for (int i = 0; i < qualities.size(); i++) {
if (qualities[i] == quality) { if (qualities[i] == quality) {
@ -300,11 +316,19 @@ namespace dropout_dl {
std::cout << YELLOW << "File already exists: " << filepath << RESET << '\n'; std::cout << YELLOW << "File already exists: " << filepath << RESET << '\n';
return; return;
} }
std::fstream out(filepath, std::fstream out(filepath + ".mp4",
std::ios_base::in | std::ios_base::out | std::ios_base::trunc); std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
out << this->get_video_data(quality, filepath) << std::endl; out << this->get_video_data(quality, filepath) << std::endl;
if (!this->captions_url.empty()) {
std::fstream captions_file(filepath + ".vtt",
std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
captions_file << get_generic_page(this->captions_url);
}
std::cout << GREEN << filepath << RESET; std::cout << GREEN << filepath << RESET;
std::cout << '\n'; std::cout << '\n';
@ -315,14 +339,14 @@ namespace dropout_dl {
if (filename.empty()) { if (filename.empty()) {
if (this->episode_number != 0) { if (this->episode_number != 0) {
if (this->season_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"; 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;
} }
else { else {
filename = this->series + " - " + this->season + " Episode " + std::to_string(this->episode_number) + " - " + this->name + ".mp4"; filename = this->series + " - " + this->season + " Episode " + std::to_string(this->episode_number) + " - " + this->name;
} }
} }
else { else {
filename = this->series + " - " + this->season + " - " + this->name + ".mp4"; filename = this->series + " - " + this->season + " - " + this->name;
} }
filename = format_filename(filename); filename = format_filename(filename);
} }
@ -335,6 +359,5 @@ namespace dropout_dl {
} else { } else {
this->download_quality(quality, series_directory, filename); this->download_quality(quality, series_directory, filename);
} }
} }
} // dropout_dl } // dropout_dl

View File

@ -47,6 +47,8 @@ namespace dropout_dl {
std::string embedded_page_data; std::string embedded_page_data;
/// The url for the main config page. This contains page the link to the mp4 video of the episode /// The url for the main config page. This contains page the link to the mp4 video of the episode
std::string config_url; std::string config_url;
/// The url for the captions of the episode.
std::string captions_url;
/// The data of the main config page. This contains the link to the mp4 video of the episode /// The data of the main config page. This contains the link to the mp4 video of the episode
std::string config_data; std::string config_data;
/// The list of the qualities available for the episode. This is a parallel array with the quality_urls vector /// The list of the qualities available for the episode. This is a parallel array with the quality_urls vector
@ -134,6 +136,15 @@ namespace dropout_dl {
*/ */
std::vector<std::string> get_qualities(); std::vector<std::string> get_qualities();
/**
*
* @return the url for the captions of the episode
*
* Gets the url for the captions of the episode if possible. If not returns "".
*/
std::string get_captions_url();
/** /**
* *
* @param quality - The quality of the video * @param quality - The quality of the video
@ -191,7 +202,7 @@ namespace dropout_dl {
* Create an episode object from the link using to cookies to get all the necessary information. * Create an episode object from the link using to cookies to get all the necessary information.
* This constructor initializes all the object data. * This constructor initializes all the object data.
*/ */
episode(const std::string& episode_url, std::vector<cookie> cookies, const std::string& series, const std::string& season, int episode_number, int season_number, bool verbose = false) { episode(const std::string& episode_url, std::vector<cookie> cookies, const std::string& series, const std::string& season, int episode_number, int season_number, bool verbose = false, bool download_captions = false) {
this->episode_url = episode_url; this->episode_url = episode_url;
this->verbose = verbose; this->verbose = verbose;
@ -254,6 +265,16 @@ namespace dropout_dl {
this->config_data = get_generic_page(this->config_url); this->config_data = get_generic_page(this->config_url);
if (download_captions) {
this->captions_url = get_captions_url();
if (verbose) {
std::cout << "Got caption url: " << this->captions_url << "\n";
}
}
else {
this->captions_url = "";
}
this->get_qualities(); this->get_qualities();
} }
@ -266,11 +287,10 @@ namespace dropout_dl {
* Create an episode object from the link using to cookies to get all the necessary information. * Create an episode object from the link using to cookies to get all the necessary information.
* This constructor initializes all the object data. * This constructor initializes all the object data.
*/ */
episode(const std::string& episode_url, std::vector<cookie> cookies, bool verbose = false) { episode(const std::string& episode_url, std::vector<cookie> cookies, bool verbose = false, bool download_captions = false) {
this->episode_url = episode_url; this->episode_url = episode_url;
this->verbose = verbose; this->verbose = verbose;
episode_data = get_episode_page(episode_url, cookies[0].value, cookies[1].value); episode_data = get_episode_page(episode_url, cookies[0].value, cookies[1].value);
if (verbose) { if (verbose) {
@ -337,6 +357,13 @@ namespace dropout_dl {
this->config_data = get_generic_page(this->config_url); this->config_data = get_generic_page(this->config_url);
if (download_captions) {
this->captions_url = get_captions_url();
}
else {
this->captions_url = "";
}
this->get_qualities(); this->get_qualities();
} }

View File

@ -23,6 +23,7 @@ namespace dropout_dl {
bool is_series = false; bool is_series = false;
bool is_season = false; bool is_season = false;
bool is_episode = false; bool is_episode = false;
bool download_captions = false;
std::string quality; std::string quality;
std::string filename; std::string filename;
std::string output_directory; std::string output_directory;
@ -107,6 +108,9 @@ namespace dropout_dl {
else if (arg == "episode") { else if (arg == "episode") {
is_episode = true; is_episode = true;
} }
else if (arg == "captions") {
download_captions = 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"
"\n" "\n"
@ -121,6 +125,7 @@ namespace dropout_dl {
"\t--force-cookies Interpret the next to arguments as authentication cookie and session cookie\n" "\t--force-cookies Interpret the next to arguments as authentication cookie and session cookie\n"
"\t--series Interpret the url as a link to a series and download all episodes from all seasons\n" "\t--series Interpret the url as a link to a series and download all episodes from all seasons\n"
"\t--season Interpret the url as a link to a season and download all episodes from all seasons\n" "\t--season Interpret the url as a link to a season and download all episodes from all seasons\n"
"\t--captions Download the captions along with the episode\n"
<< std::endl; << std::endl;
exit(0); exit(0);
@ -385,7 +390,7 @@ int main(int argc, char** argv) {
if (options.verbose) { if (options.verbose) {
std::cout << "Getting series\n"; std::cout << "Getting series\n";
} }
dropout_dl::series series(options.url, options.cookies); dropout_dl::series series(options.url, options.cookies, options.download_captions);
series.download(options.quality, options.output_directory); series.download(options.quality, options.output_directory);
} }
@ -393,7 +398,7 @@ int main(int argc, char** argv) {
if (options.verbose) { if (options.verbose) {
std::cout << "Getting season\n"; 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, options.download_captions);
season.download(options.quality, options.output_directory + "/" + season.series_name); season.download(options.quality, options.output_directory + "/" + season.series_name);
} }
@ -401,7 +406,7 @@ int main(int argc, char** argv) {
if (options.verbose) { if (options.verbose) {
std::cout << "Getting episode\n"; std::cout << "Getting episode\n";
} }
dropout_dl::episode ep(options.url, options.cookies, options.verbose); dropout_dl::episode ep(options.url, options.cookies, options.verbose, options.download_captions);
if (options.verbose) { if (options.verbose) {
std::cout << "filename: " << options.filename << '\n'; std::cout << "filename: " << options.filename << '\n';

View File

@ -24,7 +24,7 @@ namespace dropout_dl {
for (int j = 0; j + i < html_data.size(); j++) { for (int j = 0; j + i < html_data.size(); j++) {
if (html_data[i + j] == '"') { if (html_data[i + j] == '"') {
start_point += 15; start_point += 15;
return {html_data.substr(i, j), cookies, this->series_name, this->name, episode_number, this->season_number}; return episode(html_data.substr(i, j), cookies, this->series_name, this->name, episode_number, this->season_number, false, this->download_captions);
} }
} }
} }

View File

@ -24,6 +24,8 @@ namespace dropout_dl {
std::string page_data; std::string page_data;
/// The list of all the episodes in the season /// The list of all the episodes in the season
std::vector<episode> episodes; std::vector<episode> episodes;
/// Whether or not to download captions
bool download_captions;
episode get_episode(const std::string& html_data, int& start_point, const std::vector<cookie>& cookies, int episode_number = 0); episode get_episode(const std::string& html_data, int& start_point, const std::vector<cookie>& cookies, int episode_number = 0);
@ -64,8 +66,9 @@ namespace dropout_dl {
* *
* Creates a season object and populates the needed information. * Creates a season object and populates the needed information.
*/ */
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 = "", bool download_captions = false) {
this->url = url; this->url = url;
this->download_captions = download_captions;
this->season_number = get_season_number(this->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;

View File

@ -115,7 +115,7 @@ namespace dropout_dl {
} }
season series::get_season(const std::string &url, const std::vector<cookie>& cookies) { season series::get_season(const std::string &url, const std::vector<cookie>& cookies, bool download_captions) {
std::string html_data = get_generic_page(url); std::string html_data = get_generic_page(url);
std::string search_class("js-switch-season"); std::string search_class("js-switch-season");
@ -184,7 +184,7 @@ namespace dropout_dl {
season_name = season_name.substr(name_start, season_name = season_name.substr(name_start,
season_name.size() - name_start - name_end); season_name.size() - name_start - name_end);
return {season_url, season_name, cookies, get_series_name(html_data)}; return {season_url, season_name, cookies, get_series_name(html_data), download_captions};
} }
season_url.clear(); season_url.clear();

View File

@ -56,7 +56,7 @@ namespace dropout_dl {
* *
* Gets the season page, which is really just a series page, and creates a season object with all the episodes of the season * Gets the season page, which is really just a series page, and creates a season object with all the episodes of the season
*/ */
static season get_season(const std::string& url, const std::vector<cookie>& cookies); static season get_season(const std::string& url, const std::vector<cookie>& cookies, bool download_captions);
/** /**
* *