mirror of
https://framagit.org/veretcle/tootube.git
synced 2025-07-20 20:41:17 +02:00
✨: add peertube source video file
This commit is contained in:
207
src/peertube.rs
207
src/peertube.rs
@@ -1,5 +1,10 @@
|
||||
use serde::Deserialize;
|
||||
use std::{boxed::Box, cmp::Ordering, error::Error};
|
||||
use crate::{config::PeertubeConfig, error::TootubeError};
|
||||
use log::debug;
|
||||
use reqwest::Client;
|
||||
use rpassword::prompt_password;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{boxed::Box, cmp::Ordering, error::Error, io::stdin};
|
||||
use tokio::fs::{read_to_string, write};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct PeerTubeVideos {
|
||||
@@ -22,6 +27,44 @@ pub struct PeerTubeVideoStreamingPlaylists {
|
||||
pub files: Vec<PeerTubeVideoStreamingPlaylistsFiles>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PeerTubeOauthClientsLocalResponse {
|
||||
client_id: String,
|
||||
client_secret: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct PeerTubeUsersToken {
|
||||
client_id: String,
|
||||
client_secret: String,
|
||||
grant_type: String,
|
||||
password: Option<String>,
|
||||
username: Option<String>,
|
||||
refresh_token: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PeerTubeUsersTokenResponse {
|
||||
refresh_token: String,
|
||||
access_token: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PeerTubeVideoSourceResponse {
|
||||
#[serde(rename = "fileDownloadUrl")]
|
||||
pub file_download_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PeerTubeVideoTokenResponse {
|
||||
files: PeerTubeVideoTokenResponseFiles,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PeerTubeVideoTokenResponseFiles {
|
||||
token: String,
|
||||
}
|
||||
|
||||
#[derive(Eq, Debug, Deserialize)]
|
||||
pub struct PeerTubeVideoStreamingPlaylistsFiles {
|
||||
pub id: u64,
|
||||
@@ -74,3 +117,163 @@ async fn get_video_detail(u: &str, v: &str) -> Result<PeerTubeVideo, Box<dyn Err
|
||||
|
||||
Ok(body)
|
||||
}
|
||||
|
||||
/// This function makes the registration process a little bit easier
|
||||
#[tokio::main]
|
||||
pub async fn register(config: &PeertubeConfig) -> Result<(), Box<dyn Error>> {
|
||||
// Get client ID/secret
|
||||
let oauth2_client = reqwest::get(format!("{}/api/v1/oauth-clients/local", config.base_url))
|
||||
.await?
|
||||
.json::<PeerTubeOauthClientsLocalResponse>()
|
||||
.await?;
|
||||
|
||||
println!(
|
||||
"Please type your PeerTube username for instance {}:",
|
||||
config.base_url
|
||||
);
|
||||
let mut username = String::new();
|
||||
stdin()
|
||||
.read_line(&mut username)
|
||||
.expect("Unable to read back the username!");
|
||||
|
||||
let password = prompt_password("Your password: ").expect("Unable to read back the password!");
|
||||
|
||||
let params = PeerTubeUsersToken {
|
||||
client_id: oauth2_client.client_id.clone(),
|
||||
client_secret: oauth2_client.client_secret.clone(),
|
||||
grant_type: "password".to_string(),
|
||||
username: Some(username.trim().to_string()),
|
||||
password: Some(password.clone()),
|
||||
refresh_token: None,
|
||||
};
|
||||
|
||||
let client = Client::new();
|
||||
let oauth2_token = client
|
||||
.post(format!("{}/api/v1/users/token", config.base_url))
|
||||
.form(¶ms)
|
||||
.send()
|
||||
.await?
|
||||
.json::<PeerTubeUsersTokenResponse>()
|
||||
.await?;
|
||||
|
||||
println!("You can now paste the following lines inside the `peertube` section of your tootube.toml file:");
|
||||
|
||||
println!();
|
||||
|
||||
println!("[peertube.oauth2]");
|
||||
println!("client_id=\"{}\"", oauth2_client.client_id);
|
||||
println!("client_secret=\"{}\"", oauth2_client.client_secret);
|
||||
println!("refresh_token=<path to refresh_token>");
|
||||
|
||||
println!();
|
||||
|
||||
println!("Finally, add the refresh token inside the refresh_token path:");
|
||||
println!("{}", oauth2_token.refresh_token);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_refresh_token(config: &PeertubeConfig) -> Result<String, Box<dyn Error>> {
|
||||
// unwrap is safe here, this function is only called when oauth2 is present
|
||||
let oauth2_config = config.oauth2.as_ref().unwrap().clone();
|
||||
// retrieve the refresh_token from the file
|
||||
let refresh_token = read_to_string(&oauth2_config.refresh_token).await?;
|
||||
|
||||
debug!(
|
||||
"Opened file {} to retrieve Token",
|
||||
&oauth2_config.refresh_token
|
||||
);
|
||||
|
||||
let params = PeerTubeUsersToken {
|
||||
client_id: oauth2_config.client_id.clone(),
|
||||
client_secret: oauth2_config.client_secret.clone(),
|
||||
grant_type: "refresh_token".to_string(),
|
||||
refresh_token: Some(refresh_token),
|
||||
username: None,
|
||||
password: None,
|
||||
};
|
||||
|
||||
let client = Client::new();
|
||||
let oauth2_token = client
|
||||
.post(format!("{}/api/v1/users/token", config.base_url))
|
||||
.form(¶ms)
|
||||
.send()
|
||||
.await?
|
||||
.json::<PeerTubeUsersTokenResponse>()
|
||||
.await?;
|
||||
|
||||
debug!("Retrieved access_token: {}", &oauth2_token.access_token);
|
||||
|
||||
// write the new refresh token to the file
|
||||
write(&oauth2_config.refresh_token, oauth2_token.refresh_token).await?;
|
||||
|
||||
debug!(
|
||||
"Written refresh_token to file {}",
|
||||
&oauth2_config.refresh_token
|
||||
);
|
||||
|
||||
Ok(oauth2_token.access_token)
|
||||
}
|
||||
|
||||
pub async fn get_original_video_source(
|
||||
uuid: &str,
|
||||
config: &PeertubeConfig,
|
||||
) -> Result<String, Box<dyn Error>> {
|
||||
let access_token = get_refresh_token(config).await?;
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let source_vid = client
|
||||
.get(format!("{}/api/v1/videos/{}/source", config.base_url, uuid))
|
||||
.header("Authorization", format!("Bearer {}", &access_token))
|
||||
.send()
|
||||
.await?
|
||||
.json::<PeerTubeVideoSourceResponse>()
|
||||
.await?;
|
||||
|
||||
debug!("Got the Source Vid URL: {}", &source_vid.file_download_url);
|
||||
|
||||
let video_file_token = client
|
||||
.post(format!("{}/api/v1/videos/{}/token", config.base_url, uuid))
|
||||
.header("Authorization", format!("Bearer {}", &access_token))
|
||||
.send()
|
||||
.await?
|
||||
.json::<PeerTubeVideoTokenResponse>()
|
||||
.await?;
|
||||
|
||||
debug!("Got the File Token: {}", &video_file_token.files.token);
|
||||
|
||||
Ok(format!(
|
||||
"{}?videoFileToken={}",
|
||||
source_vid.file_download_url, video_file_token.files.token
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn delete_original_video_source(
|
||||
uuid: &str,
|
||||
config: &PeertubeConfig,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let access_token = get_refresh_token(config).await?;
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let res = client
|
||||
.delete(format!(
|
||||
"{}/api/v1/videos/{}/source/file",
|
||||
config.base_url, uuid
|
||||
))
|
||||
.header("Authorization", format!("Bearer {}", &access_token))
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if !res.status().is_success() {
|
||||
return Err(TootubeError::new(&format!(
|
||||
"Cannot delete source video file {}: {}",
|
||||
uuid,
|
||||
res.text().await?
|
||||
))
|
||||
.into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Reference in New Issue
Block a user