1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! # Ferinth
//!
//! Ferinth is a simple library for using the [Modrinth API](https://github.com/modrinth/labrinth/wiki/API-Documentation) in Rust projects.
//! It uses [Reqwest](https://docs.rs/reqwest/) as its HTTPS client and deserialises responses to strongly typed structs using [SerDe](https://serde.rs/).
//!
//! ## Features
//!
//! This crate includes the following:
//!
//! - All structure definitions based on <https://docs.modrinth.com/api-spec/>
//! - All of the GET calls
//!
//! URL traversal is blocked because all IDs are verified.
//! ```
//! # #[tokio::main]
//! # async fn main() {
//! # let modrinth = ferinth::Ferinth::new();
//! assert!(modrinth.get_project("sodium/version").await.is_err());
//! # }
//! ```
//!
//! This crate uses [RusTLS](https://docs.rs/rustls/) rather than OpenSSL, because OpenSSL is outdated and slower.
//!
//! The following features still need to be implemented
//! - Search projects
//! - User authentication
//! - Other types of requests
//!

mod api_calls;
mod request;
pub mod structures;

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error("A given string was not base62 compliant")]
    NotBase62,
    #[error("A given string was not SHA1 compliant")]
    NotSHA1,
    #[error("{}", .0)]
    ReqwestError(#[from] reqwest::Error),
    #[error("{}", .0)]
    URLParseError(#[from] url::ParseError),
}

pub(crate) type Result<T> = std::result::Result<T, Error>;

/// An instance of the API to invoke API calls on.
///
/// To initialise this container,
/// ```rust
/// # use ferinth::Ferinth;
/// let modrinth = Ferinth::new();
/// // Use the instance to call the API
/// let sodium_mod = modrinth.get_project("sodium");
/// ```
#[derive(Debug, Clone)]
pub struct Ferinth {
    client: reqwest::Client,
}

impl Ferinth {
    /// Create a new API instance
    ///
    /// `user_agent` should be the name of the program
    ///
    /// ```rust
    /// # use ferinth::Ferinth;
    /// let modrinth = Ferinth::new();
    /// ```
    pub fn new() -> Self {
        Self {
            client: reqwest::Client::new(),
        }
    }
}