use crate::types::{HistoryEntry, Status};
use sqlx::{FromRow, sqlite::SqlitePool};
use std::path::PathBuf;
mod articles;
mod downloads;
mod duplicates;
mod history;
mod migrations;
mod passwords;
mod rss;
mod state;
#[derive(Debug, Clone)]
pub struct NewDownload {
pub name: String,
pub nzb_path: String,
pub nzb_meta_name: Option<String>,
pub nzb_hash: Option<String>,
pub job_name: Option<String>,
pub category: Option<String>,
pub destination: String,
pub post_process: i32,
pub priority: i32,
pub status: i32,
pub size_bytes: i64,
}
#[derive(Debug, Clone, FromRow)]
pub struct Download {
pub id: i64,
pub name: String,
pub nzb_path: String,
pub nzb_meta_name: Option<String>,
pub nzb_hash: Option<String>,
pub job_name: Option<String>,
pub category: Option<String>,
pub destination: String,
pub post_process: i32,
pub priority: i32,
pub status: i32,
pub progress: f32,
pub speed_bps: i64,
pub size_bytes: i64,
pub downloaded_bytes: i64,
pub error_message: Option<String>,
pub created_at: i64,
pub started_at: Option<i64>,
pub completed_at: Option<i64>,
pub direct_unpack_state: i32,
pub direct_unpack_extracted_count: i32,
}
#[derive(Debug, Clone)]
pub struct NewArticle {
pub download_id: crate::types::DownloadId,
pub message_id: String,
pub segment_number: i32,
pub file_index: i32,
pub size_bytes: i64,
}
#[derive(Debug, Clone, FromRow)]
pub struct Article {
pub id: i64,
pub download_id: i64,
pub message_id: String,
pub segment_number: i32,
pub file_index: i32,
pub size_bytes: i64,
pub status: i32,
pub downloaded_at: Option<i64>,
}
#[derive(Debug, Clone)]
pub struct NewDownloadFile {
pub download_id: crate::types::DownloadId,
pub file_index: i32,
pub filename: String,
pub subject: Option<String>,
pub total_segments: i32,
}
#[derive(Debug, Clone, FromRow)]
pub struct DownloadFile {
pub id: i64,
pub download_id: i64,
pub file_index: i32,
pub filename: String,
pub subject: Option<String>,
pub total_segments: i32,
pub paused: i32,
pub completed: i32,
pub original_filename: Option<String>,
}
pub mod article_status {
pub const PENDING: i32 = 0;
pub const DOWNLOADED: i32 = 1;
pub const FAILED: i32 = 2;
}
#[derive(Debug, Clone)]
pub struct NewHistoryEntry {
pub name: String,
pub category: Option<String>,
pub destination: Option<PathBuf>,
pub status: i32,
pub size_bytes: u64,
pub download_time_secs: i64,
pub completed_at: i64,
}
#[derive(Debug, Clone, FromRow)]
pub struct HistoryRow {
pub id: i64,
pub name: String,
pub category: Option<String>,
pub destination: Option<String>,
pub status: i32,
pub size_bytes: i64,
pub download_time_secs: i64,
pub completed_at: i64,
}
impl From<HistoryRow> for HistoryEntry {
fn from(row: HistoryRow) -> Self {
use chrono::{TimeZone, Utc};
use std::time::Duration;
HistoryEntry {
id: row.id,
name: row.name,
category: row.category,
destination: row.destination.map(PathBuf::from),
status: Status::from_i32(row.status),
size_bytes: row.size_bytes as u64,
download_time: Duration::from_secs(row.download_time_secs as u64),
completed_at: Utc
.timestamp_opt(row.completed_at, 0)
.single()
.unwrap_or_else(Utc::now),
}
}
}
#[derive(Debug, Clone, FromRow)]
pub struct RssFeed {
pub id: i64,
pub name: String,
pub url: String,
pub check_interval_secs: i64,
pub category: Option<String>,
pub auto_download: i32,
pub priority: i32,
pub enabled: i32,
pub last_check: Option<i64>,
pub last_error: Option<String>,
pub created_at: i64,
}
#[derive(Debug, Clone, FromRow)]
pub struct RssFilterRow {
pub id: i64,
pub feed_id: i64,
pub name: String,
pub include_patterns: Option<String>,
pub exclude_patterns: Option<String>,
pub min_size: Option<i64>,
pub max_size: Option<i64>,
pub max_age_secs: Option<i64>,
}
pub struct InsertRssFeedParams<'a> {
pub name: &'a str,
pub url: &'a str,
pub check_interval_secs: i64,
pub category: Option<&'a str>,
pub auto_download: bool,
pub priority: i32,
pub enabled: bool,
}
pub struct UpdateRssFeedParams<'a> {
pub id: i64,
pub name: &'a str,
pub url: &'a str,
pub check_interval_secs: i64,
pub category: Option<&'a str>,
pub auto_download: bool,
pub priority: i32,
pub enabled: bool,
}
pub struct InsertRssFilterParams<'a> {
pub feed_id: i64,
pub name: &'a str,
pub include_patterns: Option<&'a str>,
pub exclude_patterns: Option<&'a str>,
pub min_size: Option<i64>,
pub max_size: Option<i64>,
pub max_age_secs: Option<i64>,
}
pub struct Database {
pool: SqlitePool,
}
#[allow(clippy::unwrap_used, clippy::expect_used)]
#[cfg(test)]
mod tests;