1
/*
2
Copyright (C) 2021 Kunal Mehta <legoktm@debian.org>
3

            
4
This program is free software: you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation, either version 3 of the License, or
7
(at your option) any later version.
8

            
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13

            
14
You should have received a copy of the GNU General Public License
15
along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
 */
17

            
18
//! A MediaWiki API client library.
19
//!
20
//! `mwapi` is a low-level library for the [MediaWiki Action API](https://www.mediawiki.org/wiki/API:Main_page).
21
//! If you intend to edit pages or want a higher-level interface, it's recommended to use [`mwbot`](https://docs.rs/mwbot/),
22
//! which builds on top of this crate.
23
//!
24
//! ## Goals
25
//! * generic to fit any application, whether for interactive usage
26
//!   or writing a bot
27
//! * fully compatible with concurrent use cases
28
//! * turns MediaWiki errors into Rust errors for you
29
//! * logging (using the `tracing` crate) for visiblity into errors
30
//! * follow all [best practices](https://www.mediawiki.org/wiki/API:Etiquette)
31
//!
32
//! ## Quick start
33
//! ```
34
//! # #[tokio::main]
35
//! # async fn main() -> mwapi::Result<()> {
36
//! let client = mwapi::Client::builder("https://en.wikipedia.org/w/api.php")
37
//!     .set_user_agent("mwapi demo")
38
//!     // Provide credentials for login:
39
//!     // .set_botpassword("username", "password")
40
//!     .build().await?;
41
//! let resp = client.get_value(&[
42
//!     ("action", "query"),
43
//!     ("prop", "info"),
44
//!     ("titles", "Taylor Swift"),
45
//! ]).await?;
46
//! let info = resp["query"]["pages"][0].clone();
47
//! assert_eq!(info["ns"].as_u64().unwrap(), 0);
48
//! assert_eq!(info["title"].as_str().unwrap(), "Taylor Swift");
49
//! # Ok(())
50
//! # }
51
//!
52
//! ```
53
//!
54
//! ## Functionality
55
//! * authentication, using [OAuth2](https://www.mediawiki.org/wiki/OAuth/Owner-only_consumers#OAuth_2) (recommended) or BotPasswords
56
//! * error handling, transforming MediaWiki errors into Rust ones
57
//! * CSRF [token](https://www.mediawiki.org/wiki/API:Tokens) handling with `post_with_token`
58
//! * rate limiting and concurrency controls
59
//! * file uploads (needs `upload` feature)
60
//!
61
//! ## See also
62
//! * [`mwbot`](https://docs.rs/mwbot/) provides a higher level interface to
63
//!   interacting with MediaWiki
64
//! * [`mwapi_responses`](https://docs.rs/mwapi_responses/) is a macro to
65
//!   generate strict types for dynamic API queries
66
//!
67
//! ## Contributing
68
//! `mwapi` is a part of the [`mwbot-rs` project](https://www.mediawiki.org/wiki/Mwbot-rs).
69
//! We're always looking for new contributors, please [reach out](https://www.mediawiki.org/wiki/Mwbot-rs#Contributing)
70
//! if you're interested!
71
#![deny(clippy::all)]
72
#![deny(rustdoc::all)]
73
#![cfg_attr(docsrs, feature(doc_cfg))]
74

            
75
mod client;
76
mod error;
77
mod params;
78
mod responses;
79
mod time;
80
mod tokens;
81
#[cfg(feature = "upload")]
82
mod upload;
83

            
84
const VERSION: &str = env!("CARGO_PKG_VERSION");
85

            
86
pub use client::{Builder, Client};
87
pub use error::{ApiError, Error};
88
pub use params::Params;
89
use std::fmt::{Display, Formatter};
90

            
91
pub type Result<T> = std::result::Result<T, Error>;
92

            
93
/// Assert that your account has the specified login state, see
94
/// [API:Assert](https://www.mediawiki.org/wiki/API:Assert) for more details.
95
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
96
pub enum Assert {
97
    /// Not logged in, aka anonymous
98
    Anonymous,
99
    /// Logged in to a bot account
100
    Bot,
101
    /// Logged in (to any account)
102
    User,
103
    /// Do not add any assert
104
    None,
105
}
106

            
107
impl Assert {
108
222
    fn value(&self) -> Option<&'static str> {
109
222
        match self {
110
2
            Assert::Anonymous => Some("anon"),
111
            Assert::Bot => Some("bot"),
112
2
            Assert::User => Some("user"),
113
218
            Assert::None => None,
114
        }
115
222
    }
116
}
117

            
118
impl Default for Assert {
119
    fn default() -> Self {
120
        Self::None
121
    }
122
}
123

            
124
#[derive(Clone, Copy, Debug)]
125
pub enum ErrorFormat {
126
    Html,
127
    Wikitext,
128
    Plaintext,
129
}
130

            
131
impl Display for ErrorFormat {
132
226
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
133
226
        let val = match &self {
134
            ErrorFormat::Html => "html",
135
200
            ErrorFormat::Wikitext => "wikitext",
136
26
            ErrorFormat::Plaintext => "plaintext",
137
        };
138
226
        write!(f, "{val}")
139
226
    }
140
}
141

            
142
impl Default for ErrorFormat {
143
112
    fn default() -> Self {
144
112
        Self::Plaintext
145
112
    }
146
}
147

            
148
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
149
pub(crate) enum Method {
150
    Get,
151
    Post,
152
}