# mwbot

[![crates.io](https://img.shields.io/crates/v/mwbot.svg)](https://crates.io/crates/mwbot)
[![docs.rs](https://img.shields.io/docsrs/mwbot?label=docs.rs)](https://docs.rs/mwbot)
[![docs (main)](https://img.shields.io/badge/doc.wikimedia.org-green?label=docs%40main)](https://doc.wikimedia.org/mwbot-rs/mwbot/mwbot/)
[![pipeline status](https://gitlab.wikimedia.org/repos/mwbot-rs/mwbot/badges/main/pipeline.svg)](https://gitlab.wikimedia.org/repos/mwbot-rs/mwbot/-/commits/main)
[![coverage report](https://img.shields.io/endpoint?url=https%3A%2F%2Fdoc.wikimedia.org%2Fcover%2Fmwbot-rs%2Fmwbot%2Fcoverage%2Fcoverage.json)](https://doc.wikimedia.org/cover/mwbot-rs/mwbot/coverage)

A MediaWiki bot and tool framework

`mwbot` aims to provide a batteries-included framework for building bots
and tools for MediaWiki wikis. It builds on top of the [mwapi](https://docs.rs/mwapi)
and [parsoid](https://docs.rs/parsoid) crates, which offer lower-level APIs.

### Quickstart
#### Configuration
Create a `~/.config/mwbot.toml` file with the following structure:
```toml
wiki_url = "https://en.wikipedia.org/w/"
```

If want to authenticate, add an auth section:
```toml
[auth]
username = "Example"
oauth2_token = "[...]"
```
See [the OAuth documentation](https://www.mediawiki.org/wiki/OAuth/For_Developers#OAuth_2)
for how to get an OAuth 2 token. Using an [owner-only consumer](https://www.mediawiki.org/wiki/OAuth/Owner-only_consumers#OAuth_2)
is the easiest way to do so.

<div class="warning">

On UNIX-like systems, for security, you must make sure the config's
file permissions don't permit reading by other users, or authorization
will fail with a [`ReadableConfig`][ConfigError::ReadableConfig] error. In this case,
`chmod 600 ~/.config/mwbot.toml` can be used to correct the permissions and
make sure the file is only readable and writeable to its owner.

</div>
#### Reading a page
```rust
let bot = mwbot::Bot::from_default_config().await.unwrap();
let page = bot.page("Rust (programming language)")?;
let html = page.html().await?.into_mutable();
// The lead section is the second p tag in the first section
let lead = html.select("section > p")[1].text_contents();
assert!(lead.starts_with("Rust is a multi-paradigm, general-purpose programming language"));
```
Using [`Bot::from_default_config()`] will look in the current directory
for `mwbot.toml` before looking in the user's config directory. A
custom path can be specified by using `Bot::from_config(...)`.

#### Editing a page
```rust
let bot = mwbot::Bot::from_default_config().await.unwrap();
let page = bot.page("Project:Sandbox")?;
let wikitext = "This is a test edit!";
page.save(wikitext, &SaveOptions::summary("test edit!")).await?;
```
`Page.save()` accepts both HTML and wikitext and supports the [`{{nobots}}`](https://en.wikipedia.org/wiki/Template:Bots)
exclusion mechanism, among other features.

#### Next steps
Try using one of the offered [page generators](./generators/index.html) to fetch and operate on
multiple pages.

### Contributing
`mwbot` is the flagship crate of the [`mwbot-rs` project](https://www.mediawiki.org/wiki/Mwbot-rs).
We're always looking for new contributors, please [reach out](https://www.mediawiki.org/wiki/Mwbot-rs#Contributing)
if you're interested!

## License
This crate is released under GPL-3.0-or-later.
See [COPYING](./COPYING) for details.
