diff --git a/Cargo.toml b/Cargo.toml
index c4ac9602..d921bb1b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,4 +22,5 @@ async-trait = "0.1.22"
 futures = "0.3.1"
 pin-project = "0.4.6"
 serde_with_macros = "1.0.1"
-either = "1.5.3"
\ No newline at end of file
+either = "1.5.3"
+mime = "0.3.16"
\ No newline at end of file
diff --git a/src/dispatching/dispatchers/filter.rs b/src/dispatching/dispatchers/filter.rs
index 7c993a1a..5124d6a3 100644
--- a/src/dispatching/dispatchers/filter.rs
+++ b/src/dispatching/dispatchers/filter.rs
@@ -31,10 +31,11 @@ type FiltersWithHandlers<'a, T, E> = Vec<FilterWithHandler<'a, T, E>>;
 /// use std::convert::Infallible;
 /// use teloxide::{dispatching::FilterDispatcher, RequestError};
 ///
-/// let _ =
-///     FilterDispatcher::new(|err: Either<RequestError, Infallible>| async {
+/// let _ = FilterDispatcher::new(|err: Either<RequestError, Infallible>| {
+///     async {
 ///         dbg!(err);
-///     });
+///     }
+/// });
 /// ```
 ///
 /// Or you can do it even simpler by providing the built-in error handler
@@ -83,9 +84,11 @@ type FiltersWithHandlers<'a, T, E> = Vec<FilterWithHandler<'a, T, E>>;
 /// // error handler that just ignores all errors (that can't ever happen).
 /// let mut dp = FilterDispatcher::<Infallible, _>::new(|_| async {})
 ///     // Add a handler, which handles all messages sent to the bot.
-///     .message_handler(true, |mes: Message| async move {
-///         println!("New message: {:?}", mes);
-///         Ok(())
+///     .message_handler(true, |mes: Message| {
+///         async move {
+///             println!("New message: {:?}", mes);
+///             Ok(())
+///         }
 ///     })
 ///     // Add a handler, which handles all messages edited in a chat
 ///     // with the bot.
diff --git a/src/network/download.rs b/src/network/download.rs
index 05f08f5d..0e68414f 100644
--- a/src/network/download.rs
+++ b/src/network/download.rs
@@ -39,11 +39,13 @@ pub async fn download_file_stream(
         .await?
         .error_for_status()?;
 
-    Ok(futures::stream::unfold(res, |mut res| async {
-        match res.chunk().await {
-            Err(err) => Some((Err(err), res)),
-            Ok(Some(c)) => Some((Ok(c), res)),
-            Ok(None) => None,
+    Ok(futures::stream::unfold(res, |mut res| {
+        async {
+            match res.chunk().await {
+                Err(err) => Some((Err(err), res)),
+                Ok(Some(c)) => Some((Ok(c), res)),
+                Ok(None) => None,
+            }
         }
     }))
 }
diff --git a/src/types/animation.rs b/src/types/animation.rs
index f589c589..92d7e9e6 100644
--- a/src/types/animation.rs
+++ b/src/types/animation.rs
@@ -1,6 +1,6 @@
 use serde::{Deserialize, Serialize};
 
-use crate::types::PhotoSize;
+use crate::types::{MimeWrapper, PhotoSize};
 
 /// This object represents an animation file (GIF or H.264/MPEG-4 AVC video
 /// without sound).
@@ -33,7 +33,7 @@ pub struct Animation {
     pub file_name: Option<String>,
 
     /// A MIME type of the file as defined by a sender.
-    pub mime_type: Option<String>,
+    pub mime_type: Option<MimeWrapper>,
 
     /// A size of a file.
     pub file_size: Option<u32>,
@@ -59,7 +59,7 @@ mod tests {
             "file_size":3452
         },
         "file_name":"some",
-        "mime_type":"gif",
+        "mime_type":"video/gif",
         "file_size":6500}"#;
         let expected = Animation {
             file_id: "id".to_string(),
@@ -75,7 +75,9 @@ mod tests {
                 file_size: Some(3452),
             }),
             file_name: Some("some".to_string()),
-            mime_type: Some("gif".to_string()),
+            mime_type: Some(MimeWrapper {
+                mime: "video/gif".parse().unwrap(),
+            }),
             file_size: Some(6500),
         };
         let actual = serde_json::from_str::<Animation>(json).unwrap();
diff --git a/src/types/mod.rs b/src/types/mod.rs
index 651271e5..8baca877 100644
--- a/src/types/mod.rs
+++ b/src/types/mod.rs
@@ -171,3 +171,6 @@ mod encrypted_credentials;
 mod encrypted_passport_element;
 mod passport_data;
 mod passport_file;
+
+pub use non_telegram_types::*;
+mod non_telegram_types;
diff --git a/src/types/non_telegram_types/country_code.rs b/src/types/non_telegram_types/country_code.rs
new file mode 100644
index 00000000..4f7705ac
--- /dev/null
+++ b/src/types/non_telegram_types/country_code.rs
@@ -0,0 +1,254 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
+pub enum CountryCode {
+    AD,
+    AE,
+    AF,
+    AG,
+    AI,
+    AL,
+    AM,
+    AO,
+    AQ,
+    AR,
+    AS,
+    AT,
+    AU,
+    AW,
+    AX,
+    AZ,
+    BA,
+    BB,
+    BD,
+    BE,
+    BF,
+    BG,
+    BH,
+    BI,
+    BJ,
+    BL,
+    BM,
+    BN,
+    BO,
+    BQ,
+    BR,
+    BS,
+    BT,
+    BV,
+    BW,
+    BY,
+    BZ,
+    CA,
+    CC,
+    CD,
+    CF,
+    CG,
+    CH,
+    CI,
+    CK,
+    CL,
+    CM,
+    CN,
+    CO,
+    CR,
+    CU,
+    CV,
+    CW,
+    CX,
+    CY,
+    CZ,
+    DE,
+    DJ,
+    DK,
+    DM,
+    DO,
+    DZ,
+    EC,
+    EE,
+    EG,
+    EH,
+    ER,
+    ES,
+    ET,
+    FI,
+    FJ,
+    FK,
+    FM,
+    FO,
+    FR,
+    GA,
+    GB,
+    GD,
+    GE,
+    GF,
+    GG,
+    GH,
+    GI,
+    GL,
+    GM,
+    GN,
+    GP,
+    GQ,
+    GR,
+    GS,
+    GT,
+    GU,
+    GW,
+    GY,
+    HK,
+    HM,
+    HN,
+    HR,
+    HT,
+    HU,
+    ID,
+    IE,
+    IL,
+    IM,
+    IN,
+    IO,
+    IQ,
+    IR,
+    IS,
+    IT,
+    JE,
+    JM,
+    JO,
+    JP,
+    KE,
+    KG,
+    KH,
+    KI,
+    KM,
+    KN,
+    KP,
+    KR,
+    KW,
+    KY,
+    KZ,
+    LA,
+    LB,
+    LC,
+    LI,
+    LK,
+    LR,
+    LS,
+    LT,
+    LU,
+    LV,
+    LY,
+    MA,
+    MC,
+    MD,
+    ME,
+    MF,
+    MG,
+    MH,
+    MK,
+    ML,
+    MM,
+    MN,
+    MO,
+    MP,
+    MQ,
+    MR,
+    MS,
+    MT,
+    MU,
+    MV,
+    MW,
+    MX,
+    MY,
+    MZ,
+    NA,
+    NC,
+    NE,
+    NF,
+    NG,
+    NI,
+    NL,
+    NO,
+    NP,
+    NR,
+    NU,
+    NZ,
+    OM,
+    PA,
+    PE,
+    PF,
+    PG,
+    PH,
+    PK,
+    PL,
+    PM,
+    PN,
+    PR,
+    PS,
+    PT,
+    PW,
+    PY,
+    QA,
+    RE,
+    RO,
+    RS,
+    RU,
+    RW,
+    SA,
+    SB,
+    SC,
+    SD,
+    SE,
+    SG,
+    SH,
+    SI,
+    SJ,
+    SK,
+    SL,
+    SM,
+    SN,
+    SO,
+    SR,
+    SS,
+    ST,
+    SV,
+    SX,
+    SY,
+    SZ,
+    TC,
+    TD,
+    TF,
+    TG,
+    TH,
+    TJ,
+    TK,
+    TL,
+    TM,
+    TN,
+    TO,
+    TR,
+    TT,
+    TV,
+    TW,
+    TZ,
+    UA,
+    UG,
+    UM,
+    US,
+    UY,
+    UZ,
+    VA,
+    VC,
+    VE,
+    VG,
+    VI,
+    VN,
+    VU,
+    WF,
+    WS,
+    YE,
+    YT,
+    ZA,
+    ZM,
+    ZW,
+}
diff --git a/src/types/non_telegram_types/currency.rs b/src/types/non_telegram_types/currency.rs
new file mode 100644
index 00000000..0cdebce6
--- /dev/null
+++ b/src/types/non_telegram_types/currency.rs
@@ -0,0 +1,89 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
+pub enum Currency {
+    AED,
+    AFN,
+    ALL,
+    AMD,
+    ARS,
+    AUD,
+    AZN,
+    BAM,
+    BDT,
+    BGN,
+    BND,
+    BOB,
+    BRL,
+    CAD,
+    CHF,
+    CLP,
+    CNY,
+    COP,
+    CRC,
+    CZK,
+    DKK,
+    DOP,
+    DZD,
+    EGP,
+    EUR,
+    GBP,
+    GEL,
+    GTQ,
+    HKD,
+    HNL,
+    HRK,
+    HUF,
+    IDR,
+    ILS,
+    INR,
+    ISK,
+    JMD,
+    JPY,
+    KES,
+    KGS,
+    KRW,
+    KZT,
+    LBP,
+    LKR,
+    MAD,
+    MDL,
+    MNT,
+    MUR,
+    MVR,
+    MXN,
+    MYR,
+    MZN,
+    NGN,
+    NIO,
+    NOK,
+    NPR,
+    NZD,
+    PAB,
+    PEN,
+    PHP,
+    PKR,
+    PLN,
+    PYG,
+    QAR,
+    RON,
+    RSD,
+    RUB,
+    SAR,
+    SEK,
+    SGD,
+    THB,
+    TJS,
+    TRY,
+    TTD,
+    TWD,
+    TZS,
+    UAH,
+    UGX,
+    USD,
+    UYU,
+    UZS,
+    VND,
+    YER,
+    ZAR,
+}
diff --git a/src/types/non_telegram_types/language_code.rs b/src/types/non_telegram_types/language_code.rs
new file mode 100644
index 00000000..1837db6e
--- /dev/null
+++ b/src/types/non_telegram_types/language_code.rs
@@ -0,0 +1,190 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum LanguageCode {
+    AA,
+    AB,
+    AE,
+    AF,
+    AK,
+    AM,
+    AN,
+    AR,
+    AS,
+    AV,
+    AY,
+    AZ,
+    BA,
+    BE,
+    BG,
+    BH,
+    BI,
+    BM,
+    BN,
+    BO,
+    BR,
+    BS,
+    CA,
+    CE,
+    CH,
+    CO,
+    CR,
+    CS,
+    CU,
+    CV,
+    CY,
+    DA,
+    DE,
+    DV,
+    DZ,
+    EE,
+    EL,
+    EN,
+    EO,
+    ES,
+    ET,
+    EU,
+    FA,
+    FF,
+    FI,
+    FJ,
+    FO,
+    FR,
+    FY,
+    GA,
+    GD,
+    GL,
+    GN,
+    GU,
+    GV,
+    HA,
+    HE,
+    HI,
+    HO,
+    HR,
+    HT,
+    HU,
+    HY,
+    HZ,
+    IA,
+    ID,
+    IE,
+    IG,
+    II,
+    IK,
+    IO,
+    IS,
+    IT,
+    IU,
+    JA,
+    JV,
+    KA,
+    KG,
+    KI,
+    KJ,
+    KK,
+    KL,
+    KM,
+    KN,
+    KO,
+    KR,
+    KS,
+    KU,
+    KV,
+    KW,
+    KY,
+    LA,
+    LB,
+    LG,
+    LI,
+    LN,
+    LO,
+    LT,
+    LU,
+    LV,
+    MG,
+    MH,
+    MI,
+    MK,
+    ML,
+    MN,
+    MR,
+    MS,
+    MT,
+    MY,
+    NA,
+    NB,
+    ND,
+    NE,
+    NG,
+    NL,
+    NN,
+    NO,
+    NR,
+    NV,
+    NY,
+    OC,
+    OJ,
+    OM,
+    OR,
+    OS,
+    PA,
+    PI,
+    PL,
+    PS,
+    PT,
+    QU,
+    RM,
+    RN,
+    RO,
+    RU,
+    RW,
+    SA,
+    SC,
+    SD,
+    SE,
+    SG,
+    SI,
+    SK,
+    SL,
+    SM,
+    SN,
+    SO,
+    SQ,
+    SR,
+    SS,
+    ST,
+    SU,
+    SV,
+    SW,
+    TA,
+    TE,
+    TG,
+    TH,
+    TI,
+    TK,
+    TL,
+    TN,
+    TO,
+    TR,
+    TS,
+    TT,
+    TW,
+    TY,
+    UG,
+    UK,
+    UR,
+    UZ,
+    VE,
+    VI,
+    VO,
+    WA,
+    WO,
+    XH,
+    YI,
+    YO,
+    ZA,
+    ZH,
+    ZU,
+}
diff --git a/src/types/non_telegram_types/mime_wrapper.rs b/src/types/non_telegram_types/mime_wrapper.rs
new file mode 100644
index 00000000..20222e1c
--- /dev/null
+++ b/src/types/non_telegram_types/mime_wrapper.rs
@@ -0,0 +1,56 @@
+use derive_more::From;
+use mime::Mime;
+use serde::{
+    de::Visitor, export::Formatter, Deserialize, Deserializer, Serialize,
+    Serializer,
+};
+
+#[derive(Clone, Debug, Eq, Hash, PartialEq, From)]
+pub struct MimeWrapper {
+    pub mime: Mime,
+}
+
+impl Serialize for MimeWrapper {
+    fn serialize<S>(
+        &self,
+        serializer: S,
+    ) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
+    where
+        S: Serializer,
+    {
+        serializer.serialize_str(self.mime.as_ref())
+    }
+}
+
+struct MimeVisitor;
+impl<'a> Visitor<'a> for MimeVisitor {
+    type Value = MimeWrapper;
+
+    fn expecting(
+        &self,
+        formatter: &mut Formatter<'_>,
+    ) -> Result<(), serde::export::fmt::Error> {
+        formatter.write_str("mime type")
+    }
+
+    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+    where
+        E: serde::de::Error,
+    {
+        match v.parse::<Mime>() {
+            Ok(mime_type) => Ok(MimeWrapper { mime: mime_type }),
+            Err(e) => Err(E::custom(e)),
+        }
+    }
+}
+
+impl<'de> Deserialize<'de> for MimeWrapper {
+    fn deserialize<D>(
+        deserializer: D,
+    ) -> Result<Self, <D as Deserializer<'de>>::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        deserializer.deserialize_str(MimeVisitor)
+    }
+}
diff --git a/src/types/non_telegram_types/mod.rs b/src/types/non_telegram_types/mod.rs
new file mode 100644
index 00000000..2202122b
--- /dev/null
+++ b/src/types/non_telegram_types/mod.rs
@@ -0,0 +1,9 @@
+pub use country_code::*;
+pub use currency::*;
+pub use language_code::*;
+pub use mime_wrapper::*;
+
+mod country_code;
+mod currency;
+mod language_code;
+mod mime_wrapper;
diff --git a/src/types/pre_checkout_query.rs b/src/types/pre_checkout_query.rs
index ef668553..172e5e8f 100644
--- a/src/types/pre_checkout_query.rs
+++ b/src/types/pre_checkout_query.rs
@@ -1,6 +1,6 @@
 use serde::{Deserialize, Serialize};
 
-use crate::types::{OrderInfo, User};
+use crate::types::{Currency, OrderInfo, User};
 
 /// This object contains information about an incoming pre-checkout query.
 ///
@@ -17,7 +17,7 @@ pub struct PreCheckoutQuery {
     /// Three-letter ISO 4217 [currency] code.
     ///
     /// [currency]: https://core.telegram.org/bots/payments#supported-currencies
-    pub currency: String,
+    pub currency: Currency,
 
     /// Total price in the _smallest units_ of the currency (integer, **not**
     /// float/double). For example, for a price of `US$ 1.45` pass `amount =
diff --git a/src/types/shipping_address.rs b/src/types/shipping_address.rs
index b323bb24..478ad714 100644
--- a/src/types/shipping_address.rs
+++ b/src/types/shipping_address.rs
@@ -1,3 +1,4 @@
+use crate::types::CountryCode;
 use serde::{Deserialize, Serialize};
 
 /// This object represents a shipping address.
@@ -6,7 +7,7 @@ use serde::{Deserialize, Serialize};
 #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
 pub struct ShippingAddress {
     /// ISO 3166-1 alpha-2 country code.
-    pub country_code: String,
+    pub country_code: CountryCode,
 
     /// State, if applicable.
     pub state: String,
diff --git a/src/types/successful_payment.rs b/src/types/successful_payment.rs
index a3508bd7..d38a36b5 100644
--- a/src/types/successful_payment.rs
+++ b/src/types/successful_payment.rs
@@ -1,6 +1,6 @@
 use serde::{Deserialize, Serialize};
 
-use crate::types::OrderInfo;
+use crate::types::{Currency, OrderInfo};
 
 /// This object contains basic information about a successful payment.
 ///
@@ -11,7 +11,7 @@ pub struct SuccessfulPayment {
     /// Three-letter ISO 4217 [currency] code.
     ///
     /// [currency]: https://core.telegram.org/bots/payments#supported-currencies
-    pub currency: String,
+    pub currency: Currency,
 
     /// Total price in the smallest units of the currency (integer, not
     /// float/double). For example, for a price of `US$ 1.45` pass `amount =
diff --git a/src/types/update.rs b/src/types/update.rs
index 2777ebd2..3dfb2270 100644
--- a/src/types/update.rs
+++ b/src/types/update.rs
@@ -63,8 +63,8 @@ pub enum UpdateKind {
 #[cfg(test)]
 mod test {
     use crate::types::{
-        Chat, ChatKind, ForwardKind, MediaKind, Message, MessageKind, Sender,
-        Update, UpdateKind, User,
+        Chat, ChatKind, ForwardKind, LanguageCode, MediaKind, Message,
+        MessageKind, Sender, Update, UpdateKind, User,
     };
 
     // TODO: more tests for deserialization
@@ -114,7 +114,7 @@ mod test {
                         first_name: String::from("Waffle"),
                         last_name: None,
                         username: Some(String::from("WaffleLapkin")),
-                        language_code: Some(String::from("en")),
+                        language_code: Some(LanguageCode::EN),
                     }),
                     forward_kind: ForwardKind::Origin {
                         reply_to_message: None,
diff --git a/src/types/user.rs b/src/types/user.rs
index 52bb3b25..67086ca6 100644
--- a/src/types/user.rs
+++ b/src/types/user.rs
@@ -1,3 +1,4 @@
+use crate::types::LanguageCode;
 use serde::{Deserialize, Serialize};
 
 /// This object represents a Telegram user or bot.
@@ -24,7 +25,7 @@ pub struct User {
     /// [IETF language tag] of the user's language.
     ///
     /// [IETF language tag]: https://en.wikipedia.org/wiki/IETF_language_tag
-    pub language_code: Option<String>,
+    pub language_code: Option<LanguageCode>,
 }
 
 #[cfg(test)]
@@ -39,7 +40,7 @@ mod tests {
             "first_name":"firstName",
             "last_name":"lastName",
             "username":"Username",
-            "language_code":"languageCode"
+            "language_code":"ru"
         }"#;
         let expected = User {
             id: 12345,
@@ -47,7 +48,7 @@ mod tests {
             first_name: "firstName".to_string(),
             last_name: Some("lastName".to_string()),
             username: Some("Username".to_string()),
-            language_code: Some("languageCode".to_string()),
+            language_code: Some(LanguageCode::RU),
         };
         let actual = serde_json::from_str::<User>(&json).unwrap();
         assert_eq!(actual, expected)
diff --git a/src/utils/html.rs b/src/utils/html.rs
index a4f5a7d9..dbd91cfa 100644
--- a/src/utils/html.rs
+++ b/src/utils/html.rs
@@ -121,7 +121,8 @@ mod tests {
     fn test_link() {
         assert_eq!(
             link("https://www.google.com/?q=foo&l=ru", "<google>"),
-            "<a href=\"https://www.google.com/?q=foo&amp;l=ru\">&lt;google&gt;</a>",
+            "<a href=\"https://www.google.com/?q=foo&amp;l=ru\">&lt;google&gt;\
+             </a>",
         );
     }