Skip to content

Commit 705f1cc

Browse files
committed
docs: Update documentation and project metadata
1 parent 40ffd00 commit 705f1cc

9 files changed

Lines changed: 91 additions & 38 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "RuTorrent"
2+
name = "rutorrent"
33
version = "0.1.2"
44
description = "RuTorrent is a lightweight API that downloads magnet links and asynchronously transfers files to a remote server over SSH via rsync"
55
license = "MIT"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
### Installation
1111

1212
```shell
13-
cargo add RuTorrent
13+
cargo add rutorrent
1414
```
1515

1616
### Usage
17-
```rust
17+
```rust,no_run
1818
use rutorrent;
1919
2020
#[actix_rt::main]

src/api.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ fn resolve_payload(body: &[settings::PutItem]) -> Vec<settings::PutItem> {
230230
///
231231
/// # Arguments
232232
///
233+
/// * `request` - Reference to the `HttpRequest` object.
234+
/// * `pending` - Reference to the `PendingMap` object.
235+
/// * `config` - Reference to the `Config` object.
236+
/// * `db_connection` - Database connection received through app data.
233237
/// * `body` - Request body that takes `PutItem` object.
234238
///
235239
/// #### Sample Request
@@ -280,7 +284,7 @@ pub async fn put_torrent(
280284
request: HttpRequest,
281285
pending: web::Data<settings::PendingMap>,
282286
config: web::Data<settings::Config>,
283-
db_conn: web::Data<settings::DbConn>,
287+
db_connection: web::Data<settings::DBConnection>,
284288
body: web::Json<Vec<settings::PutItem>>,
285289
) -> impl Responder {
286290
if !authenticator(request, &config) {
@@ -343,7 +347,7 @@ pub async fn put_torrent(
343347
&& !item.remote_path.is_empty()
344348
{
345349
pending_lock.insert(tag.clone(), item.clone());
346-
if let Ok(conn) = db_conn.lock() {
350+
if let Ok(conn) = db_connection.lock() {
347351
database::upsert_pending(&conn, &tag, &item);
348352
}
349353
} else {

src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/// Entry point for the RuTorrent application.
2+
///
3+
/// This asynchronous main function triggers the `start` function from the `rutorrent` library.
14
#[actix_rt::main]
25
async fn main() -> std::io::Result<()> {
36
rutorrent::start().await

src/parser.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::constant;
22

3+
/// Represents the command-line arguments parsed from the environment.
34
#[derive(Debug, Clone)]
45
pub struct Arguments {
56
pub env_file: String,
@@ -8,9 +9,13 @@ pub struct Arguments {
89

910
/// Parses and returns the command-line arguments.
1011
///
12+
/// # Arguments
13+
///
14+
/// * `metadata` - Takes the project metadata as an argument.
15+
///
1116
/// # Returns
1217
///
13-
/// A String notion of the argument, `env_file` if present.
18+
/// Returns the `Arguments` object with `env_file` and `read_db` variables.
1419
pub fn arguments(metadata: &constant::MetaData) -> Arguments {
1520
let args: Vec<String> = std::env::args().collect();
1621

src/rsync.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ fn parse_progress(line: &str) -> Option<f64> {
3333
///
3434
/// # Arguments
3535
///
36-
/// * `state` - Shared application state used to track transfer progress and status
37-
/// * `hash` - Unique identifier for the transfer entry in the state
36+
/// * `state` - Shared application state used to track transfer progress and status.
37+
/// * `hash` - Unique identifier for the transfer entry in the state.
3838
/// * `name` - Human-readable name of the item being transferred (used for logging)
39-
/// * `source` - Local source path to be copied
40-
/// * `target` - Remote rsync target configuration (username, host, and destination path)
39+
/// * `source` - Local source path to be copied.
40+
/// * `put_item` - Reference to the `PutItem` object.
4141
///
4242
/// # Notes
4343
///

src/settings.rs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::num::NonZeroUsize;
44
use std::sync::Arc;
55
use tokio::sync::RwLock;
66
use utoipa::ToSchema;
7+
use std::str::FromStr;
78

89
/// ### SharedState
910
/// Shared application state for tracking active rsync operations.
@@ -12,9 +13,12 @@ pub type SharedState = Arc<RwLock<HashMap<String, RsyncTrack>>>;
1213
/// Shared map for storing pending torrent metadata before resolution.
1314
pub type PendingMap = Arc<RwLock<HashMap<String, PutItem>>>;
1415

15-
pub type DbConn = Arc<std::sync::Mutex<rusqlite::Connection>>;
16-
use std::str::FromStr;
16+
/// ### DBConnection
17+
/// Shared `ruslite` connection object.
18+
pub type DBConnection = Arc<std::sync::Mutex<rusqlite::Connection>>;
1719

20+
/// ### LogOptions
21+
/// Options for logging output.
1822
#[derive(Debug, Clone, PartialEq)]
1923
pub enum LogOptions {
2024
Stdout,
@@ -24,6 +28,13 @@ pub enum LogOptions {
2428
impl FromStr for LogOptions {
2529
type Err = String;
2630

31+
/// Parses a string into a `LogOptions` value.
32+
///
33+
/// Accepted values are:
34+
/// - `"stdout"` → logs to standard output
35+
/// - `"file"` → logs to a file
36+
///
37+
/// Returns an error if the input does not match a supported option.
2738
fn from_str(s: &str) -> Result<Self, Self::Err> {
2839
match s {
2940
"stdout" => Ok(LogOptions::Stdout),
@@ -64,17 +75,26 @@ pub struct Config {
6475
pub telegram_bot_token: String,
6576
}
6677

78+
/// Formats and prints the startup error message.
79+
///
80+
/// # Arguments
81+
///
82+
/// * `msg` - Message to be printed.
6783
fn startup_error(msg: &str) {
6884
eprintln!("\nStartupError:\n\t{}\n", msg);
6985
}
7086

71-
/// ### Config::new
72-
/// Creates a new [`Config`] instance from environment variables.
73-
///
74-
/// # Returns
75-
///
76-
/// A [`Config`] populated with environment values or sensible defaults.
7787
impl Config {
88+
/// Creates a new application configuration by reading environment variables.
89+
///
90+
/// Required values are validated at startup, and the process will terminate
91+
/// with an error message if any critical configuration is missing or invalid.
92+
///
93+
/// This includes:
94+
/// - API key validation
95+
/// - Worker count validation
96+
/// - Logging configuration parsing
97+
/// - External service configuration normalization (e.g. URL cleanup)
7898
pub fn new() -> Self {
7999
let host = squire::get_env_var("host", Some("127.0.0.1"));
80100
let port = squire::get_env_var("port", Some("3000"))
@@ -225,22 +245,33 @@ pub struct PutItem {
225245
pub delete_after_copy: bool,
226246
}
227247

248+
/// Gets the default host from the `remote_host` environment variable.
228249
fn default_host() -> String {
229250
squire::get_env_var("remote_host", None)
230251
}
231252

253+
/// Gets the default username from the `remote_user` environment variable.
232254
fn default_username() -> String {
233255
squire::get_env_var("remote_user", None)
234256
}
235257

258+
/// Gets the default remote path from the `remote_path` environment variable.
236259
fn default_path() -> String {
237260
squire::get_env_var("remote_path", None)
238261
}
239262

263+
/// Gets the default save path from the `save_path` environment variable.
240264
fn default_save_path() -> String {
241265
squire::get_env_var("save_path", None)
242266
}
243267

268+
/// Determines whether files should be deleted after copying.
269+
///
270+
/// This value is read from the `delete_after_copy` environment variable.
271+
/// If the variable is missing or cannot be parsed as a boolean,
272+
/// it defaults to `false`, since this is called during run-time.
244273
fn default_delete_after_copy() -> bool {
245-
false
274+
squire::get_env_var("delete_after_copy", Some("false"))
275+
.parse::<bool>()
276+
.unwrap_or(false)
246277
}

src/squire.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,14 @@ async fn qb_get(client: &Client, url: String) -> Option<Value> {
3030
/// # Arguments
3131
///
3232
/// * `array` - Array of existing torrents in QBitAPI.
33-
/// * `pending` - Shared map of pending torrent metadata keyed by tags
34-
/// * `state` - Shared state where active torrent tracking entries are stored
33+
/// * `pending` - Shared map of pending torrent metadata keyed by tags.
34+
/// * `state` - Shared state where active torrent tracking entries are stored.
35+
/// * `db_connection` - Database connection received through app data.
3536
async fn resolve_new_torrents(
3637
array: &Vec<Value>,
3738
pending: &settings::PendingMap,
3839
state: &settings::SharedState,
39-
db_conn: &settings::DbConn,
40+
db_connection: &settings::DBConnection,
4041
) {
4142
let mut pending_lock = pending.write().await;
4243
let mut db = state.write().await;
@@ -67,7 +68,7 @@ async fn resolve_new_torrents(
6768
put_item: item,
6869
},
6970
);
70-
if let Ok(conn) = db_conn.lock() {
71+
if let Ok(conn) = db_connection.lock() {
7172
database::remove_pending(&conn, tag);
7273
database::upsert(&conn, &hash, db.get(&hash).unwrap());
7374
}
@@ -113,10 +114,11 @@ fn notifier(title: String, body: String, config: settings::Config) {
113114
///
114115
/// # Arguments
115116
///
116-
/// * `client` - Authenticated HTTP client for qBittorrent API requests
117-
/// * `state` - Shared state used to track torrent and transfer progress
118-
/// * `pending` - Shared map of pending torrent metadata
119-
/// * `config` - Application configuration containing API settings
117+
/// * `client` - Authenticated HTTP client for qBittorrent API requests.
118+
/// * `state` - Shared state used to track torrent and transfer progress.
119+
/// * `pending` - Shared map of pending torrent metadata.
120+
/// * `config` - Application configuration containing API settings.
121+
/// * `db_connection` - Database connection received through app data.
120122
///
121123
/// # Notes
122124
///
@@ -129,7 +131,7 @@ pub fn spawn_worker(
129131
state: settings::SharedState,
130132
pending: settings::PendingMap,
131133
config: settings::Config,
132-
db_conn: settings::DbConn,
134+
db_connection: settings::DBConnection,
133135
) {
134136
tokio::spawn(async move {
135137
log::info!("Worker started");
@@ -159,7 +161,7 @@ pub fn spawn_worker(
159161
};
160162

161163
log::trace!("Torrents active: {:?}", array);
162-
resolve_new_torrents(array, &pending, &state, &db_conn).await;
164+
resolve_new_torrents(array, &pending, &state, &db_connection).await;
163165
} else {
164166
log::error!("Failed to get info from QBitAPI");
165167

@@ -210,7 +212,7 @@ pub fn spawn_worker(
210212
if !returned.contains(h.as_str()) {
211213
log::info!("Torrent removed from QBitAPI, dropping from state: {}", h);
212214
db.remove(h);
213-
if let Ok(conn) = db_conn.lock() {
215+
if let Ok(conn) = db_connection.lock() {
214216
database::remove(&conn, h);
215217
}
216218
}
@@ -241,7 +243,7 @@ pub fn spawn_worker(
241243
config_cloned,
242244
);
243245
db.remove(&hash);
244-
if let Ok(conn) = db_conn.lock() {
246+
if let Ok(conn) = db_connection.lock() {
245247
database::remove(&conn, &hash);
246248
}
247249
}
@@ -279,7 +281,7 @@ pub fn spawn_worker(
279281
}
280282
}
281283
db.remove(&hash);
282-
if let Ok(conn) = db_conn.lock() {
284+
if let Ok(conn) = db_connection.lock() {
283285
database::remove(&conn, &hash);
284286
}
285287
}
@@ -342,7 +344,11 @@ pub fn get_env_var(key: &str, default: Option<&str>) -> String {
342344
default.unwrap_or_default().to_string()
343345
}
344346

345-
/// Load dotenv file using the env var `env_file` or `ENV_FILE`
347+
/// Load dotenv file using the `env_file` CLI arg or an environment variable.
348+
///
349+
/// # Arguments
350+
///
351+
/// * `env_file` - Takes the `env_file` passed through CLI argument.
346352
pub fn load_env_file(mut env_file: String) {
347353
if env_file.is_empty() {
348354
env_file = get_env_var("env_file", Some(".env"));
@@ -356,11 +362,11 @@ pub fn load_env_file(mut env_file: String) {
356362
/// # Description
357363
/// A secret is considered strong if it satisfies all the following:
358364
///
359-
/// - Has at least `min_length` characters
360-
/// - Contains at least 1 digit
361-
/// - Contains at least 1 symbol (non-alphanumeric, non-whitespace)
362-
/// - Contains at least 1 uppercase letter
363-
/// - Contains at least 1 lowercase letter
365+
/// - Has at least "min_length" characters
366+
/// - Contains at least 1 digit
367+
/// - Contains at least 1 symbol (non-alphanumeric, non-whitespace)
368+
/// - Contains at least 1 uppercase letter
369+
/// - Contains at least 1 lowercase letter
364370
///
365371
/// # Arguments
366372
///

src/swagger.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ pub struct ApiDoc;
2424
struct SecurityAddon;
2525

2626
impl Modify for SecurityAddon {
27+
/// Adds an API key security scheme to the OpenAPI components.
28+
///
29+
/// This inserts an `apikey` header-based security scheme at the top level
30+
/// so it is available in Swagger UI and other OpenAPI consumers.
2731
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
2832
let components = openapi.components.get_or_insert_with(Default::default);
2933
components.add_security_scheme(

0 commit comments

Comments
 (0)