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::{parsoid::*, Result};

/// Implementation of the `{{nobots}}` exclusion mechanism as documented
/// at [Template:Bots](https://en.wikipedia.org/wiki/Template:Bots).
///
/// If true, the page is fine to edit. If false, don't edit.
pub fn nobots(html: &ImmutableWikicode, user: &str) -> Result<bool> {
    let code = html.clone().into_mutable();
    for temp in code.filter_templates()? {
        if ["Template:Bots", "Template:Nobots"].contains(&temp.name().as_str())
        {
            for (param, value) in temp.params() {
                let bots: Vec<_> = value.split(',').collect();
                if param == "allow" {
                    if value == "none" {
                        return Ok(false);
                    }
                    if bots.contains(&"all") || bots.contains(&user) {
                        return Ok(true);
                    }
                } else if param == "deny" {
                    if value == "none" {
                        return Ok(true);
                    }
                    if bots.contains(&"all") || bots.contains(&user) {
                        return Ok(false);
                    }
                }
            }
            if temp.name_in_wikitext() == "nobots" && temp.params().is_empty() {
                return Ok(false);
            }
        }
    }
    Ok(true)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tests::testwp;

    async fn check_nobots(bot: &crate::Bot, wikitext: &str) -> bool {
        let html = bot.parsoid.transform_to_html(wikitext).await.unwrap();
        nobots(&html, "Username").unwrap()
    }

    #[tokio::test]
    async fn test_nobots() {
        let bot = testwp().await;
        assert!(check_nobots(&bot, "{{bots}}").await);
        assert!(!(check_nobots(&bot, "{{nobots}}").await));
        assert!(check_nobots(&bot, "{{bots|allow=Username}}").await);
        assert!(!(check_nobots(&bot, "{{bots|deny=Username}}").await));
        assert!(!(check_nobots(&bot, "{{bots|deny=Example,Username}}").await));
        assert!(check_nobots(&bot, "{{bots|allow=all}}").await);
        assert!(!(check_nobots(&bot, "{{bots|allow=none}}").await));
        assert!(!(check_nobots(&bot, "{{bots|deny=all}}").await));
        assert!(check_nobots(&bot, "{{bots|deny=none}}").await);
    }
}