feat(yarr): Added download option
This commit is contained in:
189
yarr-api/examples/download_after_search.rs
Normal file
189
yarr-api/examples/download_after_search.rs
Normal file
@@ -0,0 +1,189 @@
|
||||
//! Example demonstrating download after search functionality
|
||||
//!
|
||||
//! This example shows how to:
|
||||
//! 1. Search for available releases for a specific series/episode
|
||||
//! 2. Download the best quality release automatically
|
||||
//! 3. Handle different search scenarios
|
||||
|
||||
use std::env;
|
||||
use yarr_api::{ApiError, SonarrClient};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), ApiError> {
|
||||
// Initialize the client with environment variables
|
||||
let base_url = env::var("SONARR_URL").unwrap_or_else(|_| "http://localhost:8989".to_string());
|
||||
let api_key =
|
||||
env::var("SONARR_API_KEY").expect("SONARR_API_KEY environment variable is required");
|
||||
|
||||
let client = SonarrClient::new(base_url, api_key);
|
||||
|
||||
println!("🔍 Sonarr Download After Search Example");
|
||||
println!("========================================");
|
||||
|
||||
// Example 1: Search and download best release for a specific series
|
||||
println!("\n📺 Example 1: Search and download for series ID 1");
|
||||
match search_and_download_for_series(&client, 1).await {
|
||||
Ok(success) => {
|
||||
if success {
|
||||
println!("✅ Successfully found and downloaded a release!");
|
||||
} else {
|
||||
println!("❌ No suitable releases found for download");
|
||||
}
|
||||
}
|
||||
Err(e) => println!("❌ Error: {}", e),
|
||||
}
|
||||
|
||||
// Example 2: Search releases for a specific episode
|
||||
println!("\n🎬 Example 2: Search releases for episode ID 123");
|
||||
match search_releases_for_episode(&client, 123).await {
|
||||
Ok(releases) => {
|
||||
println!("📋 Found {} releases:", releases.len());
|
||||
for (i, release) in releases.iter().enumerate().take(5) {
|
||||
println!(
|
||||
" {}. {} ({})",
|
||||
i + 1,
|
||||
release.title.as_deref().unwrap_or("Unknown"),
|
||||
format_size(release.size.unwrap_or(0))
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(e) => println!("❌ Error: {}", e),
|
||||
}
|
||||
|
||||
// Example 3: Search and download best quality for a season
|
||||
println!("\n📀 Example 3: Search and download best for season 1 of series 1");
|
||||
match search_and_download_best_for_season(&client, 1, 1).await {
|
||||
Ok(release_opt) => match release_opt {
|
||||
Some(release) => {
|
||||
println!(
|
||||
"✅ Downloaded: {}",
|
||||
release.title.as_deref().unwrap_or("Unknown")
|
||||
);
|
||||
println!(" Quality: {}", release.quality_weight.unwrap_or(0));
|
||||
println!(" Size: {}", format_size(release.size.unwrap_or(0)));
|
||||
}
|
||||
None => println!("❌ No suitable releases found"),
|
||||
},
|
||||
Err(e) => println!("❌ Error: {}", e),
|
||||
}
|
||||
|
||||
// Example 4: Manual search and selective download
|
||||
println!("\n🎯 Example 4: Manual search and filter");
|
||||
match manual_search_and_filter(&client, 1).await {
|
||||
Ok(()) => println!("✅ Manual search completed"),
|
||||
Err(e) => println!("❌ Error: {}", e),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Search and download the first available release for a series
|
||||
async fn search_and_download_for_series(
|
||||
client: &SonarrClient,
|
||||
series_id: u32,
|
||||
) -> Result<bool, ApiError> {
|
||||
client
|
||||
.search_and_download(Some(series_id), None, None)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Search for releases for a specific episode (without downloading)
|
||||
async fn search_releases_for_episode(
|
||||
client: &SonarrClient,
|
||||
episode_id: u32,
|
||||
) -> Result<Vec<yarr_api::ReleaseResource>, ApiError> {
|
||||
client.search_releases(None, Some(episode_id), None).await
|
||||
}
|
||||
|
||||
/// Search and download the best quality release for a season
|
||||
async fn search_and_download_best_for_season(
|
||||
client: &SonarrClient,
|
||||
series_id: u32,
|
||||
season_number: i32,
|
||||
) -> Result<Option<yarr_api::ReleaseResource>, ApiError> {
|
||||
client
|
||||
.search_and_download_best(Some(series_id), None, Some(season_number))
|
||||
.await
|
||||
}
|
||||
|
||||
/// Manual search with custom filtering logic
|
||||
async fn manual_search_and_filter(client: &SonarrClient, series_id: u32) -> Result<(), ApiError> {
|
||||
let releases = client.search_releases(Some(series_id), None, None).await?;
|
||||
|
||||
println!("🔍 Found {} total releases", releases.len());
|
||||
|
||||
// Custom filtering: prefer releases with specific criteria
|
||||
let filtered_releases: Vec<_> = releases
|
||||
.into_iter()
|
||||
.filter(|r| {
|
||||
// Only downloadable releases
|
||||
if !r.download_allowed.unwrap_or(false) || r.rejected.unwrap_or(true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prefer releases with higher seeds (for torrents)
|
||||
if let Some(seeders) = r.seeders {
|
||||
if seeders < 5 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid very large files (over 10GB)
|
||||
if let Some(size) = r.size {
|
||||
if size > 10 * 1024 * 1024 * 1024 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
.collect();
|
||||
|
||||
println!("📋 {} releases match our criteria", filtered_releases.len());
|
||||
|
||||
if let Some(best_release) = filtered_releases.first() {
|
||||
println!(
|
||||
"🎯 Downloading: {}",
|
||||
best_release.title.as_deref().unwrap_or("Unknown")
|
||||
);
|
||||
client.download_release(best_release).await?;
|
||||
println!("✅ Download initiated successfully!");
|
||||
} else {
|
||||
println!("❌ No releases match our filtering criteria");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Format file size in human-readable format
|
||||
fn format_size(bytes: i64) -> String {
|
||||
const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
|
||||
|
||||
if bytes == 0 {
|
||||
return "0 B".to_string();
|
||||
}
|
||||
|
||||
let mut size = bytes as f64;
|
||||
let mut unit_index = 0;
|
||||
|
||||
while size >= 1024.0 && unit_index < UNITS.len() - 1 {
|
||||
size /= 1024.0;
|
||||
unit_index += 1;
|
||||
}
|
||||
|
||||
format!("{:.1} {}", size, UNITS[unit_index])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_format_size() {
|
||||
assert_eq!(format_size(0), "0 B");
|
||||
assert_eq!(format_size(1024), "1.0 KB");
|
||||
assert_eq!(format_size(1536), "1.5 KB");
|
||||
assert_eq!(format_size(1048576), "1.0 MB");
|
||||
assert_eq!(format_size(1073741824), "1.0 GB");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user