Merge pull request #235 from teloxide/update-docs

Update the docs
This commit is contained in:
Temirkhan Myrzamadi 2020-07-25 01:46:37 +06:00 committed by GitHub
commit e8c58086d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 201 additions and 78 deletions

View file

@ -363,7 +363,7 @@ A: Most programming languages have their own implementations of Telegram bots fr
Q: Can I use webhooks?
A: teloxide doesn't provide special API for working with webhooks due to their nature with lots of subtle settings. Instead, you setup your webhook by yourself, as shown in [webhook_ping_pong_bot](examples/ngrok_ping_pong_bot/src/main.rs).
A: teloxide doesn't provide special API for working with webhooks due to their nature with lots of subtle settings. Instead, you setup your webhook by yourself, as shown in [`examples/ngrok_ping_pong_bot`](examples/ngrok_ping_pong_bot/src/main.rs) and [`examples/heroku_ping_pong_bot`](examples/heroku_ping_pong_bot/src/main.rs).
Associated links:
- [Marvin's Marvellous Guide to All Things Webhook](https://core.telegram.org/bots/webhooks)
@ -371,7 +371,7 @@ Associated links:
Q: Can I use different loggers?
A: Of course, you can. The [`enable_logging!`](https://docs.rs/teloxide/latest/teloxide/macro.enable_logging.html) and [`enable_logging_with_filter!`](https://docs.rs/teloxide/latest/teloxide/macro.enable_logging_with_filter.html) macros are just convenient utilities, not necessary to use them. You can setup a different logger, for example, [fern](https://crates.io/crates/fern), as usual, e.g. teloxide has no specific requirements as it depends only on [log](https://crates.io/crates/log).
A: Yes. The [`enable_logging!`](https://docs.rs/teloxide/latest/teloxide/macro.enable_logging.html) and [`enable_logging_with_filter!`](https://docs.rs/teloxide/latest/teloxide/macro.enable_logging_with_filter.html) macros are just convenient utilities, not necessary to use them. You can setup a different logger, for example, [fern](https://crates.io/crates/fern), as usual, e.g. teloxide has no specific requirements as it depends only on [log](https://crates.io/crates/log).
## Community bots
Feel free to push your own bot into our collection!

View file

@ -8,9 +8,11 @@ use std::{sync::Arc, time::Duration};
mod api;
mod download;
/// A Telegram bot used to send requests.
/// A requests sender.
///
/// No need to put `Bot` into `Arc`, because it's already in.
/// No need to put it into [`Arc`], because it's already in.
///
/// [`Arc`]: std::sync::Arc
#[derive(Debug, Clone)]
pub struct Bot {
token: Arc<str>,
@ -108,6 +110,9 @@ impl Bot {
}
}
/// A builder of [`Bot`], supporting some extra settings.
///
/// [`Bot`] crate::Bot
#[derive(Debug, Default)]
pub struct BotBuilder {
token: Option<String>,

View file

@ -1,7 +1,4 @@
use crate::{
dispatching::{dialogue::TransitionOut, UpdateWithCx},
types::Message,
};
use crate::dispatching::dialogue::{TransitionIn, TransitionOut};
use futures::future::BoxFuture;
/// Represents a dialogue FSM.
@ -9,6 +6,6 @@ pub trait BotDialogue: Default {
/// Turns itself into another state, depending on the input message.
fn dispatch(
self,
cx: UpdateWithCx<Message>,
cx: TransitionIn,
) -> BoxFuture<'static, TransitionOut<Self>>;
}

View file

@ -15,11 +15,11 @@ use std::sync::{Arc, Mutex};
/// A dispatcher of dialogues.
///
/// Note that `DialogueDispatcher` implements [`DispatcherHandler`], so you can
/// just put an instance of this dispatcher into the [`Dispatcher`]'s methods.
/// Note that it implements [`DispatcherHandler`], so you can just put an
/// instance of this dispatcher into the [`Dispatcher`]'s methods.
///
/// See [the module-level documentation for the design
/// overview](crate::dispatching::dialogue).
/// See the [module-level documentation](crate::dispatching::dialogue) for the
/// design overview.
///
/// [`Dispatcher`]: crate::dispatching::Dispatcher
/// [`DispatcherHandler`]: crate::dispatching::DispatcherHandler

View file

@ -12,8 +12,15 @@ pub enum DialogueStage<D> {
/// Returns a new dialogue state.
///
/// Note the `Dialogue: From<State>` constraint. It means that you don't need to
/// pass `Dialogue` -- you can just pass one of it's states. [`From`] can be
/// conveniently derived by [derive-more].
///
/// See [the module-level documentation for the design
/// overview](crate::dispatching::dialogue).
///
/// [`From`]: std::convert::From
/// [derive-more]: https://crates.io/crates/derive_more
pub fn next<Dialogue, State>(new_state: State) -> TransitionOut<Dialogue>
where
Dialogue: From<State>,

View file

@ -1,20 +1,19 @@
//! Dealing with dialogues.
//!
//! There are four main components:
//! There are three main components:
//!
//! 1. Your type `D` (typically an enumeration), implementing [`BotDialogue`].
//! It is essentially a [FSM]: its variants are possible dialogue states and
//! [`BotDialogue::dispatch`] is a transition function.
//!
//! 1. Your type `D`, which designates a dialogue state at the current
//! moment.
//! 2. [`Storage<D>`], which encapsulates all the dialogues.
//! 3. Your handler, which receives an update and turns your dialogue into the
//! next state ([`DialogueDispatcherHandlerCx<YourUpdate, D>`] ->
//! [`DialogueStage<D>`]).
//! 4. [`DialogueDispatcher`], which encapsulates your handler, [`Storage<D>`],
//!
//! 3. [`DialogueDispatcher`], which encapsulates your handler, [`Storage<D>`],
//! and implements [`DispatcherHandler`].
//!
//! For example, you supply [`DialogueDispatcher`] into
//! [`Dispatcher::messages_handler`]. Every time [`Dispatcher`] sees an incoming
//! [`UpdateKind::Message(message)`], `message` is transferred into
//! [`DialogueDispatcher`]. After this, following steps are executed:
//! You pass [`DialogueDispatcher`] into [`Dispatcher`]. Every time
//! [`Dispatcher`] sees an incoming input, it is transferred into
//! [`DialogueDispatcher`], and the following steps are executed:
//!
//! 1. If a storage doesn't contain a dialogue from this chat, supply
//! `D::default()` into you handler, otherwise, supply the saved dialogue
@ -23,21 +22,102 @@
//! from the storage, otherwise ([`DialogueStage::Next`]) force the storage to
//! update the dialogue.
//!
//! Please, see [examples/dialogue_bot] as an example.
//! To avoid boilerplate, teloxide exports these convenient things: the [`up!`]
//! macro, the [`next`] and [`exit`] functions, and `#[derive(BotDialogue)]`.
//! Here's how your dialogues management code skeleton should look like:
//!
//! ```no_run
//! use std::convert::Infallible;
//!
//! use teloxide::prelude::*;
//! use teloxide_macros::BotDialogue;
//!
//! struct _1State;
//! struct _2State;
//! struct _3State;
//!
//! type Out = TransitionOut<D>;
//!
//! async fn _1_transition(_cx: TransitionIn, _state: _1State) -> Out {
//! todo!()
//! }
//! async fn _2_transition(_cx: TransitionIn, _state: _2State) -> Out {
//! todo!()
//! }
//! async fn _3_transition(_cx: TransitionIn, _state: _3State) -> Out {
//! todo!()
//! }
//!
//! #[derive(BotDialogue)]
//! enum D {
//! #[transition(_1_transition)]
//! _1(_1State),
//! #[transition(_2_transition)]
//! _2(_2State),
//! #[transition(_3_transition)]
//! _3(_3State),
//! }
//!
//! impl Default for D {
//! fn default() -> Self {
//! Self::_1(_1State)
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! run().await;
//! }
//!
//! async fn run() {
//! teloxide::enable_logging!();
//! log::info!("Starting dialogue_bot!");
//!
//! let bot = Bot::from_env();
//!
//! Dispatcher::new(bot)
//! .messages_handler(DialogueDispatcher::new(
//! |input: DialogueWithCx<Message, D, Infallible>| async move {
//! // Unwrap without panic because of std::convert::Infallible.
//! input
//! .dialogue
//! .unwrap()
//! .dispatch(input.cx)
//! .await
//! .expect("Something wrong with the bot!")
//! },
//! ))
//! .dispatch()
//! .await;
//! }
//! ```
//!
//! See [examples/dialogue_bot] as a real example.
//!
//! [`BotDialogue`]: crate::dispatching::dialogue::BotDialogue
//! [`BotDialogue::dispatch`]:
//! crate::dispatching::dialogue::BotDialogue::dispatch
//! [FSM]: https://en.wikipedia.org/wiki/Finite-state_machine
//!
//! [`Storage<D>`]: crate::dispatching::dialogue::Storage
//!
//! [`DialogueStage<D>`]: crate::dispatching::dialogue::DialogueStage
//! [`DialogueDispatcher`]: crate::dispatching::dialogue::DialogueDispatcher
//!
//! [`DialogueStage::Exit`]:
//! crate::dispatching::dialogue::DialogueStage::Exit
//! [`DialogueStage::Next`]: crate::dispatching::dialogue::DialogueStage::Next
//!
//! [`up!`]: crate::up
//! [`next`]: crate::dispatching::dialogue::next
//! [`exit`]: crate::dispatching::dialogue::exit
//!
//! [`DispatcherHandler`]: crate::dispatching::DispatcherHandler
//! [`Dispatcher`]: crate::dispatching::Dispatcher
//! [`Dispatcher::messages_handler`]:
//! crate::dispatching::Dispatcher::messages_handler
//! [`UpdateKind::Message(message)`]: crate::types::UpdateKind::Message
//! [`DialogueWithCx<YourUpdate, D>`]:
//! crate::dispatching::dialogue::DialogueWithCx
//!
//! [examples/dialogue_bot]: https://github.com/teloxide/teloxide/tree/master/examples/dialogue_bot
#![allow(clippy::type_complexity)]
@ -116,5 +196,5 @@ macro_rules! up {
/// An input passed into a FSM transition function.
pub type TransitionIn = UpdateWithCx<Message>;
// A type returned from a FSM transition function.
/// A type returned from a FSM transition function.
pub type TransitionOut<D> = ResponseResult<DialogueStage<D>>;

View file

@ -1,4 +1,5 @@
/// Various serializers for memory storages.
//! Various serializers for memory storages.
use serde::{de::DeserializeOwned, ser::Serialize};
/// A serializer for memory storages.

View file

@ -48,8 +48,8 @@ fn send<'a, Upd>(
/// One dispatcher to rule them all.
///
/// See [the module-level documentation for the design
/// overview](crate::dispatching).
/// See the [module-level documentation](crate::dispatching) for the design
/// overview.
pub struct Dispatcher {
bot: Bot,

View file

@ -5,8 +5,8 @@ use futures::future::BoxFuture;
/// An asynchronous handler of a stream of updates used in [`Dispatcher`].
///
/// See [the module-level documentation for the design
/// overview](crate::dispatching).
/// See the [module-level documentation](crate::dispatching) for the design
/// overview.
///
/// [`Dispatcher`]: crate::dispatching::Dispatcher
pub trait DispatcherHandler<Upd> {

View file

@ -5,6 +5,9 @@ use futures::{stream::BoxStream, Stream, StreamExt};
/// An extension trait to be used with [`DispatcherHandlerRx`].
///
/// See the [module-level documentation](crate::dispatching) for the design
/// overview.
///
/// [`DispatcherHandlerRx`]: crate::dispatching::DispatcherHandlerRx
pub trait DispatcherHandlerRxExt {
/// Extracts only text messages from this stream of arbitrary messages.

View file

@ -1,12 +1,11 @@
//! Updates dispatching.
//!
//! The key type here is [`Dispatcher`]. It encapsulates [`Bot`] and handlers
//! for [the 11 update kinds].
//! for [all the update kinds].
//!
//! You can register a maximum of 11 handlers for [the 11 update kinds]. Every
//! handler accept [`tokio::sync::mpsc::UnboundedReceiver`] (the RX halve of an
//! asynchronous unbounded MPSC channel). Inside a body of your handler, you
//! typically asynchronously concurrently iterate through updates like this:
//! Every handler accept [`tokio::sync::mpsc::UnboundedReceiver`] (the RX halve
//! of an asynchronous channel). Inside a body of your handler, you typically
//! asynchronously concurrently iterate through updates like this:
//!
//! ```
//! use teloxide::prelude::*;
@ -29,12 +28,11 @@
//! [`tokio::sync::mpsc::UnboundedReceiver`] and return `Future<Output = ()`
//! as a handler.
//!
//! Since they implement [`DispatcherHandler`] too!
//! Since they implement [`DispatcherHandler`] too.
//!
//! # Examples
//! ### The ping-pong bot
//! This bot has a single message handler, which answers "pong" to each incoming
//! message:
//! # The ping-pong bot
//! This bot has a single handler of messages, which answers "pong" to each
//! incoming message:
//!
//! ([Full](https://github.com/teloxide/teloxide/blob/master/examples/ping_pong_bot/src/main.rs))
//! ```no_run
@ -67,7 +65,7 @@
//! [See more examples](https://github.com/teloxide/teloxide/tree/master/examples).
//!
//! [`Dispatcher`]: crate::dispatching::Dispatcher
//! [the 11 update kinds]: crate::types::UpdateKind
//! [all the update kinds]: crate::types::UpdateKind
//! [`Update`]: crate::types::Update
//! [`ErrorHandler`]: crate::dispatching::ErrorHandler
//! [`DispatcherHandler`]: crate::dispatching::DispatcherHandler

View file

@ -92,7 +92,7 @@
//! updates `0..=N`.
//!
//! # Webhooks
//! See the [README FAQ about webhooks](https://github.com/teloxide/teloxide/blob/master/README.md#can-i-use-webhooks).
//! See the [README FAQ about webhooks](https://github.com/teloxide/teloxide/blob/master/README.md#faq).
//!
//! [`UpdateListener`]: UpdateListener
//! [`polling_default`]: polling_default

View file

@ -12,8 +12,8 @@ use crate::{
/// A [`Dispatcher`]'s handler's context of a bot and an update.
///
/// See [the module-level documentation for the design
/// overview](crate::dispatching).
/// See the [module-level documentation](crate::dispatching) for the design
/// overview.
///
/// [`Dispatcher`]: crate::dispatching::Dispatcher
#[derive(Debug)]
@ -32,6 +32,7 @@ where
}
impl UpdateWithCx<Message> {
/// A shortcut for `.answer(text).send().await`.
pub async fn answer_str<T>(&self, text: T) -> ResponseResult<Message>
where
T: Into<String>,

View file

@ -3,7 +3,7 @@ use reqwest::StatusCode;
use serde::Deserialize;
use thiserror::Error;
/// An error occurred after downloading a file.
/// An error caused by downloading a file.
#[derive(Debug, Error, From)]
pub enum DownloadError {
#[error("A network error: {0}")]
@ -13,7 +13,7 @@ pub enum DownloadError {
Io(#[source] std::io::Error),
}
/// An error occurred after making a request to Telegram.
/// An error caused by sending a request to Telegram.
#[derive(Debug, Error)]
pub enum RequestError {
#[error("A Telegram's error #{status_code}: {kind:?}")]
@ -36,9 +36,13 @@ pub enum RequestError {
InvalidJson(#[source] serde_json::Error),
}
/// A kind of a API error returned from Telegram. If you receive Unknown value,
/// please [open the issue](https://github.com/teloxide/teloxide/issues/new) with description
/// of error.
/// A kind of an API error.
///
/// If you receive [`ApiErrorKind::Unknown`], please [open an issue] with
/// the description of the error.
///
/// [`ApiErrorKind::Unknown`]: crate::ApiErrorKind::Unknown
/// [open an issue]: https://github.com/teloxide/teloxide/issues/new
#[derive(Debug, Deserialize, PartialEq, Hash, Eq, Clone)]
#[serde(untagged)]
pub enum ApiErrorKind {
@ -46,7 +50,7 @@ pub enum ApiErrorKind {
Unknown(String),
}
/// A kind of a known API error returned from Telegram.
/// A kind of a known API error.
#[derive(Debug, Deserialize, PartialEq, Copy, Hash, Eq, Clone)]
pub enum KnownApiErrorKind {
/// Occurs when the bot tries to send message to user who blocked the bot.

View file

@ -17,7 +17,9 @@
#![forbid(unsafe_code)]
pub use bot::{Bot, BotBuilder};
pub use errors::{ApiErrorKind, DownloadError, RequestError};
pub use errors::{
ApiErrorKind, DownloadError, KnownApiErrorKind, RequestError,
};
mod errors;
mod net;

View file

@ -10,8 +10,11 @@ use crate::{
/// Once the user has confirmed their payment and shipping details, the Bot API
/// sends the final confirmation in the form of an [`Update`] with the field
/// `pre_checkout_query`. Use this method to respond to such pre-checkout
/// queries. Note: The Bot API must receive an answer within 10 seconds after
/// the pre-checkout query was sent.
/// queries.
///
/// # Note
/// The Bot API must receive an answer within 10 seconds after the pre-checkout
/// query was sent.
///
/// [The official docs](https://core.telegram.org/bots/api#answerprecheckoutquery).
///

View file

@ -3,8 +3,9 @@
/// [The official docs](https://core.telegram.org/bots/api#callbackgame).
use serde::{Deserialize, Serialize};
/// A placeholder, currently holds no information. Use [@Botfather] to set up
/// your game.
/// A placeholder, currently holds no information.
///
/// Use [@Botfather] to set up your game.
///
/// [@Botfather]: https://t.me/botfather
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]

View file

@ -46,7 +46,9 @@ pub enum PassportElementErrorKind {
}
/// Represents an issue in one of the data fields that was provided by the
/// user. The error is considered resolved when the field's value changes.
/// user.
///
/// The error is considered resolved when the field's value changes.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrordatafield).
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
@ -61,9 +63,10 @@ pub struct PassportElementErrorDataField {
pub data_hash: String,
}
/// Represents an issue with the front side of a document. The error is
/// considered resolved when the file with the front side of the document
/// changes.
/// Represents an issue with the front side of a document.
///
/// The error is considered resolved when the file with the front side of the
/// document changes.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorfrontside).
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
@ -76,9 +79,10 @@ pub struct PassportElementErrorFrontSide {
pub file_hash: String,
}
/// Represents an issue with the reverse side of a document. The error is
/// considered resolved when the file with reverse side of the document
/// changes.
/// Represents an issue with the reverse side of a document.
///
/// The error is considered resolved when the file with reverse side of the
/// document changes.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorreverseside).
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
@ -91,8 +95,9 @@ pub struct PassportElementErrorReverseSide {
pub file_hash: String,
}
//// Represents an issue with the selfie with a document. The error is
//// considered resolved when the file with the selfie changes.
//// Represents an issue with the selfie with a document.
//
/// The error is considered resolved when the file with the selfie changes.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorselfie).
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
@ -104,8 +109,10 @@ pub struct PassportElementErrorSelfie {
pub file_hash: String,
}
/// Represents an issue with a document scan. The error is considered
/// resolved when the file with the document scan changes.
/// Represents an issue with a document scan.
///
/// The error is considered resolved when the file with the document scan
/// changes.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorfile).
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
@ -117,8 +124,10 @@ pub struct PassportElementErrorFile {
pub file_hash: String,
}
/// Represents an issue with a list of scans. The error is considered
/// resolved when the list of files containing the scans changes.
/// Represents an issue with a list of scans.
///
/// The error is considered resolved when the list of files containing the scans
/// changes.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorfiles).
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
@ -131,8 +140,9 @@ pub struct PassportElementErrorFiles {
}
/// Represents an issue with one of the files that constitute the
/// translation of a document. The error is considered resolved when the
/// file changes.
/// translation of a document.
///
/// The error is considered resolved when the file changes.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrortranslationfile).
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
@ -145,8 +155,9 @@ pub struct PassportElementErrorTranslationFile {
pub file_hash: String,
}
/// Represents an issue with the translated version of a document. The
/// error is considered resolved when a file with the document translation
/// Represents an issue with the translated version of a document.
///
/// The error is considered resolved when a file with the document translation
/// change.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrortranslationfiles).
@ -159,8 +170,9 @@ pub struct PassportElementErrorTranslationFiles {
pub file_hashes: Vec<String>,
}
/// Represents an issue in an unspecified place. The error is considered
/// resolved when new data is added.
/// Represents an issue in an unspecified place.
///
/// The error is considered resolved when new data is added.
///
/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorunspecified).
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]

View file

@ -1,3 +1,10 @@
/// Constructs a client from the `TELOXIDE_PROXY` environmental variable.
///
/// This function passes the value of `TELOXIDE_PROXY` into
/// [`reqwest::Proxy::all`], if it exists, otherwise returns the default
/// client.
///
/// [`reqwest::Proxy::all`]: https://docs.rs/reqwest/latest/reqwest/struct.Proxy.html#method.all
pub fn client_from_env() -> reqwest::Client {
use reqwest::{Client, Proxy};

View file

@ -1,6 +1,8 @@
//! Some useful utilities.
pub mod client_from_env;
mod client_from_env;
pub mod command;
pub mod html;
pub mod markdown;
pub use client_from_env::client_from_env;