Files
biliup/crates/biliup-cli/src/server/infrastructure/models/hook_step.rs
T
ForgQi 267bda7360 Add and improve Rust doc comments across server modules
Added and expanded Rust documentation comments (///) for structs, enums, traits, functions, and methods throughout the core and infrastructure modules. These comments clarify the purpose, parameters, and return values of types and functions, improving code readability and maintainability for developers. No functional or logic changes were made.
2025-09-23 05:14:28 +08:00

162 lines
4.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use std::borrow::Cow;
use serde::{Deserialize, Serialize};
use std::path::Path;
use tokio::fs;
use tokio::io::AsyncWriteExt;
use tokio::process::Command;
use tracing::info;
/// 钩子步骤枚举:支持多种操作格式
/// 既支持 key-value 形式(如 {run: "..."}),也支持纯字符串(如 "rm")
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum HookStep {
/// 执行命令格式:{run: "command"}
Run { run: String },
/// 移动文件格式:{mv: "target_dir"}
Move { mv: String },
/// 删除文件格式:"rm"
Remove(String),
}
impl HookStep {
/// 执行钩子步骤操作
///
/// # 参数
/// * `video_paths` - 视频文件路径列表
///
/// # 返回
/// 执行成功返回Ok(()),失败返回错误信息
pub async fn execute(&self, video_paths: &[&Path]) -> Result<(), Box<dyn std::error::Error>> {
match self {
HookStep::Run { run } => {
// 执行自定义命令
self.execute_command(run, video_paths).await?;
}
HookStep::Move { mv } => {
// 移动文件到指定目录
self.move_file(video_paths, mv).await?;
}
HookStep::Remove(cmd) if cmd == "rm" => {
// 删除文件
self.remove_file(video_paths).await?;
}
HookStep::Remove(cmd) => {
// 未知命令,返回错误
return Err(format!("Unknown command: {}", cmd).into());
}
}
Ok(())
}
/// 执行自定义命令,将视频路径作为标准输入传入
///
/// # 参数
/// * `cmd` - 要执行的命令字符串
/// * `video_paths` - 视频文件路径列表
async fn execute_command(
&self,
cmd: &str,
video_paths: &[&Path],
) -> Result<(), Box<dyn std::error::Error>> {
println!("Executing: {}", cmd);
// 解析命令和参数
let parts: Vec<&str> = cmd.split_whitespace().collect();
if parts.is_empty() {
return Err("Empty command".into());
}
// 启动子进程,配置标准输入管道
let mut process = Command::new(parts[0])
.args(&parts[1..])
.stdin(std::process::Stdio::piped())
.spawn()?;
// 将视频文件路径写入标准输入
if let Some(mut stdin) = process.stdin.take() {
let paths_str = video_paths
.iter()
.map(|p| p.to_string_lossy())
.reduce(|acc, e| Cow::from(acc.to_string() + "\n" + &*e))
.expect("At least one video path should exist");
stdin.write_all(paths_str.as_bytes()).await?;
}
// 等待进程完成并检查退出状态
let status = process.wait().await?;
if !status.success() {
return Err(format!("Command failed with status: {}", status).into());
}
Ok(())
}
/// 移动文件到指定目录
///
/// # 参数
/// * `video_paths` - 视频文件路径列表
/// * `target_dir` - 目标目录路径
async fn move_file(
&self,
video_paths: &[&Path],
target_dir: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let target_path = Path::new(target_dir);
// 创建目标目录(如果不存在)
if !target_path.exists() {
fs::create_dir_all(target_path).await?;
}
// 移动每个视频文件到目标目录
for video_path in video_paths {
let file_name = video_path.file_name().ok_or("Invalid file name")?;
let destination = target_path.join(file_name);
println!(
"Moving {} to {}",
video_path.display(),
destination.display()
);
fs::rename(video_path, destination).await?;
}
Ok(())
}
/// 删除指定的视频文件
///
/// # 参数
/// * `video_paths` - 要删除的视频文件路径列表
async fn remove_file(&self, video_paths: &[&Path]) -> Result<(), Box<dyn std::error::Error>> {
// 逐个删除视频文件
for video_path in video_paths {
println!("Removing: {}", video_path.display());
fs::remove_file(video_path).await?;
}
Ok(())
}
}
/// 处理所有后处理器步骤
/// 处理视频文件的主函数
/// 按顺序执行所有处理器步骤
///
/// # 参数
/// * `video_path` - 视频文件路径列表
/// * `processors` - 处理器步骤列表
pub async fn process_video(
video_path: &[&Path],
processors: &[HookStep],
) -> Result<(), Box<dyn std::error::Error>> {
info!("Starting video processing...");
// 依次执行每个处理器步骤
for processor in processors {
processor.execute(video_path).await?;
}
info!("Video processing completed");
Ok(())
}