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;
}
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) {
for (int i = 0; i < qualities.size(); i++) {
if (qualities[i] == quality) {
@ -300,11 +316,19 @@ namespace dropout_dl {
std::cout << YELLOW << "File already exists: " << filepath << RESET << '\n';
return;
}
std::fstream out(filepath,
std::fstream out(filepath + ".mp4",
std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
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 << '\n';
@ -315,14 +339,14 @@ namespace dropout_dl {
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";
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 {
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 {
filename = this->series + " - " + this->season + " - " + this->name + ".mp4";
filename = this->series + " - " + this->season + " - " + this->name;
}
filename = format_filename(filename);
}
@ -335,6 +359,5 @@ namespace dropout_dl {
} else {
this->download_quality(quality, series_directory, filename);
}
}
} // dropout_dl

View File

@ -47,6 +47,8 @@ namespace dropout_dl {
std::string embedded_page_data;
/// The url for the main config page. This contains page the link to the mp4 video of the episode
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
std::string config_data;
/// 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();
/**
*
* @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
@ -191,7 +202,7 @@ namespace dropout_dl {
* Create an episode object from the link using to cookies to get all the necessary information.
* 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->verbose = verbose;
@ -254,6 +265,16 @@ namespace dropout_dl {
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();
}
@ -266,11 +287,10 @@ namespace dropout_dl {
* Create an episode object from the link using to cookies to get all the necessary information.
* 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->verbose = verbose;
episode_data = get_episode_page(episode_url, cookies[0].value, cookies[1].value);
if (verbose) {
@ -337,6 +357,13 @@ namespace dropout_dl {
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();
}

View File

@ -23,6 +23,7 @@ namespace dropout_dl {
bool is_series = false;
bool is_season = false;
bool is_episode = false;
bool download_captions = false;
std::string quality;
std::string filename;
std::string output_directory;
@ -107,6 +108,9 @@ namespace dropout_dl {
else if (arg == "episode") {
is_episode = true;
}
else if (arg == "captions") {
download_captions = true;
}
else if (arg == "help") {
std::cout << "Usage: dropout-dl [OPTIONS] <url> [OPTIONS]\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--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--captions Download the captions along with the episode\n"
<< std::endl;
exit(0);
@ -385,7 +390,7 @@ int main(int argc, char** argv) {
if (options.verbose) {
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);
}
@ -393,7 +398,7 @@ int main(int argc, char** argv) {
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, options.download_captions);
season.download(options.quality, options.output_directory + "/" + season.series_name);
}
@ -401,7 +406,7 @@ int main(int argc, char** argv) {
if (options.verbose) {
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) {
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++) {
if (html_data[i + j] == '"') {
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;
/// The list of all the episodes in the season
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);
@ -64,8 +66,9 @@ namespace dropout_dl {
*
* 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->download_captions = download_captions;
this->season_number = get_season_number(this->url);
this->name = 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 search_class("js-switch-season");
@ -184,7 +184,7 @@ namespace dropout_dl {
season_name = season_name.substr(name_start,
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();

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
*/
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);
/**
*