Initial commit

This commit is contained in:
askiiart 2024-11-21 13:19:57 -06:00
commit 493d019352
Signed by untrusted user who does not match committer: askiiart
GPG key ID: EA85979611654C30
9 changed files with 1798 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

1598
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

7
Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "torznab-toolkit"
version = "0.1.0"
edition = "2021"
[dependencies]
rocket = "0.5.1"

21
README.md Normal file
View file

@ -0,0 +1,21 @@
# Torznab Toolkit
A toolkit for adding Torznab APIs to programs.
## Functionality
| API call | Explanation | Compatibility |
| -------- | ------------------------------------------------------------ | -------------- |
| caps | Returns the capabilities of the api. | ❌ |
| search | Free text search query. | ❌ |
| tvsearch | Search query with tv specific query params and filtering. | ❌ |
| movie | Search query with movie specific query params and filtering. | ❌ |
| music | Search query with music specific query params and filtering. | ❌ |
| book | Search query with book specific query params and filtering. | ❌ |
<!-- for copy-pasting: ❌ ✅ -->
(copied from [torznab.github.io](https://torznab.github.io/spec-1.3-draft/torznab/Specification-v1.3.html))
## Notes
Thanks to [torznab.github.io](https://torznab.github.io), as it's my primary reference for this.

22
dev-notes.md Normal file
View file

@ -0,0 +1,22 @@
# Dev notes
## Resources
- <https://torznab.github.io/spec-1.3-draft/index.html>
- <https://www.git.je/Mirrors/Sonarr/wiki/Implementing-a-Torznab-indexer>
- for testing: <https://fosstorrents.com/thankyou/?name=debian&cat=Installation%20-%20amd64&id=0&hybrid=0>
---
```rs
struct TorznabToolkitConfig {
auth_func: auth,
search_func: search,
whateverotherfunc: otherfunc,
port: 5309
}
fn launch() -> Result {
rocket::build().mount("/", routes![tt::search, tt:otherfunc])
}
```

4
src/api.rs Normal file
View file

@ -0,0 +1,4 @@
use rocket::get;
#[get("/api?t=caps")]
pub(crate) fn caps() -> Result<String, String> {}

51
src/config.rs Normal file
View file

@ -0,0 +1,51 @@
use crate::data::*;
type AuthFunc = fn(String) -> Result<String, String>;
type SearchFunc = fn(String, Vec<String>) -> Result<String, String>;
#[derive(Debug)]
pub struct Config {
/// A struct that holds configuration for torznab-toolkit
/// A search function (/api?t=search) and capabilities (/api?t=caps - struct Caps) required
/// Everything else is optional
pub search: SearchFunc,
pub auth: Option<AuthFunc>,
pub caps: Caps,
pub tvsearch: Option<SearchFunc>,
pub movie: Option<SearchFunc>,
pub music: Option<SearchFunc>,
pub book: Option<SearchFunc>,
}
#[derive(Debug)]
pub struct Caps {
/// Holds the configuration for the capabilities of the Torznab server
///
/// - server_info: `ServerInfo`
/// - see: `ServerInfo` docs
/// - limits: `Limits`
/// - specifies the max and default items listed when searching
/// - see: `Limits` docs
/// - searching: `Vec<SearchInfo>`
/// - specifies the capabilities of each search mode
/// - see: `SearchInfo` docs
/// - categories: `Vec<Category>`
/// - lists known categories
/// - see: `Category` docs
/// - genres: `Option<Vec<Genre>>`
/// - lists known genres, optional
/// - see: `Genre` docs
///
/// <div class="warning">Note that this library might not support all the capabilities listed in yet, so check the README before listing capabilities, or just accept that unsupported capabilities will return error 404.
///
/// It's recommended to add any capabilities you want, and set `available` to `false` in the `Caps` struct for any currently unsupported search types.</div>
///
///
/// TODO: Add a way to partially generate search capabilities automatically from the Config
pub server_info: ServerInfo,
pub limits: Limits,
pub searching: Vec<SearchInfo>,
pub categories: Vec<Category>,
pub genres: Option<Vec<Genre>>,
pub tags: Option<Vec<Tag>>,
}

62
src/data.rs Normal file
View file

@ -0,0 +1,62 @@
#[derive(Debug)]
pub struct ServerInfo {
/// Specify the ServerInfo to be listed in <server> for `/api?t=caps`
///
/// These fields are just those listed in the example on [torznab.github.io](https://torznab.github.io), there's no actual specification for thse fields.
/// TODO: Update this to have customizable fields instead
pub title: Option<String>,
pub email: Option<String>,
pub image: Option<String>,
pub version: Option<String>,
}
#[derive(Debug)]
pub struct Limits {
/// The maximum and defaults for the `limit` parameter in queries
/// `max` is the maximum number of results the program can return
/// `default` is the default number of results the program will return
/*
I don't know why this would possibly need to be a u64, I can't imagine you'll be returning 18 quintillion results or whatever
In fact, I *really* hope you aren't - if you are, you're doing something extremely wrong
But hey, it's an option
*/
pub max: u64,
pub default: u64,
}
#[derive(Debug)]
pub struct SearchInfo {
/// A struct holding the info for a type of search
/// - `search_type` must be `search`, `tv-search`, `movie-search`, `audio-search`, or `book-search`
/// - `available`
pub search_type: String,
pub available: bool,
pub supported_params: Vec<String>,
}
#[derive(Debug)]
pub struct Subcategory {
pub id: String,
pub name: String,
}
#[derive(Debug)]
pub struct Category {
pub id: String,
pub name: String,
pub subcategories: Vec<Subcategory>,
}
#[derive(Debug)]
pub struct Genre {
pub id: String,
pub category_id: String,
pub name: String,
}
#[derive(Debug)]
pub struct Tag {
pub id: String,
pub category_id: String,
pub name: String,
}

32
src/lib.rs Normal file
View file

@ -0,0 +1,32 @@
#![warn(missing_docs)]
//! A toolkit for adding Torznab APIs to programs.
//!
//! Just fill in your own relevant functions and config, and
//! torznab-toolkit will run the API for you
//!
//! ```rs
//! use torznab_toolkit;
//! let config: torznab_toolkit::config::Config =
//!
//! ```
//!
//! The environment variables `ROCKET_ADDRESS` and `ROCKET_PORT` specify the address and port it will run on; these currently cannot be configured any other way. See the [relevant docs](https://rocket.rs/guide/v0.5/deploying/) for details.
//!
//! ---
//!
//! This program is brought to you by: metaphorical *and* literal truckloads of structs!
//!
//! Note: I wrote the line above when I was tired. Don't ask me what *literal* truckloads of structs means, I don't know either.
mod api;
pub mod config;
pub mod data;
use config::{Caps, Config};
use rocket;
pub fn run(config: Config, caps: Caps) -> Result<bool, String> {
/// Runs the server
rocket::build().mount("/", rocket::routes![api::caps]);
return Ok(true);
}