diff --git a/README.md b/README.md
index 218ec6aa..cd2367c7 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
-> WARNING: this library is still in active development under v0.1.0, use it at your own risk!
-
teloxide
@@ -16,3 +14,231 @@
A full-featured framework that empowers you to easily build [Telegram bots](https://telegram.org/blog/bot-revolution) using the [`async`/`.await`](https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html) syntax in [Rust](https://www.rust-lang.org/). It handles all the difficult stuff so you can focus only on your business logic.
+
+## Features
+ - **Type-safe.** teloxide leverages the Rust's type system with two serious implications: resistance to human mistakes and tight integration with IDEs. Write fast, avoid debugging as possible.
+
+ - **Persistency.** By default, teloxide stores all user dialogues in RAM, but you can store them somewhere else (for example, in DB) just by implementing 2 functions.
+
+ - **Convenient dialogues system.** Define a type-safe [finite automaton](https://en.wikipedia.org/wiki/Finite-state_machine)
+ and transition functions to drive a user dialogue with ease (see the examples below).
+
+ - **Convenient API.** Automatic conversions are used to avoid boilerplate. For example, functions accept `Into`, rather than `&str` or `String`, so you can call them without `.to_string()`/`.as_str()`/etc.
+
+## Getting started
+ 1. Create a new bot using [@Botfather](https://t.me/botfather) to get a token in the format `123456789:blablabla`.
+ 2. Initialise the `TELOXIDE_TOKEN` environmental variable to your token:
+```bash
+# Unix
+$ export TELOXIDE_TOKEN=MyAwesomeToken
+
+# Windows
+$ set TELOXITE_TOKEN=MyAwesomeToken
+```
+ 3. Be sure that you are up to date:
+```bash
+$ rustup update stable
+```
+
+ 4. Execute `cargo new my_bot`, enter the directory and put these lines into your `Cargo.toml`:
+```toml
+[dependencies]
+teloxide = "0.1.0"
+log = "0.4.8"
+tokio = "0.2.11"
+pretty_env_logger = "0.4.0"
+```
+
+## The ping-pong bot
+This bot has a single message handler, which answers "pong" to each incoming message:
+
+([Full](https://github.com/teloxide/teloxide/blob/dev/examples/ping_pong_bot/src/main.rs))
+```rust
+use teloxide::prelude::*;
+
+#[tokio::main]
+async fn main() {
+ teloxide::enable_logging!();
+ log::info!("Starting the ping-pong bot!");
+
+ let bot = Bot::from_env();
+
+ Dispatcher::::new(bot)
+ .message_handler(&|ctx: DispatcherHandlerCtx| async move {
+ ctx.answer("pong").send().await?;
+ Ok(())
+ })
+ .dispatch()
+ .await;
+}
+```
+
+## Commands
+Commands are defined similar to how we define CLI using [structopt](https://docs.rs/structopt/0.3.9/structopt/). This bot says "I am a cat! Meow!" on `/meow`, generates a random number within [0; 1) on `/generate`, and shows the usage guide on `/help`:
+
+([Full](https://github.com/teloxide/teloxide/blob/dev/examples/simple_commands_bot/src/main.rs))
+```rust
+// Imports are omitted...
+
+#[derive(BotCommand)]
+#[command(rename = "lowercase", description = "These commands are supported:")]
+enum Command {
+ #[command(description = "display this text.")]
+ Help,
+ #[command(description = "be a cat.")]
+ Meow,
+ #[command(description = "generate a random number within [0; 1).")]
+ Generate,
+}
+
+async fn handle_command(
+ ctx: DispatcherHandlerCtx,
+) -> Result<(), RequestError> {
+ let text = match ctx.update.text() {
+ Some(text) => text,
+ None => {
+ log::info!("Received a message, but not text.");
+ return Ok(());
+ }
+ };
+
+ let command = match Command::parse(text) {
+ Some((command, _)) => command,
+ None => {
+ log::info!("Received a text message, but not a command.");
+ return Ok(());
+ }
+ };
+
+ match command {
+ Command::Help => ctx.answer(Command::descriptions()).send().await?,
+ Command::Generate => {
+ ctx.answer(thread_rng().gen_range(0.0, 1.0).to_string())
+ .send()
+ .await?
+ }
+ Command::Meow => ctx.answer("I am a cat! Meow!").send().await?,
+ };
+
+ Ok(())
+}
+
+#[tokio::main]
+async fn main() {
+ // Setup is omitted...
+}
+
+```
+
+## Guess a number
+Wanna see more? This is a bot, which starts a game on each incoming message. You must guess a number from 1 to 10 (inclusively):
+
+([Full](https://github.com/teloxide/teloxide/blob/dev/examples/guess_a_number_bot/src/main.rs))
+```rust
+// Imports are omitted...
+
+#[derive(SmartDefault)]
+enum Dialogue {
+ #[default]
+ Start,
+ ReceiveAttempt(u8),
+}
+
+async fn handle_message(
+ ctx: DialogueHandlerCtx,
+) -> Result, RequestError> {
+ match ctx.dialogue {
+ Dialogue::Start => {
+ ctx.answer(
+ "Let's play a game! Guess a number from 1 to 10 (inclusively).",
+ )
+ .send()
+ .await?;
+ next(Dialogue::ReceiveAttempt(thread_rng().gen_range(1, 11)))
+ }
+ Dialogue::ReceiveAttempt(secret) => match ctx.update.text() {
+ None => {
+ ctx.answer("Oh, please, send me a text message!")
+ .send()
+ .await?;
+ next(ctx.dialogue)
+ }
+ Some(text) => match text.parse::() {
+ Ok(attempt) => match attempt {
+ x if !(1..=10).contains(&x) => {
+ ctx.answer(
+ "Oh, please, send me a number in the range [1; \
+ 10]!",
+ )
+ .send()
+ .await?;
+ next(ctx.dialogue)
+ }
+ x if x == secret => {
+ ctx.answer("Congratulations! You won!").send().await?;
+ exit()
+ }
+ _ => {
+ ctx.answer("No.").send().await?;
+ next(ctx.dialogue)
+ }
+ },
+ Err(_) => {
+ ctx.answer(
+ "Oh, please, send me a number in the range [1; 10]!",
+ )
+ .send()
+ .await?;
+ next(ctx.dialogue)
+ }
+ },
+ },
+ }
+}
+
+#[tokio::main]
+async fn main() {
+ // Setup is omitted...
+
+ Dispatcher::new(bot)
+ .message_handler(&DialogueDispatcher::new(|ctx| async move {
+ handle_message(ctx)
+ .await
+ .expect("Something wrong with the bot!")
+ }))
+ .dispatch()
+ .await;
+}
+```
+
+Our [finite automaton](https://en.wikipedia.org/wiki/Finite-state_machine), designating a user dialogue, cannot be in an invalid state. See [examples/dialogue_bot](https://github.com/teloxide/teloxide/blob/dev/examples/dialogue_bot/src/main.rs) to see a bit more complicated bot with dialogues.
+
+[See more examples](https://github.com/teloxide/teloxide/tree/dev/examples).
+
+## Recommendations
+ - Use this pattern:
+
+ ```rust
+ #[tokio::main]
+ async fn main() {
+ run().await;
+ }
+
+ async fn run() {
+ // Your logic here...
+ }
+ ```
+
+ Instead of this:
+
+ ```rust
+#[tokio::main]
+ async fn main() {
+ // Your logic here...
+ }
+ ```
+
+The second one produces very strange compiler messages because of the `#[tokio::main]` macro. However, the examples in this README use the second variant for brevity.
+
+## Contributing
+See [CONRIBUTING.md](https://github.com/teloxide/teloxide/blob/dev/CONTRIBUTING.md).