diff --git a/Cargo.lock b/Cargo.lock index 124b5ee..2e73125 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "tootube" -version = "0.7.2" +version = "0.7.3" dependencies = [ "async-stream", "clap", diff --git a/Cargo.toml b/Cargo.toml index c82c053..ca0301e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tootube" authors = ["VC "] -version = "0.7.2" +version = "0.7.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/lib.rs b/src/lib.rs index c3cc3bf..fae0868 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,14 @@ pub async fn run(config: Config, pl: Vec) { .unwrap_or_else(|e| panic!("Cannot resume upload!: {e}")); debug!("YT video ID: {}", &yt_video_id); + youtube + .set_thumbnail( + &yt_video_id, + &format!("{}{}", &config.peertube.base_url, latest_vid.preview_path), + ) + .await + .unwrap_or_else(|e| panic!("Cannot upload the thumbnail: {}", e)); + if !pl.is_empty() { youtube .add_video_to_playlists(&yt_video_id, &pl) diff --git a/src/peertube.rs b/src/peertube.rs index e80957c..e837f19 100644 --- a/src/peertube.rs +++ b/src/peertube.rs @@ -20,6 +20,8 @@ pub struct PeerTubeVideo { pub name: String, pub uuid: String, pub description: String, + #[serde(rename = "previewPath")] + pub preview_path: String, #[serde(rename = "streamingPlaylists")] pub streaming_playlists: Option>, pub tags: Option>, diff --git a/src/youtube.rs b/src/youtube.rs index 7d4ea84..ceac7fe 100644 --- a/src/youtube.rs +++ b/src/youtube.rs @@ -236,6 +236,32 @@ impl YouTube { Ok(youtube) } + + /// This function uploads the thumbnail from PeerTube + pub async fn set_thumbnail( + &self, + video_id: &str, + preview_url: &str, + ) -> Result<(), Box> { + let res = reqwest::get(preview_url).await?; + let stream = res.bytes_stream(); + + let res = self + .client + .post(&format!( + "https://www.googleapis.com/upload/youtube/v3/thumbnails/set?videoId={}&uploadType=media", + video_id + )) + .header("Content-Type", "application/octet-stream") + .body(Body::wrap_stream(stream)) + .send() + .await?; + + res.status().is_success().then_some(()).ok_or( + TootubeError::new(&format!("Thumbnail not uploaded: {}", res.text().await?)).into(), + ) + } + /// This function takes a list of playlists keyword and returns a list of playlist ID async fn get_playlist_ids(&self, pl: &[String]) -> Result, Box> { let mut page_token = String::new(); @@ -341,17 +367,18 @@ impl YouTube { .json(&upload_params) .send().await?; - if res.status().is_success() { - Ok(res - .headers() - .get("location") - .ok_or("Cannot find suitable header")? - .to_str()? - .to_string()) - } else { - Err(TootubeError::new("Cannot create resumable upload!").into()) - } + res.status() + .is_success() + .then_some( + res.headers() + .get("location") + .ok_or("Cannot find suitable header")? + .to_str()? + .to_string(), + ) + .ok_or(TootubeError::new("Cannot create resumable upload!").into()) } + /// This takes the PT stream for download, connects it to YT stream for upload pub async fn now_kiss( &self,