hugely improve docs, including adding tutorial page and improving accuracy to reflect changes

This commit is contained in:
askiiart 2024-12-02 00:18:52 -06:00
parent 3e37af540e
commit 057dd7574c
Signed by untrusted user who does not match committer: askiiart
GPG key ID: EA85979611654C30
9 changed files with 87 additions and 52 deletions

View file

@ -6,9 +6,9 @@ Just fill in your own relevant functions and config ([`Config`]), and torznab-to
```rust ```rust
use torznab_toolkit; use torznab_toolkit;
let config: torznab_toolkit::config::Config = /* config goes here */ let config: torznab_toolkit::data::Config = /* config goes here */
torznab_toolkit::run(config); torznab_toolkit::run(config).await.unwrap();
``` ```
To configure what it listens on, just change `ROCKET_ADDRESS` and `ROCKET_PORT`; see the [relevant docs](https://rocket.rs/guide/v0.5/deploying/) for details. To configure what it listens on, just change `ROCKET_ADDRESS` and `ROCKET_PORT`; see the [relevant docs](https://rocket.rs/guide/v0.5/deploying/) for details.

View file

@ -1,8 +1,6 @@
//! Contains tons of structs used by the library //! Contains tons of structs used by the library
use std::collections::HashMap; use std::collections::HashMap;
use rocket::FromForm;
pub(crate) type AuthFunc = fn(String) -> Result<bool, String>; pub(crate) type AuthFunc = fn(String) -> Result<bool, String>;
pub(crate) type SearchFunc = fn(SearchParameters) -> Result<Vec<Torrent>, String>; pub(crate) type SearchFunc = fn(SearchParameters) -> Result<Vec<Torrent>, String>;
@ -93,15 +91,15 @@ pub struct Caps {
/// ///
/// Examples: `version`, `title`, `email`, `url`, `image` /// Examples: `version`, `title`, `email`, `url`, `image`
pub server_info: Option<HashMap<String, String>>, pub server_info: Option<HashMap<String, String>>,
/// The max and default number of items to be returned by queries - see [`Limits`] /// The max and default number of items to be returned by queries
pub limits: Limits, pub limits: Limits,
/// Info about each type of search /// Info about each type of search
pub searching: Vec<SearchInfo>, pub searching: Vec<SearchInfo>,
/// What categories the server has - see [`Category`] /// What categories the server has
pub categories: Vec<Category>, pub categories: Vec<Category>,
/// What genres the server has - see [`Genre`] (optional) /// What genres the server has (optional)
pub genres: Option<Vec<Genre>>, pub genres: Option<Vec<Genre>>,
/// What torrents can be tagged with - see [`Tag`] (optional) /// What torrents can be tagged with (optional)
pub tags: Option<Vec<Tag>>, pub tags: Option<Vec<Tag>>,
} }
@ -118,7 +116,7 @@ pub struct Config {
pub search: SearchFunc, pub search: SearchFunc,
/// The auth function - if not specified, then no authorization is needed. /// The auth function - if not specified, then no authorization is needed.
pub auth: Option<AuthFunc>, pub auth: Option<AuthFunc>,
/// The capabilities of the indexer - see [`Caps`] /// The capabilities of the indexer
pub caps: Caps, pub caps: Caps,
} }

View file

@ -1,24 +1,6 @@
//! Some dummy stuff for testing the API //! Some dummy stuff for testing the API
use crate::data::*; use crate::data::*;
use std::collections::HashMap; use std::{collections::HashMap, hash::Hash};
#[macro_export]
/// HashMap equivalent of vec![]
///
/// Example:
/// ```rust
/// hashmap!(("key", "value"))
/// ```
macro_rules! hashmap {
($(($value1:expr, $value2:expr)),*) => {{
let mut hm = HashMap::new();
$(
hm.insert($value1, $value2);
)*
hm
}};
}
fn dummy_search_func(_a: SearchParameters) -> Result<Vec<Torrent>, String> { fn dummy_search_func(_a: SearchParameters) -> Result<Vec<Torrent>, String> {
return Ok(vec![Torrent { return Ok(vec![Torrent {
@ -66,15 +48,16 @@ pub(crate) fn create_empty_config() -> Config {
description: "b".to_string(), description: "b".to_string(),
}]; }];
let mut server_info: HashMap<String, String> = HashMap::new();
server_info.insert("title".to_string(), "Test Torznab server".to_string());
server_info.insert("email".to_string(), "test@example.com".to_string());
server_info.insert("version".to_string(), "1.0".to_string());
return Config { return Config {
search: dummy_search_func, search: dummy_search_func,
auth: Some(dummy_auth_func), auth: Some(dummy_auth_func),
caps: Caps { caps: Caps {
server_info: Some(hashmap!( server_info: Some(server_info),
("title".to_string(), "Test Torznab server".to_string()),
("email".to_string(), "test@example.com".to_string()),
("version".to_string(), "1.0".to_string())
)),
limits: Limits { limits: Limits {
max: 100, max: 100,
default: 20, default: 20,

View file

@ -1,3 +1,6 @@
//! Links:
//! - **[Tutorial](notes::tutorial)**
//! - [Minor implementation and usage notes](notes::notes)
#![warn(missing_docs)] #![warn(missing_docs)]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
pub(crate) mod api; pub(crate) mod api;

View file

@ -1,6 +0,0 @@
//! Notes regarding the implementation of Torznab
//!
//! - Because the behavior of `length` is ambiguous, torznab-toolkit just sets it to 0; the size is just specified by the `size` attribute
//! - See [here](https://torznab.github.io/spec-1.3-draft/revisions/1.0-Torznab-Torrent-Support.html) for details
//! - Many indexers do not have the appropriate behavior according to the spec when `limit` is negative, and that behavior doesn't even make sense; instead, it follows the behavior of other indexers, and just ignores `limit` if it's negative.
//! - If a link isn't specified for a Torrent (`link` in `other_attributes`), it will fall back to the .torrent URL, then the magnet URI; i.e. you don't have to specify `link` if you don't have a webpage for the torrent.

View file

@ -1,2 +1,2 @@
pub mod implementation; pub mod notes;
pub mod usage; pub mod tutorial;

12
src/notes/notes.rs Normal file
View file

@ -0,0 +1,12 @@
//! Notes regarding the usage of torznab-tooolkit, and its implementation of Torznab
//!
//! - Please implement whatever attributes for torrents you can whenever possible to improve search results; particularly, `season`, `ep`, and `*id` fields are recommended, besides those listed in [``]
//! - Potential attributes are listed [here](https://torznab.github.io/spec-1.3-draft/torznab/Specification-v1.3.html#predefined-attributes)
//! - Because the behavior of `length` is ambiguous, torznab-toolkit just sets it to 0; the size is just specified by the `size` attribute
//! - See [here](https://torznab.github.io/spec-1.3-draft/revisions/1.0-Torznab-Torrent-Support.html) for details
//! - Many indexers do not have the appropriate behavior according to the spec when `limit` is negative, and that behavior doesn't even make sense; instead, it follows the behavior of other indexers, and just ignores `limit` if it's negative.
//! - If a link isn't specified for a Torrent (`link` in the `other_attributes` field of [`Torrent`]), it will fall back to the .torrent URL, then the magnet URI; i.e. you don't have to specify `link` if you don't have a webpage for the torrent.
//! - Currently if a function returns an [`Err`], torznab-toolkit won't handle it and will just return 500; however, Rocket will log it to the console.
// imports for docs
use crate::data::*;

56
src/notes/tutorial.rs Normal file
View file

@ -0,0 +1,56 @@
//! ## Structure of the program using this library
//!
//! First off, you should create a search function. This function will handle all search types, with what type being specified in the parameter's `search_type` field (`search`, `tv-search`, `movie-search`, `audio-search`, or `movie-search`). Given those parameters, the search function then returns a [`Result`]<[`Vec`]<[`Torrent`]>, [`String`]> object.
//! The torrents will be listed by the API in the order they're returned here
//!
//! ```rust
//! use torznab_toolkit::data::{SearchParameters, Torrent};
//!
//! fn search(parameters: SearchParameters) -> Result<Vec<Torrent>, String> {
//! return Ok(vec![Torrent {
//! title: "totally normal torrent".to_string(),
//! description: None,
//! size: 2484345508,
//! category_ids: vec![1010],
//! torrent_file_url: Some("http://localhost/totally-normal.torrent".to_string()),
//! magnet_uri: Some("magnet:?xt=urn:btih:blahblahblahdothechachacha".to_string()),
//! other_attributes: None,
//! }]);
//! }
//! ```
//!
//! If you want authentication, you can also create a function for that; returning true indicates that the apikey is valid.
//!
//! ```rust
//! fn auth(apikey: String) -> Result<bool, String> {
//! if apikey == "letmein".to_string() {
//! return Ok(true);
//! }
//! return Ok(false);
//! }
//! ```
//!
//! Now you need to configure torznab-toolkit using a [`Config`] object. In total, you'll need the following objects for the config:
//! - The search function
//! - The API function (optional)
//! - The capabilities of the server - i.e. ([`Caps`])
//!
//! Most of the config will be part of [`Caps`]. For details on all these, just check out the doc pages for each of the fields.
//!
//! TODO: Add examples for each struct used in [`Caps`]
//!
//! With all that, you can now start up the server, which is simple:
//!
//! ```rust
//! use torznab_toolkit;
//! let config: torznab_toolkit::data::Config = /* config goes here */
//!
//! torznab_toolkit::run(config).await.unwrap();
//! ```
//!
//! To easily change what address is listens on and what port, you can use the `ROCKET_ADDRESS` and `ROCKET_PORT` environment variables; the defaults are `127.0.0.1` and `8000`.
//! For more details on configuring Rocket, see the [Configuration](https://rocket.rs/guide/v0.5/configuration/) page in Rocket's docs - you can also use a `Rocket.toml` file.
// imports for the docs
use crate::data::*;
use crate::run;

View file

@ -1,11 +0,0 @@
//! Notes regarding the usage of torznab-tooolkit
//!
//! ---
//!
//! - Please implement the `season`, `ep`, and `id` attributes for torrents when possible
//! - Implementing `id`, at least, is far out of scope of this library, and providing `season` and `ep` more effective than this library parsing for them. However, parsing for those as an optional fallback may be added later.
//! - See [here](https://torznab.github.io/spec-1.3-draft/revisions/1.0-Torznab-Torrent-Support.html) for details
//!
//! TODO: Add better docs for using the library
// TODO: Add parsing for `season` and `ep`