figure out a bunch of weird stuff and doc it, add struct to hold torrent info

This commit is contained in:
askiiart 2024-11-29 15:49:33 -06:00
parent 666ea1fd43
commit 8ad7ba87ac
Signed by untrusted user who does not match committer: askiiart
GPG key ID: EA85979611654C30
9 changed files with 155 additions and 38 deletions

View file

@ -8,6 +8,7 @@ use rocket::http::Status;
use rocket::response::status;
use rocket::FromForm;
use rocket::{get, response::content::RawXml};
use std::collections::HashMap;
use xml::writer::{EmitterConfig, XmlEvent};
#[derive(Debug, Clone, PartialEq, Eq, FromForm)]
@ -34,6 +35,7 @@ struct SearchForm {
}
impl SearchForm {
/// Converts it to a SearchParameters object
fn to_parameters(&self, conf: Config) -> SearchParameters {
// TODO: Clean up this code - split it into a separate function?
let mut categories: Option<Vec<u32>> = None;
@ -131,6 +133,7 @@ pub(crate) fn caps() -> status::Custom<RawXml<String>> {
#[get("/api?t=search&<form..>")]
/// The search function for the API
// FIXME: VERY incomplete also
pub(crate) fn search(form: SearchForm) -> status::Custom<RawXml<String>> {
// The compiler won't let you get a field from a struct in the Option here, since the default is None
// So this is needed
@ -151,10 +154,7 @@ pub(crate) fn search(form: SearchForm) -> status::Custom<RawXml<String>> {
match parameters.apikey {
Some(apikey) => {
if !auth(apikey).unwrap() {
return status::Custom(
Status::Unauthorized,
RawXml("401 Unauthorized".to_string()),
);
unauthorized = true;
}
}
None => {

View file

@ -1,5 +1,7 @@
//! Contains tons of structs used by the library
use std::collections::HashMap;
use rocket::FromForm;
pub(crate) type AuthFunc = fn(String) -> Result<bool, String>;
// TODO: Figure out what the arguments should be for a search function and what it should return
@ -97,17 +99,23 @@ pub struct Tag {
#[derive(Debug, Clone, PartialEq, Eq)]
/// Holds the configuration for the capabilities of the Torznab server (used in `/api?t=caps`)
///
/// <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.
/// <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 501.
///
/// 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 automatically from the Config
pub struct Caps {
pub server_info: ServerInfo,
/// The server info, like title - optional
pub server_info: Option<ServerInfo>,
/// The max and default number of items to be returned by queries - see [`Limits`]
pub limits: Limits,
/// Info about each type of search
pub searching: Vec<SearchInfo>,
/// What categories the server has - see [`Category`]
pub categories: Vec<Category>,
/// What genres the server has - see [`Genre`] (optional)
pub genres: Option<Vec<Genre>>,
/// What torrents can be tagged with - see [`Tag`] (optional)
pub tags: Option<Vec<Tag>>,
}
@ -116,12 +124,19 @@ pub struct Caps {
/// The search function (`/api?t=search`) and capabilities (`/api?t=caps` - struct [`Caps`]) are required
/// Everything else is optional
pub struct Config {
/// The function to use for a free text search
pub search: SearchFunc,
/// The auth function - if not specified, then no authorization is needed.
pub auth: Option<AuthFunc>,
/// The capabilities of the indexer - see [`Caps`]
pub caps: Caps,
/// The function to use for a tv search
pub tvsearch: Option<SearchFunc>,
/// The function to use for a movie search
pub movie: Option<SearchFunc>,
/// The function to use for a music search
pub music: Option<SearchFunc>,
/// The function to use for a book search
pub book: Option<SearchFunc>,
}
@ -142,3 +157,20 @@ pub(crate) struct SearchParameters {
/// The maximum number of items to return - also limited to whatever `limits` is in [`Caps`]
pub(crate) limit: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
/// Holds the info for a torrent
pub struct Torrent {
title: String,
description: Option<String>,
size: u64,
categories: Vec<Category>,
seeders: Option<u32>,
leechers: Option<u32>,
peers: Option<u32>,
infohash: Option<String>,
link: Option<String>,
torrent_file_url: Option<String>,
magnet_uri: Option<String>,
other_attributes: Option<HashMap<String, String>>,
}

View file

@ -48,12 +48,12 @@ pub(crate) fn create_empty_config() -> Config {
search: dummy_search_func,
auth: Some(dummy_auth_func),
caps: Caps {
server_info: ServerInfo {
server_info: Some(ServerInfo {
title: Some("Test Torznab server".to_string()),
email: Some("test@example.com".to_string()),
image: None,
version: Some("1.0".to_string()),
},
}),
limits: Limits {
max: 100,
default: 20,

View file

@ -1,23 +1,5 @@
#![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.
#![doc = include_str!("../README.md")]
pub mod api;
pub mod data;
mod dummy;
@ -42,3 +24,6 @@ pub async fn run(conf: data::Config) -> Result<bool, rocket::Error> {
}
}
}
/// Notes regarding the usage of torznab-toolkit and how it implements the Torznab API.
pub mod notes;

View file

@ -0,0 +1,6 @@
//! 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

1
src/notes/mod.rs Normal file
View file

@ -0,0 +1 @@
pub mod usage;

8
src/notes/usage.rs Normal file
View file

@ -0,0 +1,8 @@
//! 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 parsing for `season` and `ep`