mwbot 0.7.1

A MediaWiki bot framework
Documentation
/*
Copyright (C) 2021 Kunal Mehta <legoktm@debian.org>

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

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

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

use crate::{ApiClient, Result};
use mwtitle::{
    SiteInfo as TitleSiteInfo, SiteInfoResponse as TitleSiteInfoResponse,
};
use serde::{de::Error, Deserialize, Deserializer};

// TODO: Port all this to mwapi_responses

#[derive(Debug, Deserialize)]
pub(crate) struct Response {
    pub(crate) query: SiteInfo,
}

#[derive(Clone, Debug, Deserialize)]
pub(crate) struct SiteInfo {
    pub(crate) general: General,
}

#[derive(Clone, Debug, Deserialize)]
pub(crate) struct General {
    // Turn the "MediaWiki {version}" generator field into just the version
    #[serde(rename = "generator")]
    #[serde(deserialize_with = "deserialize_version")]
    pub(crate) version: String,
    #[serde(rename = "servername")]
    pub(crate) server_name: String,
    #[serde(rename = "wikiid")]
    pub(crate) wiki_id: String,
}

fn deserialize_version<'de, D>(deserializer: D) -> Result<String, D::Error>
where
    D: Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;

    s.strip_prefix("MediaWiki ")
        .map(|stripped| stripped.to_string())
        .ok_or_else(|| {
            D::Error::custom(
                "string does not start with required prefix 'MediaWiki '",
            )
        })
}

pub(crate) async fn get_siteinfo(
    api: &ApiClient,
) -> Result<(SiteInfo, TitleSiteInfo)> {
    let resp = api
        .get_value(&[
            ("action", "query"),
            ("meta", "siteinfo"),
            ("siprop", "general|namespaces|namespacealiases|interwikimap"),
        ])
        .await?;
    let site_info: Response = serde_json::from_value(resp.clone())?;
    let title_site_info: TitleSiteInfoResponse = serde_json::from_value(resp)?;
    Ok((site_info.query, title_site_info.query))
}