Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 44 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,66 @@
# lichess-api

[![Crates.io][crates-badge]][crates-url]
[![Docs.rs][docs-badge]][docs-url]
[![Dependencies][deps-badge]][deps-url]
[![Apache 2.0 licensed][apache-badge]][apache-url]

[crates-badge]: https://img.shields.io/crates/v/lichess-api.svg
[crates-url]: https://crates.io/crates/lichess-api
[docs-badge]: https://docs.rs/lichess-api/badge.svg
[docs-url]: https://docs.rs/lichess-api
[deps-badge]: https://deps.rs/repo/github/ion232/lichess-api/status.svg
[deps-url]: https://deps.rs/repo/github/ion232/lichess-api
[apache-badge]: https://img.shields.io/badge/license-Apache%202.0-blue.svg
[apache-url]: LICENSE

A Rust API client library for [the current lichess.org API](https://lichess.org/api).
All endpoints are supported.
An asynchronous client library for [the current lichess.org API](https://lichess.org/api) with all endpoints supported.

## Features
## Quick start

| Feature | Default | Description |
|---------|:-------:|-------------|
| `oauth` | yes | OAuth2 authorization code flow with PKCE, for acting on behalf of other users. Pulls in `rand` and `sha2`. |

Most clients authenticate with a [personal API token](https://lichess.org/account/oauth/token) and don't need the OAuth flow. If you only ever act as yourself, you can drop the dependencies:
Add the dependencies:

```toml
lichess-api = { version = "0.7", default-features = false }
[dependencies]
lichess-api = "0.7"
tokio = { version = "1", features = ["full"] }
```

Example request:

```rust,no_run
use lichess_api::client::LichessApi;

#[tokio::main]
async fn main() -> lichess_api::error::Result<()> {
let client = reqwest::Client::new();
let token = std::env::var("LICHESS_TOKEN").ok();
let api = LichessApi::new(client, token);

let profile = api.get_profile().await?;
println!("username: {}", profile.user.username);

Ok(())
}
```

## Authentication

Most endpoints require a bearer token but some don't. E.g. the daily puzzle, etc.

- **Acting as yourself**: generate a [personal API
token](https://lichess.org/account/oauth/token) and pass it to
`LichessApi::new` as above.
- **Acting on behalf of another user**: Ensure the oauth feature is enabled and use the OAuth2 authorization code flow
with PKCE, via [`AuthorizationUrl`](https://docs.rs/lichess-api/latest/lichess_api/model/oauth/authorize/struct.AuthorizationUrl.html) and
[`PendingAuthorization`](https://docs.rs/lichess-api/latest/lichess_api/model/oauth/struct.PendingAuthorization.html).

## Features

| Feature | Default | Description |
|---------|:-------:|-------------|
| `oauth` | yes | OAuth2 authorization code flow with PKCE, for acting on behalf of other users. |

## Contributing

If you have any ideas, bug reports, feature requests, or fixes, please make an issue or submit a pull request.
Expand Down
9 changes: 9 additions & 0 deletions lib/src/api/account.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
//! Read and manage the logged in user's own account: public profile, email
//! address, kid mode, preferences, and activity timeline.
//!
//! Every method here requires a bearer token for the account being queried —
//! there is no anonymous access. [`LichessApi::get_email_address`] and
//! [`LichessApi::get_kid_mode_status`]/[`LichessApi::set_kid_mode_status`]
//! additionally require the `email:read` and `preference:read` (or
//! `preference:write`) scopes respectively, not just any token.

use crate::client::LichessApi;
use crate::error::Result;
use crate::model::account::*;
Expand Down
10 changes: 10 additions & 0 deletions lib/src/api/analysis.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
//! Position analysis.
//!
//! Lichess maintains a database of cloud engine evaluations for positions it
//! has already analyzed (mostly openings, around 320 million positions).
//! [`LichessApi::get_cloud_evaluation`] looks one up by FEN and returns its
//! principal variations if present, or an error if the position hasn't been
//! evaluated. This endpoint is public and needs no bearer token; it's meant
//! for occasional lookups, not bulk fetching — for that, use the exported
//! evaluation database from lichess.org directly.

use crate::client::LichessApi;
use crate::error::Result;
use crate::model::analysis::*;
Expand Down
16 changes: 16 additions & 0 deletions lib/src/api/arena_tournaments.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
//! Arena tournaments: Lichess's continuous-pairing tournament format, where
//! players score points per game and climb a live leaderboard for the
//! duration of the event.
//!
//! Covers listing current tournaments, creating and updating them, joining,
//! withdrawing/pausing, terminating, managing team battles, and reading back
//! standings, results, team standings, and games. Creating or modifying a
//! tournament ([`create_arena_tournament`](LichessApi::create_arena_tournament),
//! [`update_arena_tournament`](LichessApi::update_arena_tournament),
//! [`join_arena_tournament`](LichessApi::join_arena_tournament),
//! [`withdraw_from_arena_tournament`](LichessApi::withdraw_from_arena_tournament),
//! [`terminate_arena_tournament`](LichessApi::terminate_arena_tournament), and
//! [`update_arena_team_battle`](LichessApi::update_arena_team_battle)) requires
//! a bearer token with the `tournament:write` scope; reading tournament info,
//! results, team standings, and games is public and needs no token.

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
13 changes: 13 additions & 0 deletions lib/src/api/board.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
//! The Board API: play games as if from a physical board or other external
//! device, rather than the normal Lichess UI.
//!
//! Covers making moves, offering or claiming draws, resigning, berserking,
//! seeking a game, and chatting, plus the event and game-state streams needed
//! to drive a game in real time. All methods here require a bearer token with
//! the `board:play` scope.
//!
//! [`LichessApi::board_stream_incoming_events`] and
//! [`LichessApi::board_stream_board_state`] return streams of events rather
//! than a single response: keep the connection open and read from the stream
//! as moves and other updates happen, rather than polling.

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
14 changes: 14 additions & 0 deletions lib/src/api/bot.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
//! Play games as a Lichess [Bot account](https://lichess.org/api#tag/Bot).
//!
//! A regular player account must first be upgraded to a Bot account with
//! [`bot_upgrade_account`](crate::client::LichessApi::bot_upgrade_account) —
//! irreversible, and only possible before the account has played any game.
//! Once upgraded, a bot streams incoming challenges and game state and reacts
//! to them (moves, resignations, draw/takeback offers, chat) rather than
//! using the normal web UI; see the [board](crate::api::board) module for the
//! equivalent flow for human-driven clients.
//!
//! All methods here require a bearer token with the `bot:play` scope, except
//! [`bot_get_online`](crate::client::LichessApi::bot_get_online), which is
//! public.

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
20 changes: 20 additions & 0 deletions lib/src/api/broadcasts.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
//! Broadcasts: Lichess's live relays of over-the-board tournaments, made up
//! of one tournament containing one or more rounds, each fed by an external
//! PGN source.
//!
//! Reading broadcasts (getting a tournament, round, player, team standings,
//! listing/searching/browsing top and official broadcasts, and exporting PGN)
//! is public and needs no token. Creating or managing your own broadcasts —
//! [`create_broadcast_tournament`](LichessApi::create_broadcast_tournament),
//! [`update_broadcast_tournament`](LichessApi::update_broadcast_tournament),
//! [`create_broadcast_round`](LichessApi::create_broadcast_round),
//! [`update_broadcast_round`](LichessApi::update_broadcast_round),
//! [`push_broadcast_round_pgn`](LichessApi::push_broadcast_round_pgn), and
//! [`reset_broadcast_round`](LichessApi::reset_broadcast_round) — requires a
//! bearer token with the `study:write` scope.
//!
//! The `stream_*_pgn` methods keep the connection open and yield PGN as
//! games progress, so they return a `Stream` rather than a single value;
//! `export_*_pgn` methods stream the same way but close once the current
//! games have been sent.

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
12 changes: 12 additions & 0 deletions lib/src/api/bulk_pairings.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
//! Bulk pairings let a broadcaster or tournament organizer schedule many
//! games between paired players at once, up to a week in advance, rather than
//! creating challenges one by one.
//!
//! Creating a pairing ([`LichessApi::create_bulk_pairing`]) requires an OAuth
//! token with the `challenge:bulk` scope for the caller, plus a
//! `challenge:write` token for each player being paired. Once created, a
//! pairing can be looked up, canceled before it fires, or have its clocks
//! started immediately instead of waiting for the scheduled time.
//!
//! [`LichessApi::create_bulk_pairing`]: crate::client::LichessApi::create_bulk_pairing

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
11 changes: 11 additions & 0 deletions lib/src/api/challenges.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
//! Challenge other players, bots, or the Lichess AI to a game.
//!
//! Covers listing your incoming and outgoing challenges, creating, accepting,
//! declining, and canceling a challenge, creating an open challenge anyone can
//! join, and starting a game against the Lichess AI. Most operations require a
//! bearer token with a `challenge:*` scope; open challenges and public reads
//! are the exceptions. [`LichessApi::admin_challenge_tokens`] is restricted to
//! Lichess administrators.
//!
//! Request/response types live in [`crate::model::challenges`].

use crate::client::LichessApi;
use crate::error::Result;
use crate::model::challenges::*;
Expand Down
18 changes: 18 additions & 0 deletions lib/src/api/external_engine.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
//! Register and use an external engine: a chess engine running on the user's
//! own machine, made available for cloud analysis (e.g. from the Lichess
//! analysis board) via a provider/secret handshake.
//!
//! Listing, creating, fetching, updating, and deleting engine registrations
//! ([`list_external_engines`](LichessApi::list_external_engines),
//! [`create_external_engine`](LichessApi::create_external_engine),
//! [`get_external_engine`](LichessApi::get_external_engine),
//! [`update_external_engine`](LichessApi::update_external_engine),
//! [`delete_external_engine`](LichessApi::delete_external_engine)) require a
//! bearer token with the `engine:read` or `engine:write` scope and talk to
//! the regular Lichess host. Requesting and providing analysis
//! ([`analyse_with_external_engine`](LichessApi::analyse_with_external_engine),
//! [`acquire_analysis_request`](LichessApi::acquire_analysis_request),
//! [`submit_analysis`](LichessApi::submit_analysis)) instead use the engine's
//! own client/provider secrets for auth and are served from a separate host,
//! [`Domain::Engine`](crate::model::Domain::Engine).

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
8 changes: 8 additions & 0 deletions lib/src/api/fide.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
//! Look up FIDE-rated players and their rating history.
//!
//! Search by name with [`LichessApi::search_fide_player`], fetch a single
//! [`Player`] by FIDE ID with [`LichessApi::get_fide_player`], and get their
//! historical standard, rapid, and blitz ratings with
//! [`LichessApi::get_fide_player_ratings`]. This data is public and does not
//! require a token.

use crate::client::LichessApi;
use crate::error::Result;
use crate::model::fide::*;
Expand Down
14 changes: 14 additions & 0 deletions lib/src/api/games.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
//! Fetching, exporting, streaming, and importing games.
//!
//! Games can be exported as [`GameJson`] (single game or user history) or as
//! raw PGN text, and requests for many games at once return a stream of
//! results rather than a single value, since the response can be very large.
//! [`stream_games_of_users`](LichessApi::stream_games_of_users) and
//! [`stream_games_by_ids`](LichessApi::stream_games_by_ids) instead stream
//! [`GameStream`] events for games as they start and finish, in real time.
//!
//! Most exports work without a token, but return more detail when
//! authenticated, and downloading your own games is rate limited more
//! generously than anonymous or third-party requests. Importing a game and
//! bookmarking a game both require an authenticated user.

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
5 changes: 5 additions & 0 deletions lib/src/api/messaging.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! Sending private messages to other Lichess players.
//!
//! [`LichessApi::send_message`] posts a message to a user's inbox, on behalf
//! of the authenticated account. It requires the `msg:write` OAuth scope.

use crate::client::LichessApi;
use crate::error::Result;
use crate::model::messaging::*;
Expand Down
9 changes: 9 additions & 0 deletions lib/src/api/oauth.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
//! Inspect and revoke OAuth2 tokens, and exchange an authorization code for
//! an access token.
//!
//! This module covers the token-facing half of the OAuth2 PKCE flow. For
//! generating the authorization URL and completing the flow end to end, see
//! [`crate::model::oauth::authorize::AuthorizationUrl`] and
//! [`crate::model::oauth::PendingAuthorization`], which both carry a full
//! walkthrough.

use crate::client::LichessApi;
use crate::error::Result;
use crate::model::oauth::*;
Expand Down
9 changes: 9 additions & 0 deletions lib/src/api/openings.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
//! Query move statistics for a position from the Opening Explorer: aggregated
//! master games ([`openings_masters`](LichessApi::openings_masters)), rated
//! Lichess games ([`openings_lichess`](LichessApi::openings_lichess)), or a
//! specific player's games ([`openings_player`](LichessApi::openings_player)),
//! plus fetching a masters game's PGN by ID
//! ([`openings_otb`](LichessApi::openings_otb)). All of these are public and
//! need no token, and are served from a separate host,
//! [`Domain::Explorer`](crate::model::Domain::Explorer).

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
14 changes: 14 additions & 0 deletions lib/src/api/puzzles.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
//! Fetching puzzles, tracking puzzle progress, and puzzle racing.
//!
//! Covers the daily puzzle, fetching a puzzle by ID or a random next puzzle,
//! batches of puzzles for offline play, puzzle activity and the puzzle
//! dashboard, puzzles to replay for a theme, and the Puzzle Storm dashboard.
//! Also covers creating and joining a puzzle race and fetching its results.
//!
//! The daily puzzle, puzzle-by-ID, and Storm dashboard lookups are public.
//! Everything else needs a bearer token: reading activity, the dashboard,
//! replays, and fetching puzzles requires a `puzzle:read` scope, solving a
//! batch requires `puzzle:write`, and creating a race requires `racer:write`.
//!
//! Request/response types live in [`crate::model::puzzles`].

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
7 changes: 7 additions & 0 deletions lib/src/api/relations.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
//! Follow, unfollow, and block other Lichess players.
//!
//! [`LichessApi::get_following`] streams the users the authenticated account
//! follows; the request/response types live in [`crate::model::relations`].
//! All operations here act on behalf of the authenticated user and require
//! the `follow:read` or `follow:write` OAuth scope, as appropriate.

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
8 changes: 8 additions & 0 deletions lib/src/api/simuls.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
//! Simultaneous exhibitions: one host playing many opponents at once.
//!
//! Lists recently created, started, and finished simuls, matching what's shown
//! on <https://lichess.org/simul>. The created/finished lists are not
//! exhaustive — only simuls with a strong enough host are included. This
//! endpoint is public, but when called with a bearer token the pending list is
//! populated with the caller's own created-but-unstarted simuls.

use crate::client::LichessApi;
use crate::error::Result;
use crate::model::simuls::*;
Expand Down
16 changes: 16 additions & 0 deletions lib/src/api/studies.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
//! Create, import into, and export [studies](https://lichess.org/study) and
//! their chapters.
//!
//! Studies can be exported as PGN, either a single chapter, a whole study, or
//! every study belonging to a user; [`update_study_chapter_moves`] and
//! [`update_study_chapter_tags`] edit an existing chapter's move tree and PGN
//! tags in place. See [`model::studies`] for the request/response types.
//!
//! Reading a study you don't own only returns it if it's public. Pass a
//! bearer token to also see your own private and unlisted studies; writes
//! (creating, importing, deleting, or editing a chapter) always require one.
//!
//! [`update_study_chapter_moves`]: LichessApi::update_study_chapter_moves
//! [`update_study_chapter_tags`]: LichessApi::update_study_chapter_tags
//! [`model::studies`]: crate::model::studies

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
10 changes: 10 additions & 0 deletions lib/src/api/swiss_tournaments.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
//! Swiss-system tournaments.
//!
//! Unlike arena tournaments, Swiss tournaments are always organized by a team
//! ([`LichessApi::create_swiss_tournament`] takes a `team_id`), run over a
//! fixed number of rounds, and pair players based on score each round rather
//! than continuously. Most write operations (creating, updating, joining,
//! scheduling the next round, terminating, withdrawing) require the
//! `tournament:write` scope; reading tournament info, results, games, and the
//! TRF export are public.

use futures::stream::StreamExt;

use crate::client::LichessApi;
Expand Down
10 changes: 10 additions & 0 deletions lib/src/api/tablebase.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
//! Look up Syzygy endgame tablebase results for positions with few pieces
//! remaining, one method per variant: standard chess
//! ([`lookup_standard`](LichessApi::lookup_standard)), antichess
//! ([`lookup_antichess`](LichessApi::lookup_antichess)), and atomic chess
//! ([`lookup_atomic`](LichessApi::lookup_atomic)). Each returns the win/loss/draw
//! category and, where known, distance-to-zero and distance-to-mate for the
//! position and for every legal move. These endpoints are public and need no
//! token, and are served from a separate host,
//! [`Domain::Tablebase`](crate::model::Domain::Tablebase).

use crate::client::LichessApi;
use crate::error::Result;
use crate::model::tablebase::*;
Expand Down
Loading
Loading