Repository: aiogram/aiogram
Pull request #1213 (2023-07-11 20:35:11)

Fixed subtypes and union types generation, new enums added
# Description

Fixed nested subtypes serialization (like InputMedia, ChatMember and others).
In due to pydantic v2 has more strictly type parsing previously generated code makes invalid schema, where subtypes without specifying union of all subtypes generates empty object

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)
- [x] Breaking change (fix or feature that would cause existing functionality to not work as expected)

# Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes


github-actions[bot]: # :x: Changelog is required!

You need to add a brief description of the changes to the `CHANGES` directory.

For example, you can run `towncrier create <issue>.<type>` to create a file in the change directory and then write a description on that file.

Read more at [Towncrier docs](https://towncrier.readthedocs.io/en/latest/quickstart.html#creating-news-fragments)
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) Report
> Merging [#1213](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) (88e6e67) into [dev-3.x](https://app.codecov.io/gh/aiogram/aiogram/commit/a7b92bb050f10606d729a764fb78881a3bbede0b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) (a7b92bb) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://app.codecov.io/gh/aiogram/aiogram/pull/1213/graphs/tree.svg?width=650&height=150&src=pr&token=cFqEr3p9MX&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram)](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram)

```diff
@@            Coverage Diff            @@
##           dev-3.x     #1213   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          361       363    +2     
  Lines         8973      8953   -20     
=========================================
- Hits          8973      8953   -20     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `100.00% <100.00%> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) | Coverage Δ | |
|---|---|---|
| [aiogram/client/bot.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9jbGllbnQvYm90LnB5) | `100.00% <ø> (ø)` | |
| [aiogram/types/chat\_member.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS90eXBlcy9jaGF0X21lbWJlci5weQ==) | `100.00% <ø> (ø)` | |
| [aiogram/types/message.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS90eXBlcy9tZXNzYWdlLnB5) | `100.00% <ø> (ø)` | |
| [aiogram/client/context\_controller.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9jbGllbnQvY29udGV4dF9jb250cm9sbGVyLnB5) | `100.00% <100.00%> (ø)` | |
| [aiogram/enums/\_\_init\_\_.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9lbnVtcy9fX2luaXRfXy5weQ==) | `100.00% <100.00%> (ø)` | |
| [aiogram/enums/encrypted\_passport\_element.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9lbnVtcy9lbmNyeXB0ZWRfcGFzc3BvcnRfZWxlbWVudC5weQ==) | `100.00% <100.00%> (ø)` | |
| [aiogram/enums/passport\_element\_error\_type.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9lbnVtcy9wYXNzcG9ydF9lbGVtZW50X2Vycm9yX3R5cGUucHk=) | `100.00% <100.00%> (ø)` | |
| [aiogram/filters/chat\_member\_updated.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9maWx0ZXJzL2NoYXRfbWVtYmVyX3VwZGF0ZWQucHk=) | `100.00% <100.00%> (ø)` | |
| [aiogram/methods/answer\_web\_app\_query.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9tZXRob2RzL2Fuc3dlcl93ZWJfYXBwX3F1ZXJ5LnB5) | `100.00% <100.00%> (ø)` | |
| [aiogram/methods/delete\_my\_commands.py](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9tZXRob2RzL2RlbGV0ZV9teV9jb21tYW5kcy5weQ==) | `100.00% <100.00%> (ø)` | |
| ... and [32 more](https://app.codecov.io/gh/aiogram/aiogram/pull/1213?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) | |


Patch:
diff --git a/.butcher/enums/EncryptedPassportElement.yml b/.butcher/enums/EncryptedPassportElement.yml
new file mode 100644
index 00000000..e0540d7f
--- /dev/null
+++ b/.butcher/enums/EncryptedPassportElement.yml
@@ -0,0 +1,10 @@
+name: EncryptedPassportElement
+description: |
+  This object represents type of encrypted passport element.
+
+  Source: https://core.telegram.org/bots/api#encryptedpassportelement
+parse:
+  entity: EncryptedPassportElement
+  category: types
+  attribute: type
+  regexp: "'([a-z_]+)'"
diff --git a/.butcher/enums/PassportElementErrorType.yml b/.butcher/enums/PassportElementErrorType.yml
new file mode 100644
index 00000000..d5d52aeb
--- /dev/null
+++ b/.butcher/enums/PassportElementErrorType.yml
@@ -0,0 +1,18 @@
+name: PassportElementErrorType
+description: |
+  This object represents a passport element error type.
+
+  Source: https://core.telegram.org/bots/api#passportelementerror
+multi_parse:
+  attribute: source
+  regexp: 'must be ([a-z_]+)'
+  entities:
+    - PassportElementErrorDataField
+    - PassportElementErrorFrontSide
+    - PassportElementErrorReverseSide
+    - PassportElementErrorSelfie
+    - PassportElementErrorFile
+    - PassportElementErrorFiles
+    - PassportElementErrorTranslationFile
+    - PassportElementErrorTranslationFiles
+    - PassportElementErrorUnspecified
diff --git a/.butcher/types/BotCommandScope/subtypes.yml b/.butcher/types/BotCommandScope/subtypes.yml
new file mode 100644
index 00000000..6756ad51
--- /dev/null
+++ b/.butcher/types/BotCommandScope/subtypes.yml
@@ -0,0 +1,1 @@
+discriminator: "type"
diff --git a/.butcher/types/BotCommandScopeAllChatAdministrators/replace.yml b/.butcher/types/BotCommandScopeAllChatAdministrators/replace.yml
deleted file mode 100644
index ddb65490..00000000
--- a/.butcher/types/BotCommandScopeAllChatAdministrators/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - BotCommandScope
diff --git a/.butcher/types/BotCommandScopeAllGroupChats/replace.yml b/.butcher/types/BotCommandScopeAllGroupChats/replace.yml
deleted file mode 100644
index ddb65490..00000000
--- a/.butcher/types/BotCommandScopeAllGroupChats/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - BotCommandScope
diff --git a/.butcher/types/BotCommandScopeAllPrivateChats/replace.yml b/.butcher/types/BotCommandScopeAllPrivateChats/replace.yml
deleted file mode 100644
index ddb65490..00000000
--- a/.butcher/types/BotCommandScopeAllPrivateChats/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - BotCommandScope
diff --git a/.butcher/types/BotCommandScopeChat/replace.yml b/.butcher/types/BotCommandScopeChat/replace.yml
deleted file mode 100644
index ddb65490..00000000
--- a/.butcher/types/BotCommandScopeChat/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - BotCommandScope
diff --git a/.butcher/types/BotCommandScopeChatAdministrators/replace.yml b/.butcher/types/BotCommandScopeChatAdministrators/replace.yml
deleted file mode 100644
index ddb65490..00000000
--- a/.butcher/types/BotCommandScopeChatAdministrators/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - BotCommandScope
diff --git a/.butcher/types/BotCommandScopeChatMember/replace.yml b/.butcher/types/BotCommandScopeChatMember/replace.yml
deleted file mode 100644
index ddb65490..00000000
--- a/.butcher/types/BotCommandScopeChatMember/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - BotCommandScope
diff --git a/.butcher/types/BotCommandScopeDefault/replace.yml b/.butcher/types/BotCommandScopeDefault/replace.yml
deleted file mode 100644
index ddb65490..00000000
--- a/.butcher/types/BotCommandScopeDefault/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - BotCommandScope
diff --git a/.butcher/types/ChatMember/extend.yml b/.butcher/types/ChatMember/extend.yml
deleted file mode 100644
index 01ef4960..00000000
--- a/.butcher/types/ChatMember/extend.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-define:
-  - type: "String"
-    description: "The member's status in the chat"
-    html_description: "<td>The member's status in the chat</td>"
-    rst_description: "The member's status in the chat"
-    name: "status"
-    required: true
-
-clone:
-  - ChatMemberOwner:
-      exclude:
-        - status
-  - ChatMemberAdministrator:
-      exclude:
-        - status
-  - ChatMemberMember:
-      exclude:
-        - status
-  - ChatMemberRestricted:
-      exclude:
-        - status
-  - ChatMemberLeft:
-      exclude:
-        - status
-  - ChatMemberBanned:
-      exclude:
-        - status
diff --git a/.butcher/types/ChatMember/subtypes.yml b/.butcher/types/ChatMember/subtypes.yml
new file mode 100644
index 00000000..95832398
--- /dev/null
+++ b/.butcher/types/ChatMember/subtypes.yml
@@ -0,0 +1,1 @@
+discriminator: "status"
diff --git a/.butcher/types/ChatMemberAdministrator/replace.yml b/.butcher/types/ChatMemberAdministrator/replace.yml
deleted file mode 100644
index 619942cd..00000000
--- a/.butcher/types/ChatMemberAdministrator/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - ChatMember
diff --git a/.butcher/types/ChatMemberBanned/replace.yml b/.butcher/types/ChatMemberBanned/replace.yml
index 6a3882af..0af85473 100644
--- a/.butcher/types/ChatMemberBanned/replace.yml
+++ b/.butcher/types/ChatMemberBanned/replace.yml
@@ -1,5 +1,3 @@
-bases:
-  - ChatMember
 annotations:
   until_date:
     parsed_type:
diff --git a/.butcher/types/ChatMemberLeft/replace.yml b/.butcher/types/ChatMemberLeft/replace.yml
deleted file mode 100644
index 619942cd..00000000
--- a/.butcher/types/ChatMemberLeft/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - ChatMember
diff --git a/.butcher/types/ChatMemberMember/replace.yml b/.butcher/types/ChatMemberMember/replace.yml
deleted file mode 100644
index 619942cd..00000000
--- a/.butcher/types/ChatMemberMember/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - ChatMember
diff --git a/.butcher/types/ChatMemberOwner/replace.yml b/.butcher/types/ChatMemberOwner/replace.yml
deleted file mode 100644
index 619942cd..00000000
--- a/.butcher/types/ChatMemberOwner/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - ChatMember
diff --git a/.butcher/types/ChatMemberRestricted/replace.yml b/.butcher/types/ChatMemberRestricted/replace.yml
index 6a3882af..0af85473 100644
--- a/.butcher/types/ChatMemberRestricted/replace.yml
+++ b/.butcher/types/ChatMemberRestricted/replace.yml
@@ -1,5 +1,3 @@
-bases:
-  - ChatMember
 annotations:
   until_date:
     parsed_type:
diff --git a/.butcher/types/ChatMemberUpdated/replace.yml b/.butcher/types/ChatMemberUpdated/replace.yml
index 66c1b64c..9a3a2842 100644
--- a/.butcher/types/ChatMemberUpdated/replace.yml
+++ b/.butcher/types/ChatMemberUpdated/replace.yml
@@ -3,32 +3,3 @@ annotations:
     parsed_type:
       type: std
       name: datetime.datetime
-  old_chat_member: &chat-member-type
-    parsed_type:
-      type: union
-      items:
-        - type: entity
-          references:
-            category: types
-            name: ChatMemberOwner
-        - type: entity
-          references:
-            category: types
-            name: ChatMemberAdministrator
-        - type: entity
-          references:
-            category: types
-            name: ChatMemberMember
-        - type: entity
-          references:
-            category: types
-            name: ChatMemberRestricted
-        - type: entity
-          references:
-            category: types
-            name: ChatMemberLeft
-        - type: entity
-          references:
-            category: types
-            name: ChatMemberBanned
-  new_chat_member: *chat-member-type
diff --git a/.butcher/types/InlineQueryResult/subtypes.yml b/.butcher/types/InlineQueryResult/subtypes.yml
new file mode 100644
index 00000000..6756ad51
--- /dev/null
+++ b/.butcher/types/InlineQueryResult/subtypes.yml
@@ -0,0 +1,1 @@
+discriminator: "type"
diff --git a/.butcher/types/InlineQueryResultArticle/replace.yml b/.butcher/types/InlineQueryResultArticle/replace.yml
deleted file mode 100644
index cbe6bc26..00000000
--- a/.butcher/types/InlineQueryResultArticle/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InlineQueryResult
diff --git a/.butcher/types/InlineQueryResultAudio/replace.yml b/.butcher/types/InlineQueryResultAudio/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultAudio/replace.yml
+++ b/.butcher/types/InlineQueryResultAudio/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultCachedAudio/replace.yml b/.butcher/types/InlineQueryResultCachedAudio/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultCachedAudio/replace.yml
+++ b/.butcher/types/InlineQueryResultCachedAudio/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultCachedDocument/replace.yml b/.butcher/types/InlineQueryResultCachedDocument/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultCachedDocument/replace.yml
+++ b/.butcher/types/InlineQueryResultCachedDocument/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultCachedGif/replace.yml b/.butcher/types/InlineQueryResultCachedGif/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultCachedGif/replace.yml
+++ b/.butcher/types/InlineQueryResultCachedGif/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultCachedMpeg4Gif/replace.yml b/.butcher/types/InlineQueryResultCachedMpeg4Gif/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultCachedMpeg4Gif/replace.yml
+++ b/.butcher/types/InlineQueryResultCachedMpeg4Gif/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultCachedPhoto/replace.yml b/.butcher/types/InlineQueryResultCachedPhoto/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultCachedPhoto/replace.yml
+++ b/.butcher/types/InlineQueryResultCachedPhoto/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultCachedSticker/replace.yml b/.butcher/types/InlineQueryResultCachedSticker/replace.yml
deleted file mode 100644
index cbe6bc26..00000000
--- a/.butcher/types/InlineQueryResultCachedSticker/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InlineQueryResult
diff --git a/.butcher/types/InlineQueryResultCachedVideo/replace.yml b/.butcher/types/InlineQueryResultCachedVideo/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultCachedVideo/replace.yml
+++ b/.butcher/types/InlineQueryResultCachedVideo/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultCachedVoice/replace.yml b/.butcher/types/InlineQueryResultCachedVoice/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultCachedVoice/replace.yml
+++ b/.butcher/types/InlineQueryResultCachedVoice/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultContact/replace.yml b/.butcher/types/InlineQueryResultContact/replace.yml
deleted file mode 100644
index cbe6bc26..00000000
--- a/.butcher/types/InlineQueryResultContact/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InlineQueryResult
diff --git a/.butcher/types/InlineQueryResultDocument/replace.yml b/.butcher/types/InlineQueryResultDocument/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultDocument/replace.yml
+++ b/.butcher/types/InlineQueryResultDocument/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultGame/replace.yml b/.butcher/types/InlineQueryResultGame/replace.yml
deleted file mode 100644
index cbe6bc26..00000000
--- a/.butcher/types/InlineQueryResultGame/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InlineQueryResult
diff --git a/.butcher/types/InlineQueryResultGif/replace.yml b/.butcher/types/InlineQueryResultGif/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultGif/replace.yml
+++ b/.butcher/types/InlineQueryResultGif/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultLocation/replace.yml b/.butcher/types/InlineQueryResultLocation/replace.yml
deleted file mode 100644
index cbe6bc26..00000000
--- a/.butcher/types/InlineQueryResultLocation/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InlineQueryResult
diff --git a/.butcher/types/InlineQueryResultMpeg4Gif/replace.yml b/.butcher/types/InlineQueryResultMpeg4Gif/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultMpeg4Gif/replace.yml
+++ b/.butcher/types/InlineQueryResultMpeg4Gif/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultPhoto/replace.yml b/.butcher/types/InlineQueryResultPhoto/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultPhoto/replace.yml
+++ b/.butcher/types/InlineQueryResultPhoto/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultVenue/replace.yml b/.butcher/types/InlineQueryResultVenue/replace.yml
deleted file mode 100644
index cbe6bc26..00000000
--- a/.butcher/types/InlineQueryResultVenue/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InlineQueryResult
diff --git a/.butcher/types/InlineQueryResultVideo/replace.yml b/.butcher/types/InlineQueryResultVideo/replace.yml
index cd89306d..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultVideo/replace.yml
+++ b/.butcher/types/InlineQueryResultVideo/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InlineQueryResult
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InlineQueryResultVoice/replace.yml b/.butcher/types/InlineQueryResultVoice/replace.yml
index 6c32c60f..e87fb9b3 100644
--- a/.butcher/types/InlineQueryResultVoice/replace.yml
+++ b/.butcher/types/InlineQueryResultVoice/replace.yml
@@ -1,5 +1,3 @@
-bases:
-  - InlineQueryResult
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InputContactMessageContent/replace.yml b/.butcher/types/InputContactMessageContent/replace.yml
deleted file mode 100644
index 29166299..00000000
--- a/.butcher/types/InputContactMessageContent/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InputMessageContent
diff --git a/.butcher/types/InputInvoiceMessageContent/replace.yml b/.butcher/types/InputInvoiceMessageContent/replace.yml
deleted file mode 100644
index 29166299..00000000
--- a/.butcher/types/InputInvoiceMessageContent/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InputMessageContent
diff --git a/.butcher/types/InputLocationMessageContent/replace.yml b/.butcher/types/InputLocationMessageContent/replace.yml
deleted file mode 100644
index 29166299..00000000
--- a/.butcher/types/InputLocationMessageContent/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InputMessageContent
diff --git a/.butcher/types/InputMedia/subtypes.yml b/.butcher/types/InputMedia/subtypes.yml
new file mode 100644
index 00000000..6756ad51
--- /dev/null
+++ b/.butcher/types/InputMedia/subtypes.yml
@@ -0,0 +1,1 @@
+discriminator: "type"
diff --git a/.butcher/types/InputMediaAnimation/replace.yml b/.butcher/types/InputMediaAnimation/replace.yml
index a2756429..be3f441b 100644
--- a/.butcher/types/InputMediaAnimation/replace.yml
+++ b/.butcher/types/InputMediaAnimation/replace.yml
@@ -1,5 +1,3 @@
-bases:
-  - InputMedia
 annotations:
   media:
     parsed_type:
diff --git a/.butcher/types/InputMediaAudio/replace.yml b/.butcher/types/InputMediaAudio/replace.yml
index a2756429..be3f441b 100644
--- a/.butcher/types/InputMediaAudio/replace.yml
+++ b/.butcher/types/InputMediaAudio/replace.yml
@@ -1,5 +1,3 @@
-bases:
-  - InputMedia
 annotations:
   media:
     parsed_type:
diff --git a/.butcher/types/InputMediaDocument/replace.yml b/.butcher/types/InputMediaDocument/replace.yml
index a2756429..be3f441b 100644
--- a/.butcher/types/InputMediaDocument/replace.yml
+++ b/.butcher/types/InputMediaDocument/replace.yml
@@ -1,5 +1,3 @@
-bases:
-  - InputMedia
 annotations:
   media:
     parsed_type:
diff --git a/.butcher/types/InputMediaPhoto/replace.yml b/.butcher/types/InputMediaPhoto/replace.yml
index a2756429..be3f441b 100644
--- a/.butcher/types/InputMediaPhoto/replace.yml
+++ b/.butcher/types/InputMediaPhoto/replace.yml
@@ -1,5 +1,3 @@
-bases:
-  - InputMedia
 annotations:
   media:
     parsed_type:
diff --git a/.butcher/types/InputMediaVideo/replace.yml b/.butcher/types/InputMediaVideo/replace.yml
index a2756429..be3f441b 100644
--- a/.butcher/types/InputMediaVideo/replace.yml
+++ b/.butcher/types/InputMediaVideo/replace.yml
@@ -1,5 +1,3 @@
-bases:
-  - InputMedia
 annotations:
   media:
     parsed_type:
diff --git a/.butcher/types/InputMessageContent/subtypes.yml b/.butcher/types/InputMessageContent/subtypes.yml
new file mode 100644
index 00000000..ffcd4415
--- /dev/null
+++ b/.butcher/types/InputMessageContent/subtypes.yml
@@ -0,0 +1,1 @@
+{ }
diff --git a/.butcher/types/InputTextMessageContent/replace.yml b/.butcher/types/InputTextMessageContent/replace.yml
index 63741e83..ebc1d7e9 100644
--- a/.butcher/types/InputTextMessageContent/replace.yml
+++ b/.butcher/types/InputTextMessageContent/replace.yml
@@ -1,6 +1,3 @@
-bases:
-  - InputMessageContent
-
 annotations:
   parse_mode:
     value: UNSET_PARSE_MODE
diff --git a/.butcher/types/InputVenueMessageContent/replace.yml b/.butcher/types/InputVenueMessageContent/replace.yml
deleted file mode 100644
index 29166299..00000000
--- a/.butcher/types/InputVenueMessageContent/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - InputMessageContent
diff --git a/.butcher/types/MenuButton/subtypes.yml b/.butcher/types/MenuButton/subtypes.yml
new file mode 100644
index 00000000..6756ad51
--- /dev/null
+++ b/.butcher/types/MenuButton/subtypes.yml
@@ -0,0 +1,1 @@
+discriminator: "type"
diff --git a/.butcher/types/MenuButtonCommands/replace.yml b/.butcher/types/MenuButtonCommands/replace.yml
deleted file mode 100644
index cc566462..00000000
--- a/.butcher/types/MenuButtonCommands/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - MenuButton
diff --git a/.butcher/types/MenuButtonDefault/replace.yml b/.butcher/types/MenuButtonDefault/replace.yml
deleted file mode 100644
index cc566462..00000000
--- a/.butcher/types/MenuButtonDefault/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - MenuButton
diff --git a/.butcher/types/MenuButtonWebApp/replace.yml b/.butcher/types/MenuButtonWebApp/replace.yml
deleted file mode 100644
index cc566462..00000000
--- a/.butcher/types/MenuButtonWebApp/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - MenuButton
diff --git a/.butcher/types/PassportElementError/subtypes.yml b/.butcher/types/PassportElementError/subtypes.yml
new file mode 100644
index 00000000..fd3f58ea
--- /dev/null
+++ b/.butcher/types/PassportElementError/subtypes.yml
@@ -0,0 +1,1 @@
+discriminator: "source"
diff --git a/.butcher/types/PassportElementErrorDataField/replace.yml b/.butcher/types/PassportElementErrorDataField/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorDataField/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/.butcher/types/PassportElementErrorFile/replace.yml b/.butcher/types/PassportElementErrorFile/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorFile/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/.butcher/types/PassportElementErrorFiles/replace.yml b/.butcher/types/PassportElementErrorFiles/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorFiles/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/.butcher/types/PassportElementErrorFrontSide/replace.yml b/.butcher/types/PassportElementErrorFrontSide/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorFrontSide/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/.butcher/types/PassportElementErrorReverseSide/replace.yml b/.butcher/types/PassportElementErrorReverseSide/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorReverseSide/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/.butcher/types/PassportElementErrorSelfie/replace.yml b/.butcher/types/PassportElementErrorSelfie/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorSelfie/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/.butcher/types/PassportElementErrorTranslationFile/replace.yml b/.butcher/types/PassportElementErrorTranslationFile/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorTranslationFile/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/.butcher/types/PassportElementErrorTranslationFiles/replace.yml b/.butcher/types/PassportElementErrorTranslationFiles/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorTranslationFiles/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/.butcher/types/PassportElementErrorUnspecified/replace.yml b/.butcher/types/PassportElementErrorUnspecified/replace.yml
deleted file mode 100644
index 105b390f..00000000
--- a/.butcher/types/PassportElementErrorUnspecified/replace.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bases:
-  - PassportElementError
diff --git a/CHANGES/1213.bugfix.rst b/CHANGES/1213.bugfix.rst
new file mode 100644
index 00000000..a9787889
--- /dev/null
+++ b/CHANGES/1213.bugfix.rst
@@ -0,0 +1,7 @@
+Fixed the serialization error associated with nested subtypes
+like InputMedia, ChatMember, etc.
+
+The previously generated code resulted in an invalid schema under pydantic v2,
+which has stricter type parsing.
+Hence, subtypes without the specification of all subtype unions were generating
+an empty object. This has been rectified now.
diff --git a/aiogram/client/bot.py b/aiogram/client/bot.py
index a5258eaa..b7604390 100644
--- a/aiogram/client/bot.py
+++ b/aiogram/client/bot.py
@@ -141,6 +141,13 @@ from ..types import (
     UNSET_PARSE_MODE,
     BotCommand,
     BotCommandScope,
+    BotCommandScopeAllChatAdministrators,
+    BotCommandScopeAllGroupChats,
+    BotCommandScopeAllPrivateChats,
+    BotCommandScopeChat,
+    BotCommandScopeChatAdministrators,
+    BotCommandScopeChatMember,
+    BotCommandScopeDefault,
     BotDescription,
     BotName,
     BotShortDescription,
@@ -161,9 +168,30 @@ from ..types import (
     GameHighScore,
     InlineKeyboardMarkup,
     InlineQueryResult,
+    InlineQueryResultArticle,
+    InlineQueryResultAudio,
+    InlineQueryResultCachedAudio,
+    InlineQueryResultCachedDocument,
+    InlineQueryResultCachedGif,
+    InlineQueryResultCachedMpeg4Gif,
+    InlineQueryResultCachedPhoto,
+    InlineQueryResultCachedSticker,
+    InlineQueryResultCachedVideo,
+    InlineQueryResultCachedVoice,
+    InlineQueryResultContact,
+    InlineQueryResultDocument,
+    InlineQueryResultGame,
+    InlineQueryResultGif,
+    InlineQueryResultLocation,
+    InlineQueryResultMpeg4Gif,
+    InlineQueryResultPhoto,
     InlineQueryResultsButton,
+    InlineQueryResultVenue,
+    InlineQueryResultVideo,
+    InlineQueryResultVoice,
     InputFile,
     InputMedia,
+    InputMediaAnimation,
     InputMediaAudio,
     InputMediaDocument,
     InputMediaPhoto,
@@ -579,7 +607,28 @@ class Bot(ContextInstanceMixin["Bot"]):
     async def answer_web_app_query(
         self,
         web_app_query_id: str,
-        result: InlineQueryResult,
+        result: Union[
+            InlineQueryResultCachedAudio,
+            InlineQueryResultCachedDocument,
+            InlineQueryResultCachedGif,
+            InlineQueryResultCachedMpeg4Gif,
+            InlineQueryResultCachedPhoto,
+            InlineQueryResultCachedSticker,
+            InlineQueryResultCachedVideo,
+            InlineQueryResultCachedVoice,
+            InlineQueryResultArticle,
+            InlineQueryResultAudio,
+            InlineQueryResultContact,
+            InlineQueryResultGame,
+            InlineQueryResultDocument,
+            InlineQueryResultGif,
+            InlineQueryResultLocation,
+            InlineQueryResultMpeg4Gif,
+            InlineQueryResultPhoto,
+            InlineQueryResultVenue,
+            InlineQueryResultVideo,
+            InlineQueryResultVoice,
+        ],
         request_timeout: Optional[int] = None,
     ) -> SentWebAppMessage:
         """
@@ -1073,7 +1122,17 @@ class Bot(ContextInstanceMixin["Bot"]):
 
     async def delete_my_commands(
         self,
-        scope: Optional[BotCommandScope] = None,
+        scope: Optional[
+            Union[
+                BotCommandScopeDefault,
+                BotCommandScopeAllPrivateChats,
+                BotCommandScopeAllGroupChats,
+                BotCommandScopeAllChatAdministrators,
+                BotCommandScopeChat,
+                BotCommandScopeChatAdministrators,
+                BotCommandScopeChatMember,
+            ]
+        ] = None,
         language_code: Optional[str] = None,
         request_timeout: Optional[int] = None,
     ) -> bool:
@@ -1282,7 +1341,13 @@ class Bot(ContextInstanceMixin["Bot"]):
 
     async def edit_message_media(
         self,
-        media: InputMedia,
+        media: Union[
+            InputMediaAnimation,
+            InputMediaDocument,
+            InputMediaAudio,
+            InputMediaPhoto,
+            InputMediaVideo,
+        ],
         chat_id: Optional[Union[int, str]] = None,
         message_id: Optional[int] = None,
         inline_message_id: Optional[str] = None,
@@ -1664,7 +1729,17 @@ class Bot(ContextInstanceMixin["Bot"]):
 
     async def get_my_commands(
         self,
-        scope: Optional[BotCommandScope] = None,
+        scope: Optional[
+            Union[
+                BotCommandScopeDefault,
+                BotCommandScopeAllPrivateChats,
+                BotCommandScopeAllGroupChats,
+                BotCommandScopeAllChatAdministrators,
+                BotCommandScopeChat,
+                BotCommandScopeChatAdministrators,
+                BotCommandScopeChatMember,
+            ]
+        ] = None,
         language_code: Optional[str] = None,
         request_timeout: Optional[int] = None,
     ) -> List[BotCommand]:
@@ -3077,7 +3152,7 @@ class Bot(ContextInstanceMixin["Bot"]):
         self,
         chat_id: Optional[int] = None,
         menu_button: Optional[
-            Union[MenuButtonDefault, MenuButtonWebApp, MenuButtonCommands]
+            Union[MenuButtonCommands, MenuButtonWebApp, MenuButtonDefault]
         ] = None,
         request_timeout: Optional[int] = None,
     ) -> bool:
@@ -3234,7 +3309,17 @@ class Bot(ContextInstanceMixin["Bot"]):
     async def set_my_commands(
         self,
         commands: List[BotCommand],
-        scope: Optional[BotCommandScope] = None,
+        scope: Optional[
+            Union[
+                BotCommandScopeDefault,
+                BotCommandScopeAllPrivateChats,
+                BotCommandScopeAllGroupChats,
+                BotCommandScopeAllChatAdministrators,
+                BotCommandScopeChat,
+                BotCommandScopeChatAdministrators,
+                BotCommandScopeChatMember,
+            ]
+        ] = None,
         language_code: Optional[str] = None,
         request_timeout: Optional[int] = None,
     ) -> bool:
diff --git a/aiogram/client/context_controller.py b/aiogram/client/context_controller.py
index d2402018..530c1555 100644
--- a/aiogram/client/context_controller.py
+++ b/aiogram/client/context_controller.py
@@ -11,10 +11,7 @@ class BotContextController(BaseModel):
     _bot: Optional["Bot"] = PrivateAttr()
 
     def model_post_init(self, __context: Any) -> None:
-        if not __context:
-            self._bot = None
-        else:
-            self._bot = __context.get("bot")
+        self._bot = __context.get("bot") if __context else None
 
     def as_(self, bot: Optional["Bot"]) -> Self:
         """
diff --git a/aiogram/enums/__init__.py b/aiogram/enums/__init__.py
index 73422378..ab49c599 100644
--- a/aiogram/enums/__init__.py
+++ b/aiogram/enums/__init__.py
@@ -4,12 +4,14 @@ from .chat_member_status import ChatMemberStatus
 from .chat_type import ChatType
 from .content_type import ContentType
 from .dice_emoji import DiceEmoji
+from .encrypted_passport_element import EncryptedPassportElement
 from .inline_query_result_type import InlineQueryResultType
 from .input_media_type import InputMediaType
 from .mask_position_point import MaskPositionPoint
 from .menu_button_type import MenuButtonType
 from .message_entity_type import MessageEntityType
 from .parse_mode import ParseMode
+from .passport_element_error_type import PassportElementErrorType
 from .poll_type import PollType
 from .sticker_format import StickerFormat
 from .sticker_type import StickerType
@@ -23,12 +25,14 @@ __all__ = (
     "ChatType",
     "ContentType",
     "DiceEmoji",
+    "EncryptedPassportElement",
     "InlineQueryResultType",
     "InputMediaType",
     "MaskPositionPoint",
     "MenuButtonType",
     "MessageEntityType",
     "ParseMode",
+    "PassportElementErrorType",
     "PollType",
     "StickerFormat",
     "StickerType",
diff --git a/aiogram/enums/encrypted_passport_element.py b/aiogram/enums/encrypted_passport_element.py
new file mode 100644
index 00000000..ebb4b2e6
--- /dev/null
+++ b/aiogram/enums/encrypted_passport_element.py
@@ -0,0 +1,23 @@
+from enum import Enum
+
+
+class EncryptedPassportElement(str, Enum):
+    """
+    This object represents type of encrypted passport element.
+
+    Source: https://core.telegram.org/bots/api#encryptedpassportelement
+    """
+
+    PERSONAL_DETAILS = "personal_details"
+    PASSPORT = "passport"
+    DRIVER_LICENSE = "driver_license"
+    IDENTITY_CARD = "identity_card"
+    INTERNAL_PASSPORT = "internal_passport"
+    ADDRESS = "address"
+    UTILITY_BILL = "utility_bill"
+    BANK_STATEMENT = "bank_statement"
+    RENTAL_AGREEMENT = "rental_agreement"
+    PASSPORT_REGISTRATION = "passport_registration"
+    TEMPORARY_REGISTRATION = "temporary_registration"
+    PHONE_NUMBER = "phone_number"
+    EMAIL = "email"
diff --git a/aiogram/enums/passport_element_error_type.py b/aiogram/enums/passport_element_error_type.py
new file mode 100644
index 00000000..cdcb4806
--- /dev/null
+++ b/aiogram/enums/passport_element_error_type.py
@@ -0,0 +1,19 @@
+from enum import Enum
+
+
+class PassportElementErrorType(str, Enum):
+    """
+    This object represents a passport element error type.
+
+    Source: https://core.telegram.org/bots/api#passportelementerror
+    """
+
+    DATA = "data"
+    FRONT_SIDE = "front_side"
+    REVERSE_SIDE = "reverse_side"
+    SELFIE = "selfie"
+    FILE = "file"
+    FILES = "files"
+    TRANSLATION_FILE = "translation_file"
+    TRANSLATION_FILES = "translation_files"
+    UNSPECIFIED = "unspecified"
diff --git a/aiogram/filters/chat_member_updated.py b/aiogram/filters/chat_member_updated.py
index 7671ba4e..23cf0e9c 100644
--- a/aiogram/filters/chat_member_updated.py
+++ b/aiogram/filters/chat_member_updated.py
@@ -74,9 +74,12 @@ class _MemberStatusMarker:
         return hash((self.name, self.is_member))
 
     def check(self, *, member: ChatMember) -> bool:
-        if self.is_member is not None and member.is_member != self.is_member:
+        # Not all member types have `is_member` attribute
+        is_member = getattr(member, "is_member", None)
+        status = getattr(member, "status", None)
+        if self.is_member is not None and is_member != self.is_member:
             return False
-        return self.name == member.status
+        return self.name == status
 
 
 class _MemberStatusGroupMarker:
diff --git a/aiogram/methods/answer_web_app_query.py b/aiogram/methods/answer_web_app_query.py
index 8bb1abc8..23def3e4 100644
--- a/aiogram/methods/answer_web_app_query.py
+++ b/aiogram/methods/answer_web_app_query.py
@@ -1,6 +1,30 @@
 from __future__ import annotations
 
-from ..types import InlineQueryResult, SentWebAppMessage
+from typing import Union
+
+from ..types import (
+    InlineQueryResultArticle,
+    InlineQueryResultAudio,
+    InlineQueryResultCachedAudio,
+    InlineQueryResultCachedDocument,
+    InlineQueryResultCachedGif,
+    InlineQueryResultCachedMpeg4Gif,
+    InlineQueryResultCachedPhoto,
+    InlineQueryResultCachedSticker,
+    InlineQueryResultCachedVideo,
+    InlineQueryResultCachedVoice,
+    InlineQueryResultContact,
+    InlineQueryResultDocument,
+    InlineQueryResultGame,
+    InlineQueryResultGif,
+    InlineQueryResultLocation,
+    InlineQueryResultMpeg4Gif,
+    InlineQueryResultPhoto,
+    InlineQueryResultVenue,
+    InlineQueryResultVideo,
+    InlineQueryResultVoice,
+    SentWebAppMessage,
+)
 from .base import TelegramMethod
 
 
@@ -16,5 +40,26 @@ class AnswerWebAppQuery(TelegramMethod[SentWebAppMessage]):
 
     web_app_query_id: str
     """Unique identifier for the query to be answered"""
-    result: InlineQueryResult
+    result: Union[
+        InlineQueryResultCachedAudio,
+        InlineQueryResultCachedDocument,
+        InlineQueryResultCachedGif,
+        InlineQueryResultCachedMpeg4Gif,
+        InlineQueryResultCachedPhoto,
+        InlineQueryResultCachedSticker,
+        InlineQueryResultCachedVideo,
+        InlineQueryResultCachedVoice,
+        InlineQueryResultArticle,
+        InlineQueryResultAudio,
+        InlineQueryResultContact,
+        InlineQueryResultGame,
+        InlineQueryResultDocument,
+        InlineQueryResultGif,
+        InlineQueryResultLocation,
+        InlineQueryResultMpeg4Gif,
+        InlineQueryResultPhoto,
+        InlineQueryResultVenue,
+        InlineQueryResultVideo,
+        InlineQueryResultVoice,
+    ]
     """A JSON-serialized object describing the message to be sent"""
diff --git a/aiogram/methods/delete_my_commands.py b/aiogram/methods/delete_my_commands.py
index 5fc1044e..cd91b7e7 100644
--- a/aiogram/methods/delete_my_commands.py
+++ b/aiogram/methods/delete_my_commands.py
@@ -1,8 +1,16 @@
 from __future__ import annotations
 
-from typing import Optional
+from typing import Optional, Union
 
-from ..types import BotCommandScope
+from ..types import (
+    BotCommandScopeAllChatAdministrators,
+    BotCommandScopeAllGroupChats,
+    BotCommandScopeAllPrivateChats,
+    BotCommandScopeChat,
+    BotCommandScopeChatAdministrators,
+    BotCommandScopeChatMember,
+    BotCommandScopeDefault,
+)
 from .base import TelegramMethod
 
 
@@ -16,7 +24,17 @@ class DeleteMyCommands(TelegramMethod[bool]):
     __returning__ = bool
     __api_method__ = "deleteMyCommands"
 
-    scope: Optional[BotCommandScope] = None
+    scope: Optional[
+        Union[
+            BotCommandScopeDefault,
+            BotCommandScopeAllPrivateChats,
+            BotCommandScopeAllGroupChats,
+            BotCommandScopeAllChatAdministrators,
+            BotCommandScopeChat,
+            BotCommandScopeChatAdministrators,
+            BotCommandScopeChatMember,
+        ]
+    ] = None
     """A JSON-serialized object, describing scope of users for which the commands are relevant. Defaults to :class:`aiogram.types.bot_command_scope_default.BotCommandScopeDefault`."""
     language_code: Optional[str] = None
     """A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands"""
diff --git a/aiogram/methods/edit_message_media.py b/aiogram/methods/edit_message_media.py
index f6ab0166..5d006146 100644
--- a/aiogram/methods/edit_message_media.py
+++ b/aiogram/methods/edit_message_media.py
@@ -2,7 +2,15 @@ from __future__ import annotations
 
 from typing import Optional, Union
 
-from ..types import InlineKeyboardMarkup, InputMedia, Message
+from ..types import (
+    InlineKeyboardMarkup,
+    InputMediaAnimation,
+    InputMediaAudio,
+    InputMediaDocument,
+    InputMediaPhoto,
+    InputMediaVideo,
+    Message,
+)
 from .base import TelegramMethod
 
 
@@ -16,7 +24,9 @@ class EditMessageMedia(TelegramMethod[Union[Message, bool]]):
     __returning__ = Union[Message, bool]
     __api_method__ = "editMessageMedia"
 
-    media: InputMedia
+    media: Union[
+        InputMediaAnimation, InputMediaDocument, InputMediaAudio, InputMediaPhoto, InputMediaVideo
+    ]
     """A JSON-serialized object for a new media content of the message"""
     chat_id: Optional[Union[int, str]] = None
     """Required if *inline_message_id* is not specified. Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`)"""
diff --git a/aiogram/methods/get_my_commands.py b/aiogram/methods/get_my_commands.py
index 9d4a696f..4be74e21 100644
--- a/aiogram/methods/get_my_commands.py
+++ b/aiogram/methods/get_my_commands.py
@@ -1,8 +1,17 @@
 from __future__ import annotations
 
-from typing import List, Optional
+from typing import List, Optional, Union
 
-from ..types import BotCommand, BotCommandScope
+from ..types import (
+    BotCommand,
+    BotCommandScopeAllChatAdministrators,
+    BotCommandScopeAllGroupChats,
+    BotCommandScopeAllPrivateChats,
+    BotCommandScopeChat,
+    BotCommandScopeChatAdministrators,
+    BotCommandScopeChatMember,
+    BotCommandScopeDefault,
+)
 from .base import TelegramMethod
 
 
@@ -16,7 +25,17 @@ class GetMyCommands(TelegramMethod[List[BotCommand]]):
     __returning__ = List[BotCommand]
     __api_method__ = "getMyCommands"
 
-    scope: Optional[BotCommandScope] = None
+    scope: Optional[
+        Union[
+            BotCommandScopeDefault,
+            BotCommandScopeAllPrivateChats,
+            BotCommandScopeAllGroupChats,
+            BotCommandScopeAllChatAdministrators,
+            BotCommandScopeChat,
+            BotCommandScopeChatAdministrators,
+            BotCommandScopeChatMember,
+        ]
+    ] = None
     """A JSON-serialized object, describing scope of users. Defaults to :class:`aiogram.types.bot_command_scope_default.BotCommandScopeDefault`."""
     language_code: Optional[str] = None
     """A two-letter ISO 639-1 language code or an empty string"""
diff --git a/aiogram/methods/set_chat_menu_button.py b/aiogram/methods/set_chat_menu_button.py
index 4fdd086b..9cbd019b 100644
--- a/aiogram/methods/set_chat_menu_button.py
+++ b/aiogram/methods/set_chat_menu_button.py
@@ -18,5 +18,5 @@ class SetChatMenuButton(TelegramMethod[bool]):
 
     chat_id: Optional[int] = None
     """Unique identifier for the target private chat. If not specified, default bot's menu button will be changed"""
-    menu_button: Optional[Union[MenuButtonDefault, MenuButtonWebApp, MenuButtonCommands]] = None
+    menu_button: Optional[Union[MenuButtonCommands, MenuButtonWebApp, MenuButtonDefault]] = None
     """A JSON-serialized object for the bot's new menu button. Defaults to :class:`aiogram.types.menu_button_default.MenuButtonDefault`"""
diff --git a/aiogram/methods/set_my_commands.py b/aiogram/methods/set_my_commands.py
index c668852d..3aff027f 100644
--- a/aiogram/methods/set_my_commands.py
+++ b/aiogram/methods/set_my_commands.py
@@ -1,8 +1,17 @@
 from __future__ import annotations
 
-from typing import List, Optional
+from typing import List, Optional, Union
 
-from ..types import BotCommand, BotCommandScope
+from ..types import (
+    BotCommand,
+    BotCommandScopeAllChatAdministrators,
+    BotCommandScopeAllGroupChats,
+    BotCommandScopeAllPrivateChats,
+    BotCommandScopeChat,
+    BotCommandScopeChatAdministrators,
+    BotCommandScopeChatMember,
+    BotCommandScopeDefault,
+)
 from .base import TelegramMethod
 
 
@@ -18,7 +27,17 @@ class SetMyCommands(TelegramMethod[bool]):
 
     commands: List[BotCommand]
     """A JSON-serialized list of bot commands to be set as the list of the bot's commands. At most 100 commands can be specified."""
-    scope: Optional[BotCommandScope] = None
+    scope: Optional[
+        Union[
+            BotCommandScopeDefault,
+            BotCommandScopeAllPrivateChats,
+            BotCommandScopeAllGroupChats,
+            BotCommandScopeAllChatAdministrators,
+            BotCommandScopeChat,
+            BotCommandScopeChatAdministrators,
+            BotCommandScopeChatMember,
+        ]
+    ] = None
     """A JSON-serialized object, describing scope of users for which the commands are relevant. Defaults to :class:`aiogram.types.bot_command_scope_default.BotCommandScopeDefault`."""
     language_code: Optional[str] = None
     """A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands"""
diff --git a/aiogram/types/chat_member.py b/aiogram/types/chat_member.py
index 6bf5b79e..018bebda 100644
--- a/aiogram/types/chat_member.py
+++ b/aiogram/types/chat_member.py
@@ -1,13 +1,7 @@
 from __future__ import annotations
 
-import datetime
-from typing import TYPE_CHECKING, Optional
-
 from .base import TelegramObject
 
-if TYPE_CHECKING:
-    from .user import User
-
 
 class ChatMember(TelegramObject):
     """
@@ -22,60 +16,3 @@ class ChatMember(TelegramObject):
 
     Source: https://core.telegram.org/bots/api#chatmember
     """
-
-    status: str
-    """The member's status in the chat"""
-    user: Optional[User] = None
-    """*Optional*. Information about the user"""
-    is_anonymous: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user's presence in the chat is hidden"""
-    custom_title: Optional[str] = None
-    """*Optional*. Custom title for this user"""
-    can_be_edited: Optional[bool] = None
-    """*Optional*. :code:`True`, if the bot is allowed to edit administrator privileges of that user"""
-    can_manage_chat: Optional[bool] = None
-    """*Optional*. :code:`True`, if the administrator can access the chat event log, chat statistics, message statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege"""
-    can_delete_messages: Optional[bool] = None
-    """*Optional*. :code:`True`, if the administrator can delete messages of other users"""
-    can_manage_video_chats: Optional[bool] = None
-    """*Optional*. :code:`True`, if the administrator can manage video chats"""
-    can_restrict_members: Optional[bool] = None
-    """*Optional*. :code:`True`, if the administrator can restrict, ban or unban chat members"""
-    can_promote_members: Optional[bool] = None
-    """*Optional*. :code:`True`, if the administrator can add new administrators with a subset of their own privileges or demote administrators that they have promoted, directly or indirectly (promoted by administrators that were appointed by the user)"""
-    can_change_info: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to change the chat title, photo and other settings"""
-    can_invite_users: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to invite new users to the chat"""
-    can_post_messages: Optional[bool] = None
-    """*Optional*. :code:`True`, if the administrator can post in the channel; channels only"""
-    can_edit_messages: Optional[bool] = None
-    """*Optional*. :code:`True`, if the administrator can edit messages of other users and can pin messages; channels only"""
-    can_pin_messages: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to pin messages; groups and supergroups only"""
-    can_manage_topics: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to create, rename, close, and reopen forum topics; supergroups only"""
-    is_member: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is a member of the chat at the moment of the request"""
-    can_send_messages: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send text messages, contacts, invoices, locations and venues"""
-    can_send_audios: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send audios"""
-    can_send_documents: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send documents"""
-    can_send_photos: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send photos"""
-    can_send_videos: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send videos"""
-    can_send_video_notes: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send video notes"""
-    can_send_voice_notes: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send voice notes"""
-    can_send_polls: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send polls"""
-    can_send_other_messages: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to send animations, games, stickers and use inline bots"""
-    can_add_web_page_previews: Optional[bool] = None
-    """*Optional*. :code:`True`, if the user is allowed to add web page previews to their messages"""
-    until_date: Optional[datetime.datetime] = None
-    """*Optional*. Date when restrictions will be lifted for this user; unix time. If 0, then the user is restricted forever"""
diff --git a/aiogram/types/inline_query_result_article.py b/aiogram/types/inline_query_result_article.py
index be084aed..42c11782 100644
--- a/aiogram/types/inline_query_result_article.py
+++ b/aiogram/types/inline_query_result_article.py
@@ -1,13 +1,17 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, Literal, Optional
+from typing import TYPE_CHECKING, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
 
 
 class InlineQueryResultArticle(InlineQueryResult):
@@ -23,7 +27,13 @@ class InlineQueryResultArticle(InlineQueryResult):
     """Unique identifier for this result, 1-64 Bytes"""
     title: str
     """Title of the result"""
-    input_message_content: InputMessageContent
+    input_message_content: Union[
+        InputTextMessageContent,
+        InputLocationMessageContent,
+        InputVenueMessageContent,
+        InputContactMessageContent,
+        InputInvoiceMessageContent,
+    ]
     """Content of the message to be sent"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
diff --git a/aiogram/types/inline_query_result_audio.py b/aiogram/types/inline_query_result_audio.py
index 74cea130..c57b0b72 100644
--- a/aiogram/types/inline_query_result_audio.py
+++ b/aiogram/types/inline_query_result_audio.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -40,5 +44,13 @@ class InlineQueryResultAudio(InlineQueryResult):
     """*Optional*. Audio duration in seconds"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the audio"""
diff --git a/aiogram/types/inline_query_result_cached_audio.py b/aiogram/types/inline_query_result_cached_audio.py
index 8d4819cc..6f0a73f1 100644
--- a/aiogram/types/inline_query_result_cached_audio.py
+++ b/aiogram/types/inline_query_result_cached_audio.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -34,5 +38,13 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the audio"""
diff --git a/aiogram/types/inline_query_result_cached_document.py b/aiogram/types/inline_query_result_cached_document.py
index cedb45a8..ccb28196 100644
--- a/aiogram/types/inline_query_result_cached_document.py
+++ b/aiogram/types/inline_query_result_cached_document.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -38,5 +42,13 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the file"""
diff --git a/aiogram/types/inline_query_result_cached_gif.py b/aiogram/types/inline_query_result_cached_gif.py
index acbcb6fa..f8ef40a6 100644
--- a/aiogram/types/inline_query_result_cached_gif.py
+++ b/aiogram/types/inline_query_result_cached_gif.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -35,5 +39,13 @@ class InlineQueryResultCachedGif(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the GIF animation"""
diff --git a/aiogram/types/inline_query_result_cached_mpeg4_gif.py b/aiogram/types/inline_query_result_cached_mpeg4_gif.py
index f9605d68..09cc0db8 100644
--- a/aiogram/types/inline_query_result_cached_mpeg4_gif.py
+++ b/aiogram/types/inline_query_result_cached_mpeg4_gif.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -35,5 +39,13 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the video animation"""
diff --git a/aiogram/types/inline_query_result_cached_photo.py b/aiogram/types/inline_query_result_cached_photo.py
index 96b6d208..b72ac656 100644
--- a/aiogram/types/inline_query_result_cached_photo.py
+++ b/aiogram/types/inline_query_result_cached_photo.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -37,5 +41,13 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the photo"""
diff --git a/aiogram/types/inline_query_result_cached_sticker.py b/aiogram/types/inline_query_result_cached_sticker.py
index 27f95c09..beaab093 100644
--- a/aiogram/types/inline_query_result_cached_sticker.py
+++ b/aiogram/types/inline_query_result_cached_sticker.py
@@ -1,13 +1,17 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, Literal, Optional
+from typing import TYPE_CHECKING, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
 
 
 class InlineQueryResultCachedSticker(InlineQueryResult):
@@ -26,5 +30,13 @@ class InlineQueryResultCachedSticker(InlineQueryResult):
     """A valid file identifier of the sticker"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the sticker"""
diff --git a/aiogram/types/inline_query_result_cached_video.py b/aiogram/types/inline_query_result_cached_video.py
index c1afd26e..f522bc24 100644
--- a/aiogram/types/inline_query_result_cached_video.py
+++ b/aiogram/types/inline_query_result_cached_video.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -37,5 +41,13 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the video"""
diff --git a/aiogram/types/inline_query_result_cached_voice.py b/aiogram/types/inline_query_result_cached_voice.py
index 354b6f39..7c2b0a44 100644
--- a/aiogram/types/inline_query_result_cached_voice.py
+++ b/aiogram/types/inline_query_result_cached_voice.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -36,5 +40,13 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the voice message"""
diff --git a/aiogram/types/inline_query_result_contact.py b/aiogram/types/inline_query_result_contact.py
index 121dfba9..aa2fc8c5 100644
--- a/aiogram/types/inline_query_result_contact.py
+++ b/aiogram/types/inline_query_result_contact.py
@@ -1,13 +1,17 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, Literal, Optional
+from typing import TYPE_CHECKING, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
 
 
 class InlineQueryResultContact(InlineQueryResult):
@@ -32,7 +36,15 @@ class InlineQueryResultContact(InlineQueryResult):
     """*Optional*. Additional data about the contact in the form of a `vCard <https://en.wikipedia.org/wiki/VCard>`_, 0-2048 bytes"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the contact"""
     thumbnail_url: Optional[str] = None
     """*Optional*. Url of the thumbnail for the result"""
diff --git a/aiogram/types/inline_query_result_document.py b/aiogram/types/inline_query_result_document.py
index 13a4e7c5..102aaf24 100644
--- a/aiogram/types/inline_query_result_document.py
+++ b/aiogram/types/inline_query_result_document.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -40,7 +44,15 @@ class InlineQueryResultDocument(InlineQueryResult):
     """*Optional*. Short description of the result"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. Inline keyboard attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the file"""
     thumbnail_url: Optional[str] = None
     """*Optional*. URL of the thumbnail (JPEG only) for the file"""
diff --git a/aiogram/types/inline_query_result_gif.py b/aiogram/types/inline_query_result_gif.py
index 1120369f..e3b85fe2 100644
--- a/aiogram/types/inline_query_result_gif.py
+++ b/aiogram/types/inline_query_result_gif.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -45,5 +49,13 @@ class InlineQueryResultGif(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the GIF animation"""
diff --git a/aiogram/types/inline_query_result_location.py b/aiogram/types/inline_query_result_location.py
index 1dbda6a8..4948a67c 100644
--- a/aiogram/types/inline_query_result_location.py
+++ b/aiogram/types/inline_query_result_location.py
@@ -1,13 +1,17 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, Literal, Optional
+from typing import TYPE_CHECKING, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
 
 
 class InlineQueryResultLocation(InlineQueryResult):
@@ -38,7 +42,15 @@ class InlineQueryResultLocation(InlineQueryResult):
     """*Optional*. For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified."""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the location"""
     thumbnail_url: Optional[str] = None
     """*Optional*. Url of the thumbnail for the result"""
diff --git a/aiogram/types/inline_query_result_mpeg4_gif.py b/aiogram/types/inline_query_result_mpeg4_gif.py
index d14491c6..9d475af3 100644
--- a/aiogram/types/inline_query_result_mpeg4_gif.py
+++ b/aiogram/types/inline_query_result_mpeg4_gif.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -45,5 +49,13 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the video animation"""
diff --git a/aiogram/types/inline_query_result_photo.py b/aiogram/types/inline_query_result_photo.py
index 086118f0..35a9d996 100644
--- a/aiogram/types/inline_query_result_photo.py
+++ b/aiogram/types/inline_query_result_photo.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -43,5 +47,13 @@ class InlineQueryResultPhoto(InlineQueryResult):
     """*Optional*. List of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the photo"""
diff --git a/aiogram/types/inline_query_result_venue.py b/aiogram/types/inline_query_result_venue.py
index 6f0aeb66..65841255 100644
--- a/aiogram/types/inline_query_result_venue.py
+++ b/aiogram/types/inline_query_result_venue.py
@@ -1,13 +1,17 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, Literal, Optional
+from typing import TYPE_CHECKING, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
 
 
 class InlineQueryResultVenue(InlineQueryResult):
@@ -40,7 +44,15 @@ class InlineQueryResultVenue(InlineQueryResult):
     """*Optional*. Google Places type of the venue. (See `supported types <https://developers.google.com/places/web-service/supported_types>`_.)"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the venue"""
     thumbnail_url: Optional[str] = None
     """*Optional*. Url of the thumbnail for the result"""
diff --git a/aiogram/types/inline_query_result_video.py b/aiogram/types/inline_query_result_video.py
index b1c6775e..0968dda1 100644
--- a/aiogram/types/inline_query_result_video.py
+++ b/aiogram/types/inline_query_result_video.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -49,5 +53,13 @@ class InlineQueryResultVideo(InlineQueryResult):
     """*Optional*. Short description of the result"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the video. This field is **required** if InlineQueryResultVideo is used to send an HTML-page as a result (e.g., a YouTube video)."""
diff --git a/aiogram/types/inline_query_result_voice.py b/aiogram/types/inline_query_result_voice.py
index e97a994e..995950ef 100644
--- a/aiogram/types/inline_query_result_voice.py
+++ b/aiogram/types/inline_query_result_voice.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, List, Literal, Optional
+from typing import TYPE_CHECKING, List, Literal, Optional, Union
 
 from ..enums import InlineQueryResultType
 from .base import UNSET_PARSE_MODE
@@ -8,7 +8,11 @@ from .inline_query_result import InlineQueryResult
 
 if TYPE_CHECKING:
     from .inline_keyboard_markup import InlineKeyboardMarkup
-    from .input_message_content import InputMessageContent
+    from .input_contact_message_content import InputContactMessageContent
+    from .input_invoice_message_content import InputInvoiceMessageContent
+    from .input_location_message_content import InputLocationMessageContent
+    from .input_text_message_content import InputTextMessageContent
+    from .input_venue_message_content import InputVenueMessageContent
     from .message_entity import MessageEntity
 
 
@@ -38,5 +42,13 @@ class InlineQueryResultVoice(InlineQueryResult):
     """*Optional*. Recording duration in seconds"""
     reply_markup: Optional[InlineKeyboardMarkup] = None
     """*Optional*. `Inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_ attached to the message"""
-    input_message_content: Optional[InputMessageContent] = None
+    input_message_content: Optional[
+        Union[
+            InputTextMessageContent,
+            InputLocationMessageContent,
+            InputVenueMessageContent,
+            InputContactMessageContent,
+            InputInvoiceMessageContent,
+        ]
+    ] = None
     """*Optional*. Content of the message to be sent instead of the voice recording"""
diff --git a/aiogram/types/message.py b/aiogram/types/message.py
index 9339fe7f..6d022960 100644
--- a/aiogram/types/message.py
+++ b/aiogram/types/message.py
@@ -67,7 +67,7 @@ if TYPE_CHECKING:
     from .general_forum_topic_unhidden import GeneralForumTopicUnhidden
     from .inline_keyboard_markup import InlineKeyboardMarkup
     from .input_file import InputFile
-    from .input_media import InputMedia
+    from .input_media_animation import InputMediaAnimation
     from .input_media_audio import InputMediaAudio
     from .input_media_document import InputMediaDocument
     from .input_media_photo import InputMediaPhoto
@@ -2774,7 +2774,13 @@ class Message(TelegramObject):
 
     def edit_media(
         self,
-        media: InputMedia,
+        media: Union[
+            InputMediaAnimation,
+            InputMediaDocument,
+            InputMediaAudio,
+            InputMediaPhoto,
+            InputMediaVideo,
+        ],
         inline_message_id: Optional[str] = None,
         reply_markup: Optional[InlineKeyboardMarkup] = None,
         **kwargs: Any,
diff --git a/aiogram/types/passport_element_error_data_field.py b/aiogram/types/passport_element_error_data_field.py
index 370a100a..76a6d93a 100644
--- a/aiogram/types/passport_element_error_data_field.py
+++ b/aiogram/types/passport_element_error_data_field.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,7 @@ class PassportElementErrorDataField(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrordatafield
     """
 
-    source: Literal["data"] = "data"
+    source: Literal[PassportElementErrorType.DATA] = PassportElementErrorType.DATA
     """Error source, must be *data*"""
     type: str
     """The section of the user's Telegram Passport which has the error, one of 'personal_details', 'passport', 'driver_license', 'identity_card', 'internal_passport', 'address'"""
diff --git a/aiogram/types/passport_element_error_file.py b/aiogram/types/passport_element_error_file.py
index e2016dd9..74512eea 100644
--- a/aiogram/types/passport_element_error_file.py
+++ b/aiogram/types/passport_element_error_file.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,7 @@ class PassportElementErrorFile(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrorfile
     """
 
-    source: Literal["file"] = "file"
+    source: Literal[PassportElementErrorType.FILE] = PassportElementErrorType.FILE
     """Error source, must be *file*"""
     type: str
     """The section of the user's Telegram Passport which has the issue, one of 'utility_bill', 'bank_statement', 'rental_agreement', 'passport_registration', 'temporary_registration'"""
diff --git a/aiogram/types/passport_element_error_files.py b/aiogram/types/passport_element_error_files.py
index 4b97c095..020f7a99 100644
--- a/aiogram/types/passport_element_error_files.py
+++ b/aiogram/types/passport_element_error_files.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import List, Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,7 @@ class PassportElementErrorFiles(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrorfiles
     """
 
-    source: Literal["files"] = "files"
+    source: Literal[PassportElementErrorType.FILES] = PassportElementErrorType.FILES
     """Error source, must be *files*"""
     type: str
     """The section of the user's Telegram Passport which has the issue, one of 'utility_bill', 'bank_statement', 'rental_agreement', 'passport_registration', 'temporary_registration'"""
diff --git a/aiogram/types/passport_element_error_front_side.py b/aiogram/types/passport_element_error_front_side.py
index 4d46cc94..f3b4dd2f 100644
--- a/aiogram/types/passport_element_error_front_side.py
+++ b/aiogram/types/passport_element_error_front_side.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,7 @@ class PassportElementErrorFrontSide(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrorfrontside
     """
 
-    source: Literal["front_side"] = "front_side"
+    source: Literal[PassportElementErrorType.FRONT_SIDE] = PassportElementErrorType.FRONT_SIDE
     """Error source, must be *front_side*"""
     type: str
     """The section of the user's Telegram Passport which has the issue, one of 'passport', 'driver_license', 'identity_card', 'internal_passport'"""
diff --git a/aiogram/types/passport_element_error_reverse_side.py b/aiogram/types/passport_element_error_reverse_side.py
index 7584f567..18929df6 100644
--- a/aiogram/types/passport_element_error_reverse_side.py
+++ b/aiogram/types/passport_element_error_reverse_side.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,7 @@ class PassportElementErrorReverseSide(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrorreverseside
     """
 
-    source: Literal["reverse_side"] = "reverse_side"
+    source: Literal[PassportElementErrorType.REVERSE_SIDE] = PassportElementErrorType.REVERSE_SIDE
     """Error source, must be *reverse_side*"""
     type: str
     """The section of the user's Telegram Passport which has the issue, one of 'driver_license', 'identity_card'"""
diff --git a/aiogram/types/passport_element_error_selfie.py b/aiogram/types/passport_element_error_selfie.py
index 37cd1c95..003bfec6 100644
--- a/aiogram/types/passport_element_error_selfie.py
+++ b/aiogram/types/passport_element_error_selfie.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,7 @@ class PassportElementErrorSelfie(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrorselfie
     """
 
-    source: Literal["selfie"] = "selfie"
+    source: Literal[PassportElementErrorType.SELFIE] = PassportElementErrorType.SELFIE
     """Error source, must be *selfie*"""
     type: str
     """The section of the user's Telegram Passport which has the issue, one of 'passport', 'driver_license', 'identity_card', 'internal_passport'"""
diff --git a/aiogram/types/passport_element_error_translation_file.py b/aiogram/types/passport_element_error_translation_file.py
index 92b82ad6..aac4268e 100644
--- a/aiogram/types/passport_element_error_translation_file.py
+++ b/aiogram/types/passport_element_error_translation_file.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,9 @@ class PassportElementErrorTranslationFile(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrortranslationfile
     """
 
-    source: Literal["translation_file"] = "translation_file"
+    source: Literal[
+        PassportElementErrorType.TRANSLATION_FILE
+    ] = PassportElementErrorType.TRANSLATION_FILE
     """Error source, must be *translation_file*"""
     type: str
     """Type of element of the user's Telegram Passport which has the issue, one of 'passport', 'driver_license', 'identity_card', 'internal_passport', 'utility_bill', 'bank_statement', 'rental_agreement', 'passport_registration', 'temporary_registration'"""
diff --git a/aiogram/types/passport_element_error_translation_files.py b/aiogram/types/passport_element_error_translation_files.py
index a9dbece8..427c6468 100644
--- a/aiogram/types/passport_element_error_translation_files.py
+++ b/aiogram/types/passport_element_error_translation_files.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import List, Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,9 @@ class PassportElementErrorTranslationFiles(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrortranslationfiles
     """
 
-    source: Literal["translation_files"] = "translation_files"
+    source: Literal[
+        PassportElementErrorType.TRANSLATION_FILES
+    ] = PassportElementErrorType.TRANSLATION_FILES
     """Error source, must be *translation_files*"""
     type: str
     """Type of element of the user's Telegram Passport which has the issue, one of 'passport', 'driver_license', 'identity_card', 'internal_passport', 'utility_bill', 'bank_statement', 'rental_agreement', 'passport_registration', 'temporary_registration'"""
diff --git a/aiogram/types/passport_element_error_unspecified.py b/aiogram/types/passport_element_error_unspecified.py
index c287f96c..5e8d88e7 100644
--- a/aiogram/types/passport_element_error_unspecified.py
+++ b/aiogram/types/passport_element_error_unspecified.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from typing import Literal
 
+from ..enums import PassportElementErrorType
 from .passport_element_error import PassportElementError
 
 
@@ -12,7 +13,7 @@ class PassportElementErrorUnspecified(PassportElementError):
     Source: https://core.telegram.org/bots/api#passportelementerrorunspecified
     """
 
-    source: Literal["unspecified"] = "unspecified"
+    source: Literal[PassportElementErrorType.UNSPECIFIED] = PassportElementErrorType.UNSPECIFIED
     """Error source, must be *unspecified*"""
     type: str
     """Type of element of the user's Telegram Passport which has the issue"""
diff --git a/docs/api/enums/encrypted_passport_element.rst b/docs/api/enums/encrypted_passport_element.rst
new file mode 100644
index 00000000..9d79b162
--- /dev/null
+++ b/docs/api/enums/encrypted_passport_element.rst
@@ -0,0 +1,9 @@
+########################
+EncryptedPassportElement
+########################
+
+
+.. automodule:: aiogram.enums.encrypted_passport_element
+    :members:
+    :member-order: bysource
+    :undoc-members: True
diff --git a/docs/api/enums/index.rst b/docs/api/enums/index.rst
index 84a4b837..e496f5b4 100644
--- a/docs/api/enums/index.rst
+++ b/docs/api/enums/index.rst
@@ -14,12 +14,14 @@ Here is list of all available enums:
     chat_type
     content_type
     dice_emoji
+    encrypted_passport_element
     inline_query_result_type
     input_media_type
     mask_position_point
     menu_button_type
     message_entity_type
     parse_mode
+    passport_element_error_type
     poll_type
     sticker_format
     sticker_type
diff --git a/docs/api/enums/passport_element_error_type.rst b/docs/api/enums/passport_element_error_type.rst
new file mode 100644
index 00000000..c79d9b11
--- /dev/null
+++ b/docs/api/enums/passport_element_error_type.rst
@@ -0,0 +1,9 @@
+########################
+PassportElementErrorType
+########################
+
+
+.. automodule:: aiogram.enums.passport_element_error_type
+    :members:
+    :member-order: bysource
+    :undoc-members: True
diff --git a/pyproject.toml b/pyproject.toml
index c0642a0a..31e4e968 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -149,7 +149,7 @@ features = [
     "test",
 ]
 extra-dependencies = [
-    "butcher @ git+https://github.com/aiogram/butcher.git@v0.1.15"
+    "butcher @ git+https://github.com/aiogram/butcher.git@v0.1.16"
 ]
 
 [tool.hatch.envs.dev.scripts]


Test patch:
diff --git a/tests/test_api/test_methods/test_answer_web_app_query.py b/tests/test_api/test_methods/test_answer_web_app_query.py
index 6948bead..a42640a8 100644
--- a/tests/test_api/test_methods/test_answer_web_app_query.py
+++ b/tests/test_api/test_methods/test_answer_web_app_query.py
@@ -1,5 +1,5 @@
-from aiogram.methods import AnswerWebAppQuery, Request
-from aiogram.types import InlineQueryResult, SentWebAppMessage
+from aiogram.methods import AnswerWebAppQuery
+from aiogram.types import InlineQueryResultPhoto, SentWebAppMessage
 from tests.mocked_bot import MockedBot
 
 
@@ -9,7 +9,11 @@ class TestAnswerWebAppQuery:
 
         response: SentWebAppMessage = await bot.answer_web_app_query(
             web_app_query_id="test",
-            result=InlineQueryResult(),
+            result=InlineQueryResultPhoto(
+                id="test",
+                photo_url="test",
+                thumbnail_url="test",
+            ),
         )
         request = bot.get_request()
         assert response == prepare_result.result
diff --git a/tests/test_filters/test_chat_member_updated.py b/tests/test_filters/test_chat_member_updated.py
index 8592792c..46da8b8e 100644
--- a/tests/test_filters/test_chat_member_updated.py
+++ b/tests/test_filters/test_chat_member_updated.py
@@ -1,4 +1,5 @@
 from datetime import datetime
+from typing import Optional
 
 import pytest
 
@@ -24,6 +25,11 @@ from aiogram.types import (
 )
 
 
+class ChatMemberCustom(ChatMember):
+    status: str
+    is_member: Optional[bool] = None
+
+
 class TestMemberStatusMarker:
     def test_str(self):
         marker = _MemberStatusMarker("test")
@@ -113,11 +119,11 @@ class TestMemberStatusMarker:
     @pytest.mark.parametrize(
         "name,is_member,member,result",
         [
-            ["test", None, ChatMember(status="member"), False],
-            ["test", None, ChatMember(status="test"), True],
-            ["test", True, ChatMember(status="test"), False],
-            ["test", True, ChatMember(status="test", is_member=True), True],
-            ["test", True, ChatMember(status="test", is_member=False), False],
+            ["test", None, ChatMemberCustom(status="member"), False],
+            ["test", None, ChatMemberCustom(status="test"), True],
+            ["test", True, ChatMemberCustom(status="test"), False],
+            ["test", True, ChatMemberCustom(status="test", is_member=True), True],
+            ["test", True, ChatMemberCustom(status="test", is_member=False), False],
         ],
     )
     def test_check(self, name, is_member, member, result):
@@ -244,29 +250,34 @@ class TestMemberStatusTransition:
     @pytest.mark.parametrize(
         "transition,old,new,result",
         [
-            [JOIN_TRANSITION, ChatMember(status="left"), ChatMember(status="member"), True],
             [
                 JOIN_TRANSITION,
-                ChatMember(status="restricted", is_member=True),
-                ChatMember(status="member"),
+                ChatMemberCustom(status="left"),
+                ChatMemberCustom(status="member"),
+                True,
+            ],
+            [
+                JOIN_TRANSITION,
+                ChatMemberCustom(status="restricted", is_member=True),
+                ChatMemberCustom(status="member"),
                 False,
             ],
             [
                 JOIN_TRANSITION,
-                ChatMember(status="restricted", is_member=False),
-                ChatMember(status="member"),
+                ChatMemberCustom(status="restricted", is_member=False),
+                ChatMemberCustom(status="member"),
                 True,
             ],
             [
                 JOIN_TRANSITION,
-                ChatMember(status="member"),
-                ChatMember(status="restricted", is_member=False),
+                ChatMemberCustom(status="member"),
+                ChatMemberCustom(status="restricted", is_member=False),
                 False,
             ],
             [
                 LEAVE_TRANSITION,
-                ChatMember(status="member"),
-                ChatMember(status="restricted", is_member=False),
+                ChatMemberCustom(status="member"),
+                ChatMemberCustom(status="restricted", is_member=False),
                 True,
             ],
         ],