diff --git a/lib/grammers-client/examples/downloader.rs b/lib/grammers-client/examples/downloader.rs
index ac326414..b098d361 100644
--- a/lib/grammers-client/examples/downloader.rs
+++ b/lib/grammers-client/examples/downloader.rs
@@ -25,7 +25,7 @@ use tokio::runtime;
 
 use grammers_client::session::Session;
 use grammers_client::types::Media::{Contact, Document, Photo, Sticker};
-use grammers_client::types::*;
+use grammers_client::types::{Downloadable, Media};
 
 type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
 
diff --git a/lib/grammers-client/examples/echo.rs b/lib/grammers-client/examples/echo.rs
index 4ad186e6..bc7b9ea3 100644
--- a/lib/grammers-client/examples/echo.rs
+++ b/lib/grammers-client/examples/echo.rs
@@ -71,24 +71,17 @@ async fn async_main() -> Result {
     // This code uses `select` on Ctrl+C to gracefully stop the client and have a chance to
     // save the session. You could have fancier logic to save the session if you wanted to
     // (or even save it on every update). Or you could also ignore Ctrl+C and just use
-    // `let update = client.next_update().await?`.
+    // `while let Some(updates) =  client.next_updates().await?`.
     //
     // Using `tokio::select!` would be a lot cleaner but add a heavy dependency,
     // so a manual `select` is used instead by pinning async blocks by hand.
     loop {
-        let update = {
-            let exit = pin!(async { tokio::signal::ctrl_c().await });
-            let upd = pin!(async { client.next_update().await });
+        let exit = pin!(async { tokio::signal::ctrl_c().await });
+        let upd = pin!(async { client.next_update().await });
 
-            match select(exit, upd).await {
-                Either::Left(_) => None,
-                Either::Right((u, _)) => Some(u),
-            }
-        };
-
-        let update = match update {
-            None => break,
-            Some(u) => u?,
+        let update = match select(exit, upd).await {
+            Either::Left(_) => break,
+            Either::Right((u, _)) => u?,
         };
 
         let handle = client.clone();
diff --git a/lib/grammers-client/examples/inline-pagination.rs b/lib/grammers-client/examples/inline-pagination.rs
index a173be6a..bba622d4 100644
--- a/lib/grammers-client/examples/inline-pagination.rs
+++ b/lib/grammers-client/examples/inline-pagination.rs
@@ -22,10 +22,12 @@
 //! how much data a button's payload can contain, and to keep it simple, we're storing it inline
 //! in decimal, so the numbers can't get too large).
 
+use futures_util::future::{select, Either};
 use grammers_client::session::Session;
 use grammers_client::{button, reply_markup, Client, Config, InputMessage, Update};
 use simple_logger::SimpleLogger;
 use std::env;
+use std::pin::pin;
 use tokio::{runtime, task};
 
 type Result = std::result::Result<(), Box<dyn std::error::Error>>;
@@ -132,26 +134,23 @@ async fn async_main() -> Result {
 
     println!("Waiting for messages...");
     loop {
-        tokio::select! {
+        let exit = pin!(async { tokio::signal::ctrl_c().await });
+        let upd = pin!(async { client.next_update().await });
 
-            // A way to exit the loop
-            _ = tokio::signal::ctrl_c() => {
+        let update = match select(exit, upd).await {
+            Either::Left(_) => {
                 println!("Exiting...");
-                break
-            },
-
-            res = client.next_update() => {
-                let update = res?;
-
-                let handle = client.clone();
-                task::spawn(async move {
-                    match handle_update(handle, update).await {
-                        Ok(_) => {}
-                        Err(e) => eprintln!("Error handling updates!: {e}"),
-                    }
-                });
+                break;
             }
-        }
+            Either::Right((u, _)) => u?,
+        };
+
+        let handle = client.clone();
+        task::spawn(async move {
+            if let Err(e) = handle_update(handle, update).await {
+                eprintln!("Error handling updates!: {e}")
+            }
+        });
     }
 
     println!("Saving session file...");
diff --git a/lib/grammers-client/src/client/bots.rs b/lib/grammers-client/src/client/bots.rs
index 44033604..170c20b9 100644
--- a/lib/grammers-client/src/client/bots.rs
+++ b/lib/grammers-client/src/client/bots.rs
@@ -161,15 +161,18 @@ impl Client {
         let message: InputMessage = input_message.into();
         let entities = parse_mention_entities(self, message.entities);
         let result = self
-            .invoke(&tl::functions::messages::EditInlineBotMessage {
-                id: message_id,
-                message: Some(message.text),
-                media: message.media,
-                entities,
-                no_webpage: !message.link_preview,
-                reply_markup: message.reply_markup,
-                invert_media: false,
-            })
+            .invoke_in_dc(
+                &tl::functions::messages::EditInlineBotMessage {
+                    id: message_id.clone(),
+                    message: Some(message.text),
+                    media: message.media,
+                    entities,
+                    no_webpage: !message.link_preview,
+                    reply_markup: message.reply_markup,
+                    invert_media: message.invert_media,
+                },
+                message_id.dc_id(),
+            )
             .await?;
         Ok(result)
     }
diff --git a/lib/grammers-client/src/client/messages.rs b/lib/grammers-client/src/client/messages.rs
index f99d7262..dd11ac01 100644
--- a/lib/grammers-client/src/client/messages.rs
+++ b/lib/grammers-client/src/client/messages.rs
@@ -505,7 +505,7 @@ impl Client {
                 send_as: None,
                 noforwards: false,
                 update_stickersets_order: false,
-                invert_media: false,
+                invert_media: message.invert_media,
                 quick_reply_shortcut: None,
                 effect: None,
             })
@@ -536,7 +536,7 @@ impl Client {
                 send_as: None,
                 noforwards: false,
                 update_stickersets_order: false,
-                invert_media: false,
+                invert_media: message.invert_media,
                 quick_reply_shortcut: None,
                 effect: None,
             })
@@ -583,7 +583,7 @@ impl Client {
         let entities = parse_mention_entities(self, new_message.entities);
         self.invoke(&tl::functions::messages::EditMessage {
             no_webpage: !new_message.link_preview,
-            invert_media: false,
+            invert_media: new_message.invert_media,
             peer: chat.into().to_input_peer(),
             id: message_id,
             message: Some(new_message.text),
diff --git a/lib/grammers-client/src/client/updates.rs b/lib/grammers-client/src/client/updates.rs
index f4cc3665..c6c8ff43 100644
--- a/lib/grammers-client/src/client/updates.rs
+++ b/lib/grammers-client/src/client/updates.rs
@@ -72,7 +72,7 @@ impl Client {
     ///
     /// ```
     ///
-    /// P.S. To receive updateBotInlineSend, go to [@BotFather](https://t.me/BotFather), select your bot and click "Bot Settings", then "Inline Feedback" and select probability.
+    /// P.S. If you don't receive updateBotInlineSend, go to [@BotFather](https://t.me/BotFather), select your bot and click "Bot Settings", then "Inline Feedback" and select probability.
     ///
     pub async fn next_raw_update(
         &self,
@@ -181,18 +181,12 @@ impl Client {
                 continue;
             }
 
-            let step = {
-                let sleep = pin!(async { sleep_until(deadline.into()).await });
-                let step = pin!(async { self.step().await });
+            let sleep = pin!(async { sleep_until(deadline.into()).await });
+            let step = pin!(async { self.step().await });
 
-                match select(sleep, step).await {
-                    Either::Left(_) => None,
-                    Either::Right((step, _)) => Some(step),
-                }
-            };
-
-            if let Some(step) = step {
-                step?;
+            match select(sleep, step).await {
+                Either::Left(_) => {}
+                Either::Right((step, _)) => step?,
             }
         }
     }
diff --git a/lib/grammers-client/src/parsers/html.rs b/lib/grammers-client/src/parsers/html.rs
index 220d6cd4..aa38f0c9 100644
--- a/lib/grammers-client/src/parsers/html.rs
+++ b/lib/grammers-client/src/parsers/html.rs
@@ -125,7 +125,7 @@ pub fn parse_html_message(message: &str) -> (String, Vec<tl::enums::MessageEntit
                                 tl::types::MessageEntityMentionName {
                                     offset,
                                     length,
-                                    user_id: user_id,
+                                    user_id,
                                 }
                                 .into(),
                             );
@@ -134,7 +134,7 @@ pub fn parse_html_message(message: &str) -> (String, Vec<tl::enums::MessageEntit
                                 tl::types::MessageEntityTextUrl {
                                     offset,
                                     length,
-                                    url: url,
+                                    url,
                                 }
                                 .into(),
                             );
diff --git a/lib/grammers-client/src/parsers/markdown.rs b/lib/grammers-client/src/parsers/markdown.rs
index ec946dd7..5e5c3671 100644
--- a/lib/grammers-client/src/parsers/markdown.rs
+++ b/lib/grammers-client/src/parsers/markdown.rs
@@ -59,7 +59,7 @@ pub fn parse_markdown_message(message: &str) -> (String, Vec<tl::enums::MessageE
                     tl::types::MessageEntityMentionName {
                         offset,
                         length,
-                        user_id: user_id,
+                        user_id,
                     }
                     .into(),
                 );
diff --git a/lib/grammers-client/src/types/inline.rs b/lib/grammers-client/src/types/inline.rs
new file mode 100644
index 00000000..51311a5a
--- /dev/null
+++ b/lib/grammers-client/src/types/inline.rs
@@ -0,0 +1,10 @@
+// Copyright 2020 - developers of the `grammers` project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod query;
+pub mod send;
diff --git a/lib/grammers-client/src/types/inline_query.rs b/lib/grammers-client/src/types/inline/query.rs
similarity index 92%
rename from lib/grammers-client/src/types/inline_query.rs
rename to lib/grammers-client/src/types/inline/query.rs
index 788efaef..e1dccbd0 100644
--- a/lib/grammers-client/src/types/inline_query.rs
+++ b/lib/grammers-client/src/types/inline/query.rs
@@ -5,7 +5,8 @@
 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-use super::{Chat, ChatMap, User};
+
+use super::super::{Chat, ChatMap, User};
 use crate::{client::Client, utils::generate_random_id, InputMessage};
 use grammers_mtsender::InvocationError;
 use grammers_tl_types as tl;
@@ -52,7 +53,7 @@ impl InlineQuery {
         }
     }
 
-    // User that sent the query.
+    ///	User that sent the query
     pub fn sender(&self) -> &User {
         match self
             .chats
@@ -69,12 +70,12 @@ impl InlineQuery {
         }
     }
 
-    // The text of the inline query.
+    /// The text of the inline query.
     pub fn text(&self) -> &str {
         self.raw.query.as_str()
     }
 
-    // The offset of the inline query.
+    /// The offset of the inline query.
     pub fn offset(&self) -> &str {
         self.raw.offset.as_str()
     }
@@ -96,6 +97,16 @@ impl InlineQuery {
             client: self.client.clone(),
         }
     }
+
+    /// Type of the chat from which the inline query was sent.
+    pub fn peer_type(&self) -> Option<tl::enums::InlineQueryPeerType> {
+        self.raw.peer_type.clone()
+    }
+
+    /// Query ID
+    pub fn query_id(&self) -> i64 {
+        self.raw.query_id
+    }
 }
 
 impl Answer {
@@ -217,7 +228,7 @@ impl From<Article> for InlineResult {
                 send_message: tl::enums::InputBotInlineMessage::Text(
                     tl::types::InputBotInlineMessageText {
                         no_webpage: !article.input_message.link_preview,
-                        invert_media: false,
+                        invert_media: article.input_message.invert_media,
                         message: article.input_message.text,
                         entities: Some(article.input_message.entities),
                         reply_markup: article.input_message.reply_markup,
@@ -232,7 +243,9 @@ impl fmt::Debug for InlineQuery {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("InlineQuery")
             .field("text", &self.text())
+            .field("peer_type", &self.peer_type())
             .field("sender", &self.sender())
+            .field("query_id", &self.query_id())
             .finish()
     }
 }
diff --git a/lib/grammers-client/src/types/inline/send.rs b/lib/grammers-client/src/types/inline/send.rs
new file mode 100644
index 00000000..34d93f5b
--- /dev/null
+++ b/lib/grammers-client/src/types/inline/send.rs
@@ -0,0 +1,99 @@
+// Copyright 2020 - developers of the `grammers` project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::types::{Chat, User};
+use crate::{ChatMap, Client, InputMessage};
+use grammers_mtsender::InvocationError;
+use grammers_tl_types as tl;
+use std::fmt;
+use std::sync::Arc;
+
+#[derive(Clone)]
+pub struct InlineSend {
+    raw: tl::types::UpdateBotInlineSend,
+    client: Client,
+    chats: Arc<ChatMap>,
+}
+
+impl InlineSend {
+    pub fn from_raw(
+        query: tl::types::UpdateBotInlineSend,
+        client: &Client,
+        chats: &Arc<ChatMap>,
+    ) -> Self {
+        Self {
+            raw: query,
+            client: client.clone(),
+            chats: chats.clone(),
+        }
+    }
+
+    /// The query that was used to obtain the result.
+    pub fn text(&self) -> &str {
+        self.raw.query.as_str()
+    }
+
+    /// The user that chose the result.
+    pub fn sender(&self) -> &User {
+        match self
+            .chats
+            .get(
+                &tl::types::PeerUser {
+                    user_id: self.raw.user_id,
+                }
+                .into(),
+            )
+            .unwrap()
+        {
+            Chat::User(user) => user,
+            _ => unreachable!(),
+        }
+    }
+
+    /// The unique identifier for the result that was chosen
+    pub fn result_id(&self) -> &str {
+        self.raw.id.as_str()
+    }
+
+    /// Identifier of sent inline message.
+    /// Available only if there is an inline keyboard attached.
+    /// Will be also received in callback queries and can be used to edit the message.
+    pub fn msg_id(&self) -> Option<tl::enums::InputBotInlineMessageId> {
+        self.raw.msg_id.clone()
+    }
+
+    /// Edits this inline message.
+    ///
+    /// **This method will return Ok(None) if message id is None (e.g. if an inline keyboard is not attached)**
+    pub async fn edit_msg(
+        &self,
+        input_message: impl Into<InputMessage>,
+    ) -> Result<Option<bool>, InvocationError> {
+        let msg_id = match self.raw.msg_id.clone() {
+            None => return Ok(None),
+            Some(msg_id) => msg_id,
+        };
+
+        Ok(Some(
+            self.client
+                .edit_inline_message(msg_id, input_message)
+                .await?,
+        ))
+    }
+}
+
+impl fmt::Debug for InlineSend {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("InlineSend")
+            .field("text", &self.text())
+            .field("sender", &self.sender())
+            .field("result_id", &self.result_id())
+            .field("msg_id", &self.msg_id())
+            .finish()
+    }
+}
diff --git a/lib/grammers-client/src/types/input_message.rs b/lib/grammers-client/src/types/input_message.rs
index 79e0cf1f..9677f07e 100644
--- a/lib/grammers-client/src/types/input_message.rs
+++ b/lib/grammers-client/src/types/input_message.rs
@@ -19,6 +19,7 @@ pub struct InputMessage {
     pub(crate) background: bool,
     pub(crate) clear_draft: bool,
     pub(crate) entities: Vec<tl::enums::MessageEntity>,
+    pub(crate) invert_media: bool,
     pub(crate) link_preview: bool,
     pub(crate) reply_markup: Option<tl::enums::ReplyMarkup>,
     pub(crate) reply_to: Option<i32>,
@@ -51,6 +52,14 @@ impl InputMessage {
         self
     }
 
+    /// Whether the media will be inverted.
+    ///
+    /// If inverted, photos, videos, and documents will appear at the bottom and link previews at the top of the message.
+    pub fn invert_media(mut self, invert_media: bool) -> Self {
+        self.invert_media = invert_media;
+        self
+    }
+
     /// Whether the link preview be shown for the message.
     ///
     /// This has no effect when sending media, which cannot contain a link preview.
diff --git a/lib/grammers-client/src/types/message.rs b/lib/grammers-client/src/types/message.rs
index 200cb1ea..fc4afc3c 100644
--- a/lib/grammers-client/src/types/message.rs
+++ b/lib/grammers-client/src/types/message.rs
@@ -39,14 +39,14 @@ pub struct Message {
     // server response contains a lot of chats, and some might be related to deep layers of
     // a message action for instance. Keeping the entire set like this allows for cheaper clones
     // and moves, and saves us from worrying about picking out all the chats we care about.
-    pub(crate) chats: Arc<types::ChatMap>,
+    pub(crate) chats: Arc<ChatMap>,
 }
 
 impl Message {
     pub fn from_raw(
         client: &Client,
         message: tl::enums::Message,
-        chats: &Arc<types::ChatMap>,
+        chats: &Arc<ChatMap>,
     ) -> Option<Self> {
         match message {
             // Don't even bother to expose empty messages to the user, even if they have an ID.
diff --git a/lib/grammers-client/src/types/mod.rs b/lib/grammers-client/src/types/mod.rs
index f84cbd78..2ab9f77e 100644
--- a/lib/grammers-client/src/types/mod.rs
+++ b/lib/grammers-client/src/types/mod.rs
@@ -18,7 +18,7 @@ pub mod chat_map;
 pub mod chats;
 pub mod dialog;
 pub mod downloadable;
-pub mod inline_query;
+pub mod inline;
 pub mod input_message;
 pub mod iter_buffer;
 pub mod login_token;
@@ -41,7 +41,8 @@ pub(crate) use chat_map::Peer;
 pub use chats::{AdminRightsBuilder, BannedRightsBuilder};
 pub use dialog::Dialog;
 pub use downloadable::{ChatPhoto, Downloadable, UserProfilePhoto};
-pub use inline_query::InlineQuery;
+pub use inline::query::InlineQuery;
+pub use inline::send::InlineSend;
 pub use input_message::InputMessage;
 pub use iter_buffer::IterBuffer;
 pub use login_token::LoginToken;
diff --git a/lib/grammers-client/src/types/update.rs b/lib/grammers-client/src/types/update.rs
index 93fe5efc..596b14e9 100644
--- a/lib/grammers-client/src/types/update.rs
+++ b/lib/grammers-client/src/types/update.rs
@@ -5,12 +5,12 @@
 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-use std::sync::Arc;
 
-use grammers_tl_types as tl;
+use std::sync::Arc;
 
-use super::{CallbackQuery, ChatMap, InlineQuery, Message};
+use super::{inline::send::InlineSend, CallbackQuery, ChatMap, InlineQuery, Message};
 use crate::{types::MessageDeletion, Client};
+use grammers_tl_types as tl;
 
 #[non_exhaustive]
 #[derive(Debug, Clone)]
@@ -27,6 +27,8 @@ pub enum Update {
     /// Occurs whenever you sign in as a bot and a user sends an inline query
     /// such as `@bot query`.
     InlineQuery(InlineQuery),
+    /// Occurs whenever you sign in as a bot and a user chooses result from an inline query answer.
+    InlineSend(InlineSend),
     /// Raw events are not actual events.
     /// Instead, they are the raw Update object that Telegram sends. You
     /// normally shouldn’t need these.
@@ -84,6 +86,11 @@ impl Update {
                 InlineQuery::from_raw(client, query, chats),
             )),
 
+            // InlineSend
+            tl::enums::Update::BotInlineSend(query) => {
+                Some(Self::InlineSend(InlineSend::from_raw(query, client, chats)))
+            }
+
             // Raw
             update => Some(Self::Raw(update)),
         }