Comments support
This commit is contained in:
parent
628f179e09
commit
12dae0dd5e
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -192,9 +192,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.18"
|
version = "1.2.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c"
|
checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
@ -1414,9 +1414,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx"
|
name = "sqlx"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f"
|
checksum = "14e22987355fbf8cfb813a0cf8cd97b1b4ec834b94dbd759a9e8679d41fabe83"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"sqlx-macros",
|
"sqlx-macros",
|
||||||
@ -1427,10 +1427,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-core"
|
name = "sqlx-core"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0"
|
checksum = "55c4720d7d4cd3d5b00f61d03751c685ad09c33ae8290c8a2c11335e0604300b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"crc",
|
"crc",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
@ -1460,9 +1461,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-macros"
|
name = "sqlx-macros"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310"
|
checksum = "175147fcb75f353ac7675509bc58abb2cb291caf0fd24a3623b8f7e3eb0a754b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1473,9 +1474,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-macros-core"
|
name = "sqlx-macros-core"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad"
|
checksum = "1cde983058e53bfa75998e1982086c5efe3c370f3250bf0357e344fa3352e32b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"either",
|
"either",
|
||||||
@ -1499,9 +1500,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-mysql"
|
name = "sqlx-mysql"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233"
|
checksum = "847d2e5393a4f39e47e4f36cab419709bc2b83cbe4223c60e86e1471655be333"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64",
|
"base64",
|
||||||
@ -1541,9 +1542,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-postgres"
|
name = "sqlx-postgres"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613"
|
checksum = "cc35947a541b9e0a2e3d85da444f1c4137c13040267141b208395a0d0ca4659f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64",
|
"base64",
|
||||||
@ -1578,9 +1579,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlx-sqlite"
|
name = "sqlx-sqlite"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540"
|
checksum = "6c48291dac4e5ed32da0927a0b981788be65674aeb62666d19873ab4289febde"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"flume",
|
"flume",
|
||||||
@ -1595,6 +1596,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
host = "127.0.0.1"
|
host = "127.0.0.1"
|
||||||
port = 3000
|
port = 3000
|
||||||
videos_per_page = 10
|
videos_per_page = 10
|
||||||
|
comments_per_page = 10
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
pub struct Channel;
|
pub struct Channel;
|
||||||
|
@ -1,25 +1,77 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
use serde::{Deserialize, Serialize};
|
||||||
pub enum CommentFlags {
|
use serde_json::Value;
|
||||||
Uploader,
|
use thiserror::Error;
|
||||||
Verified,
|
use tokio::fs;
|
||||||
Hearted,
|
use tracing::{error, warn};
|
||||||
Pinned,
|
|
||||||
#[default]
|
#[derive(Debug, Error)]
|
||||||
None,
|
pub enum CommentsError {
|
||||||
|
#[error("Target video {0} not found in database")]
|
||||||
|
InvalidTarget(String),
|
||||||
|
#[error("IO Error: {0}")]
|
||||||
|
IOError(#[from] std::io::Error),
|
||||||
|
#[error("Could not serialize info JSON: {0}")]
|
||||||
|
SerializeInfoJSON(#[from] serde_json::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Comment {
|
pub struct Comment {
|
||||||
|
pub id: String,
|
||||||
pub video_id: String,
|
pub video_id: String,
|
||||||
pub parent: String,
|
pub parent: String,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
pub like_count: i64,
|
pub like_count: i64,
|
||||||
pub author_id: String,
|
pub author_id: String,
|
||||||
pub author: String,
|
pub author: String,
|
||||||
pub author_thumbnail: Option<String>,
|
pub author_thumbnail: String,
|
||||||
pub author_url: Option<String>,
|
pub author_url: String,
|
||||||
pub timestamp: i64,
|
pub timestamp: i64,
|
||||||
pub flags: CommentFlags,
|
pub author_is_uploader: bool,
|
||||||
|
pub author_is_verified: bool,
|
||||||
|
pub is_hearted: bool,
|
||||||
|
pub is_pinned: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_comments_from_video(id: &str) -> Result<Vec<Comment>, CommentsError> {
|
||||||
|
let info_json = format!("videos/{id}/{id}.info.json");
|
||||||
|
let info_json = Path::new(&info_json);
|
||||||
|
|
||||||
|
if !info_json.exists() {
|
||||||
|
return Err(CommentsError::InvalidTarget(id.into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let info: Value = serde_json::from_str(&fs::read_to_string(info_json).await?)?;
|
||||||
|
|
||||||
|
let Some(comments) = info.get("comments") else {
|
||||||
|
warn!("Video {id} has no comments!");
|
||||||
|
return Ok(vec![]);
|
||||||
|
};
|
||||||
|
|
||||||
|
comments.as_array().map_or_else(
|
||||||
|
|| Ok(vec![]),
|
||||||
|
|comments| {
|
||||||
|
Ok(comments
|
||||||
|
.iter()
|
||||||
|
.map(|c| Comment {
|
||||||
|
id: c["id"].to_string(),
|
||||||
|
video_id: id.into(),
|
||||||
|
parent: c["parent"].to_string(),
|
||||||
|
text: c["text"].to_string(),
|
||||||
|
like_count: c["like_count"].as_i64().unwrap_or_default(),
|
||||||
|
author_id: c["author_id"].to_string(),
|
||||||
|
author: c["author"].to_string(),
|
||||||
|
author_thumbnail: c["author_thumbnail"].to_string(),
|
||||||
|
author_url: c["author_url"].to_string(),
|
||||||
|
timestamp: c["timestamp"].as_i64().unwrap_or_default(),
|
||||||
|
author_is_uploader: c["author_is_uploader"].as_bool().unwrap_or_default(),
|
||||||
|
author_is_verified: c["author_is_verified"].as_bool().unwrap_or_default(),
|
||||||
|
is_hearted: c["is_favorited"].as_bool().unwrap_or_default(),
|
||||||
|
is_pinned: c["is_pinned"].as_bool().unwrap_or_default(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ pub struct Config {
|
|||||||
pub host: String,
|
pub host: String,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub videos_per_page: usize,
|
pub videos_per_page: usize,
|
||||||
|
pub comments_per_page: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -18,6 +19,7 @@ impl Default for Config {
|
|||||||
host: "0.0.0.0".into(),
|
host: "0.0.0.0".into(),
|
||||||
port: 3000,
|
port: 3000,
|
||||||
videos_per_page: 10,
|
videos_per_page: 10,
|
||||||
|
comments_per_page: 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,14 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use instance::Instance;
|
use instance::Instance;
|
||||||
use middleware::auth;
|
use middleware::auth;
|
||||||
use routes::{get_video, list_videos, upload_video};
|
use routes::{
|
||||||
|
comment::video_comments,
|
||||||
|
video::{get_video, list_videos, upload_video},
|
||||||
|
};
|
||||||
use tokio::signal;
|
use tokio::signal;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
|
mod comment;
|
||||||
mod instance;
|
mod instance;
|
||||||
mod middleware;
|
mod middleware;
|
||||||
mod routes;
|
mod routes;
|
||||||
@ -31,7 +35,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.route("/upload", post(upload_video))
|
.route("/upload", post(upload_video))
|
||||||
.route_layer(axum::middleware::from_fn_with_state(instance.clone(), auth))
|
.route_layer(axum::middleware::from_fn_with_state(instance.clone(), auth))
|
||||||
.route("/", get(list_videos))
|
.route("/", get(list_videos))
|
||||||
.route("/{id}", get(get_video))
|
.route("/video/{id}", get(get_video))
|
||||||
|
.route("/comments/{id}", get(video_comments))
|
||||||
.with_state(instance);
|
.with_state(instance);
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind(address).await?;
|
let listener = tokio::net::TcpListener::bind(address).await?;
|
||||||
|
68
src/routes/comment.rs
Executable file
68
src/routes/comment.rs
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, Query, State},
|
||||||
|
http::StatusCode,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
comment::{Comment, CommentsError, get_comments_from_video},
|
||||||
|
instance::Instance,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct VideoCommentsQuery {
|
||||||
|
page: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct VideoCommentsResponse {
|
||||||
|
comments: Vec<Comment>,
|
||||||
|
page: usize,
|
||||||
|
per_page: usize,
|
||||||
|
total: usize,
|
||||||
|
pages: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetches the comments from a video, will return an empty vec if the video has no comments
|
||||||
|
pub async fn video_comments(
|
||||||
|
State(state): State<Instance>,
|
||||||
|
Path(id): Path<String>,
|
||||||
|
Query(query): Query<VideoCommentsQuery>,
|
||||||
|
) -> Result<Json<VideoCommentsResponse>, StatusCode> {
|
||||||
|
let comments = get_comments_from_video(&id).await.map_err(|e| match e {
|
||||||
|
CommentsError::InvalidTarget(t) => {
|
||||||
|
error!("Video {t} does not exist in database!");
|
||||||
|
StatusCode::NOT_FOUND
|
||||||
|
}
|
||||||
|
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
});
|
||||||
|
|
||||||
|
match comments {
|
||||||
|
Ok(comments) => {
|
||||||
|
let per_page = state.config.comments_per_page;
|
||||||
|
let total = comments.len();
|
||||||
|
let pages = total.div_ceil(per_page);
|
||||||
|
let page = query.page.unwrap_or(1).max(1).min(pages);
|
||||||
|
|
||||||
|
let start = per_page * (page - 1);
|
||||||
|
let end = (start + per_page).min(total);
|
||||||
|
|
||||||
|
let comments = if start < total {
|
||||||
|
comments[start..end].to_vec()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Json(VideoCommentsResponse {
|
||||||
|
comments,
|
||||||
|
page,
|
||||||
|
per_page,
|
||||||
|
total,
|
||||||
|
pages,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
Err(status) => Err(status),
|
||||||
|
}
|
||||||
|
}
|
2
src/routes/mod.rs
Executable file
2
src/routes/mod.rs
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod comment;
|
||||||
|
pub mod video;
|
@ -40,7 +40,7 @@ pub async fn list_videos(
|
|||||||
|
|
||||||
let per_page = state.config.videos_per_page;
|
let per_page = state.config.videos_per_page;
|
||||||
let total = videos.len();
|
let total = videos.len();
|
||||||
let pages = (total + per_page - 1).div_ceil(per_page);
|
let pages = total.div_ceil(per_page);
|
||||||
let page = query.page.unwrap_or(1).max(1).min(pages);
|
let page = query.page.unwrap_or(1).max(1).min(pages);
|
||||||
|
|
||||||
let start = per_page * (page - 1);
|
let start = per_page * (page - 1);
|
||||||
@ -64,9 +64,9 @@ pub async fn list_videos(
|
|||||||
/// Get a single video from the database by its ID
|
/// Get a single video from the database by its ID
|
||||||
pub async fn get_video(
|
pub async fn get_video(
|
||||||
State(state): State<Instance>,
|
State(state): State<Instance>,
|
||||||
Path(id): Path<i64>,
|
Path(id): Path<String>,
|
||||||
) -> Result<Json<Video>, StatusCode> {
|
) -> Result<Json<Video>, StatusCode> {
|
||||||
sqlx::query_as!(Video, "SELECT * FROM video WHERE id = ?", id)
|
sqlx::query_as!(Video, "SELECT * FROM video WHERE youtube_id = ?", id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_or(Err(StatusCode::INTERNAL_SERVER_ERROR), |video| {
|
.map_or(Err(StatusCode::INTERNAL_SERVER_ERROR), |video| {
|
||||||
@ -77,7 +77,6 @@ pub async fn get_video(
|
|||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct UploadVideoQuery {
|
pub struct UploadVideoQuery {
|
||||||
url: String,
|
url: String,
|
||||||
cookie: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Upload a video to the database
|
/// Upload a video to the database
|
||||||
@ -96,13 +95,11 @@ pub async fn upload_video(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_video = Video::from_url(&query.url, id, query.cookie.as_deref())
|
let new_video = Video::from_url(&query.url, id).await.map_err(|e| match e {
|
||||||
.await
|
VideoError::InvalidUrl | VideoError::UrlParse(_) => StatusCode::BAD_REQUEST,
|
||||||
.map_err(|e| match e {
|
VideoError::AlreadyExists => StatusCode::OK,
|
||||||
VideoError::InvalidUrl | VideoError::UrlParse(_) => StatusCode::BAD_REQUEST,
|
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
VideoError::AlreadyExists => StatusCode::OK,
|
});
|
||||||
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
});
|
|
||||||
|
|
||||||
match new_video {
|
match new_video {
|
||||||
Ok(video) => {
|
Ok(video) => {
|
18
src/video.rs
18
src/video.rs
@ -1,10 +1,11 @@
|
|||||||
use std::{fs, io, path::Path};
|
use std::{io, path::Path};
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use sha3::{Digest, Sha3_256};
|
use sha3::{Digest, Sha3_256};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use tokio::fs;
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
use url::{ParseError, Url};
|
use url::{ParseError, Url};
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ pub struct Video {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Video {
|
impl Video {
|
||||||
async fn yt_dlp_task(url: &str, cookie: Option<&str>) -> Result<(), VideoError> {
|
async fn yt_dlp_task(url: &str) -> Result<(), VideoError> {
|
||||||
let mut args = vec![
|
let mut args = vec![
|
||||||
"--write-info-json",
|
"--write-info-json",
|
||||||
"--write-thumbnail",
|
"--write-thumbnail",
|
||||||
@ -60,9 +61,6 @@ impl Video {
|
|||||||
"-v",
|
"-v",
|
||||||
url,
|
url,
|
||||||
];
|
];
|
||||||
if let Some(cookie) = cookie {
|
|
||||||
args.append(&mut vec!["--cookies", cookie]);
|
|
||||||
}
|
|
||||||
args.append(&mut vec![
|
args.append(&mut vec![
|
||||||
"-o",
|
"-o",
|
||||||
"videos/%(id)s/%(id)s.%(ext)s",
|
"videos/%(id)s/%(id)s.%(ext)s",
|
||||||
@ -97,7 +95,7 @@ impl Video {
|
|||||||
Some(query_v.1.to_string())
|
Some(query_v.1.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn from_url(url: &str, id: i64, cookie: Option<&str>) -> Result<Self, VideoError> {
|
pub async fn from_url(url: &str, id: i64) -> Result<Self, VideoError> {
|
||||||
let url = Url::parse(url)?;
|
let url = Url::parse(url)?;
|
||||||
info!("Parsed argument as URL");
|
info!("Parsed argument as URL");
|
||||||
|
|
||||||
@ -112,7 +110,7 @@ impl Video {
|
|||||||
let dir = format!("videos/{youtube_id}");
|
let dir = format!("videos/{youtube_id}");
|
||||||
let file_stem = format!("{dir}/{youtube_id}");
|
let file_stem = format!("{dir}/{youtube_id}");
|
||||||
if !Path::new(&dir).exists() {
|
if !Path::new(&dir).exists() {
|
||||||
fs::create_dir(dir)?;
|
fs::create_dir(dir).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let info_json = format!("{file_stem}.info.json");
|
let info_json = format!("{file_stem}.info.json");
|
||||||
@ -124,9 +122,9 @@ impl Video {
|
|||||||
return Err(VideoError::AlreadyExists);
|
return Err(VideoError::AlreadyExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::yt_dlp_task(url.as_str(), cookie).await?;
|
Self::yt_dlp_task(url.as_str()).await?;
|
||||||
|
|
||||||
let info: Value = serde_json::from_str(&fs::read_to_string(info_json)?)?;
|
let info: Value = serde_json::from_str(&fs::read_to_string(info_json).await?)?;
|
||||||
|
|
||||||
// info!("Info JSON for {youtube_id}\n{info}");
|
// info!("Info JSON for {youtube_id}\n{info}");
|
||||||
|
|
||||||
@ -163,7 +161,7 @@ impl Video {
|
|||||||
let path = Path::new(&file_name);
|
let path = Path::new(&file_name);
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
info!("File '{}' found", path.display());
|
info!("File '{}' found", path.display());
|
||||||
buffer = Some(fs::read(path)?);
|
buffer = Some(fs::read(path).await?);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
warn!("File '{}' not found", path.display());
|
warn!("File '{}' not found", path.display());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user