|
|
|
@ -6,7 +6,7 @@ use rand::{thread_rng, Rng};
|
|
|
|
|
use reqwest::Client; |
|
|
|
|
use std::io::Cursor; |
|
|
|
|
use std::process::Stdio; |
|
|
|
|
use tokio::io::{copy_buf, AsyncWriteExt, BufReader}; |
|
|
|
|
use tokio::io::AsyncWriteExt; |
|
|
|
|
use tokio::process::Command; |
|
|
|
|
use tokio::time::{sleep, Duration}; |
|
|
|
|
extern crate grammers_client; |
|
|
|
@ -39,7 +39,7 @@ def try_get(src, getter, expected_type=None):
|
|
|
|
|
youtube_dl.extractor.youtube.try_get = try_get |
|
|
|
|
ytdl = youtube_dl.YoutubeDL({"skip_download": True, "no_color": True, "quiet": True}) |
|
|
|
|
try: |
|
|
|
|
print(json.dumps(ytdl.extract_info("https://www.youtube.com/watch?v=" + sys.argv[1]), indent=4), file=sys.stderr) |
|
|
|
|
print(json.dumps(ytdl.extract_info("https://www.youtube.com/watch?v=" + sys.argv[1]), indent=4)) |
|
|
|
|
except Exception as e: |
|
|
|
|
sys.exit(str(e))"#; |
|
|
|
|
|
|
|
|
@ -120,6 +120,7 @@ pub async fn get_video(video_id: &str) -> Result<Option<VideoData>> {
|
|
|
|
|
let mut process = command |
|
|
|
|
.args(&["-", video_id]) |
|
|
|
|
.stdin(Stdio::piped()) |
|
|
|
|
.stdout(Stdio::piped()) |
|
|
|
|
.stderr(Stdio::piped()) |
|
|
|
|
.spawn()?; |
|
|
|
|
let mut stdin = process.stdin.take().unwrap(); |
|
|
|
@ -129,21 +130,13 @@ pub async fn get_video(video_id: &str) -> Result<Option<VideoData>> {
|
|
|
|
|
} |
|
|
|
|
drop(stdin) |
|
|
|
|
}); |
|
|
|
|
let stderr = process.stderr.take().unwrap(); |
|
|
|
|
let task: tokio::task::JoinHandle<std::result::Result<_, std::io::Error>> = |
|
|
|
|
tokio::spawn(async move { |
|
|
|
|
let mut stderr = BufReader::new(stderr); |
|
|
|
|
let mut writer = vec![]; |
|
|
|
|
copy_buf(&mut stderr, &mut writer).await?; |
|
|
|
|
Ok(writer) |
|
|
|
|
}); |
|
|
|
|
let status = process.wait().await?; |
|
|
|
|
let stderr = String::from_utf8(task.await??)?; |
|
|
|
|
if status.success() { |
|
|
|
|
let mut data: VideoData = serde_json::from_str(&stderr)?; |
|
|
|
|
data.json = stderr; |
|
|
|
|
let output = process.wait_with_output().await?; |
|
|
|
|
if output.status.success() { |
|
|
|
|
let mut data: VideoData = serde_json::from_slice(&output.stdout)?; |
|
|
|
|
data.json = String::from_utf8(output.stdout)?; |
|
|
|
|
Ok(Some(data)) |
|
|
|
|
} else { |
|
|
|
|
let stderr = String::from_utf8(output.stderr)?; |
|
|
|
|
let stderr_lowercase = stderr.to_lowercase(); |
|
|
|
|
if stderr_lowercase.contains("private video") |
|
|
|
|
|| stderr_lowercase.contains("unavailable") |
|
|
|
@ -152,8 +145,9 @@ pub async fn get_video(video_id: &str) -> Result<Option<VideoData>> {
|
|
|
|
|
Ok(None) |
|
|
|
|
} else { |
|
|
|
|
Err(Error::YoutubeDL(YoutubeDLError { |
|
|
|
|
status, |
|
|
|
|
output: stderr, |
|
|
|
|
status: output.status, |
|
|
|
|
stdout: String::from_utf8(output.stdout)?, |
|
|
|
|
stderr, |
|
|
|
|
})) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -170,7 +164,7 @@ pub async fn get_video_retry(
|
|
|
|
|
Err(err) => { |
|
|
|
|
eprintln!("Failed to get video data: {:?}", err); |
|
|
|
|
if let Error::YoutubeDL(ref err) = err { |
|
|
|
|
let output = err.output.to_lowercase(); |
|
|
|
|
let output = err.stderr.to_lowercase(); |
|
|
|
|
if output.contains("429") |
|
|
|
|
|| output.contains("too many requests") |
|
|
|
|
|| output.contains("technical difficult") |
|
|
|
|