From 35a9533e8dff7812abc65e9ee4c14482f46a98ab Mon Sep 17 00:00:00 2001
From: Josh <josh.ja.butt@gmail.com>
Date: Thu, 10 Jun 2021 21:34:41 +1000
Subject: [PATCH] Type-Hint http.py

---
 discord/http.py               | 763 +++++++++++++++++++++++-----------
 discord/types/channel.py      |   5 +-
 discord/types/emoji.py        |   5 +
 discord/types/gateway.py      |  41 ++
 discord/types/guild.py        |  17 +
 discord/types/interactions.py |  21 +-
 discord/types/invite.py       |   4 +
 discord/types/member.py       |   4 +
 discord/types/template.py     |   5 +
 discord/types/threads.py      |   4 +-
 10 files changed, 617 insertions(+), 252 deletions(-)
 create mode 100644 discord/types/gateway.py

diff --git a/discord/http.py b/discord/http.py
index 1419acb65..c35254519 100644
--- a/discord/http.py
+++ b/discord/http.py
@@ -28,7 +28,21 @@ import asyncio
 import json
 import logging
 import sys
-from typing import Any, Coroutine, List, Optional, TYPE_CHECKING, TypeVar
+from typing import (
+    Any,
+    ClassVar,
+    Coroutine,
+    Dict,
+    Final,
+    Iterable,
+    List,
+    Optional,
+    Sequence,
+    TYPE_CHECKING,
+    Tuple,
+    Type,
+    TypeVar,
+)
 from urllib.parse import quote as _uriquote
 import weakref
 
@@ -41,20 +55,45 @@ from . import __version__, utils
 log = logging.getLogger(__name__)
 
 if TYPE_CHECKING:
+    from .file import File
+    from .enums import (
+        AuditLogAction,
+        InteractionResponseType,
+    )
+
     from .types import (
+        appinfo,
+        audit_log,
+        channel,
+        components,
+        emoji,
+        embed,
+        guild,
+        integration,
         interactions,
         invite,
+        member,
+        message,
+        template,
+        role,
+        user,
+        webhook,
         channel,
         widget,
         threads,
+        voice,
     )
-    from .types.snowflake import Snowflake
+    from .types.snowflake import Snowflake, SnowflakeList
+
+    from types import TracebackType
 
     T = TypeVar('T')
+    BE = TypeVar('BE', bound=BaseException)
+    MU = TypeVar('MU', bound='MaybeUnlock')
     Response = Coroutine[Any, Any, T]
 
 
-async def json_or_text(response):
+async def json_or_text(response: aiohttp.ClientResponse) -> Any:
     text = await response.text(encoding='utf-8')
     try:
         if response.headers['content-type'] == 'application/json':
@@ -67,79 +106,90 @@ async def json_or_text(response):
 
 
 class Route:
-    BASE = 'https://discord.com/api/v8'
+    BASE: ClassVar[str] = 'https://discord.com/api/v8'
 
-    def __init__(self, method, path, **parameters):
-        self.path = path
-        self.method = method
+    def __init__(self, method: str, path: str, **parameters: Any) -> None:
+        self.path: str = path
+        self.method: str = method
         url = self.BASE + self.path
         if parameters:
-            self.url = url.format_map({k: _uriquote(v) if isinstance(v, str) else v for k, v in parameters.items()})
-        else:
-            self.url = url
+            url = url.format_map({k: _uriquote(v) if isinstance(v, str) else v for k, v in parameters.items()})
+        self.url: str = url
 
         # major parameters:
-        self.channel_id = parameters.get('channel_id')
-        self.guild_id = parameters.get('guild_id')
-        self.webhook_id = parameters.get('webhook_id')
-        self.webhook_token = parameters.get('webhook_token')
+        self.channel_id: Optional[Snowflake] = parameters.get('channel_id')
+        self.guild_id: Optional[Snowflake] = parameters.get('guild_id')
+        self.webhook_id: Optional[Snowflake] = parameters.get('webhook_id')
+        self.webhook_token: Optional[str] = parameters.get('webhook_token')
 
     @property
-    def bucket(self):
+    def bucket(self) -> str:
         # the bucket is just method + path w/ major parameters
         return f'{self.channel_id}:{self.guild_id}:{self.path}'
 
 
 class MaybeUnlock:
-    def __init__(self, lock):
-        self.lock = lock
-        self._unlock = True
+    def __init__(self, lock: asyncio.Lock) -> None:
+        self.lock: asyncio.Lock = lock
+        self._unlock: bool = True
 
-    def __enter__(self):
+    def __enter__(self: MU) -> MU:
         return self
 
-    def defer(self):
+    def defer(self) -> None:
         self._unlock = False
 
-    def __exit__(self, type, value, traceback):
+    def __exit__(self,
+        exc_type: Optional[Type[BE]],
+        exc: Optional[BE],
+        traceback: Optional[TracebackType],
+    ) -> None:
         if self._unlock:
             self.lock.release()
 
 
 # For some reason, the Discord voice websocket expects this header to be
 # completely lowercase while aiohttp respects spec and does it as case-insensitive
-aiohttp.hdrs.WEBSOCKET = 'websocket'
+aiohttp.hdrs.WEBSOCKET = 'websocket'  #type: ignore
 
 
 class HTTPClient:
     """Represents an HTTP client sending HTTP requests to the Discord API."""
 
-    SUCCESS_LOG = '{method} {url} has received {text}'
-    REQUEST_LOG = '{method} {url} with {json} has returned {status}'
+    SUCCESS_LOG: Final[ClassVar[str]] = '{method} {url} has received {text}'
+    REQUEST_LOG: Final[ClassVar[str]] = '{method} {url} with {json} has returned {status}'
 
-    def __init__(self, connector=None, *, proxy=None, proxy_auth=None, loop=None, unsync_clock=True):
-        self.loop = asyncio.get_event_loop() if loop is None else loop
+    def __init__(
+        self,
+        connector: Optional[aiohttp.BaseConnector] = None,
+        *,
+        proxy: Optional[str] = None,
+        proxy_auth: Optional[aiohttp.BasicAuth] = None,
+        loop: Optional[asyncio.AbstractEventLoop] = None,
+        unsync_clock: bool = True
+    ) -> None:
+        self.loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() if loop is None else loop
         self.connector = connector
-        self.__session = None  # filled in static_login
-        self._locks = weakref.WeakValueDictionary()
-        self._global_over = asyncio.Event()
+        self.__session: Optional[aiohttp.ClientSession] = None  # filled in static_login
+        self._locks: weakref.WeakValueDictionary = weakref.WeakValueDictionary()
+        self._global_over: asyncio.Event = asyncio.Event()
         self._global_over.set()
-        self.token = None
-        self.bot_token = False
-        self.proxy = proxy
-        self.proxy_auth = proxy_auth
-        self.use_clock = not unsync_clock
+        self.token: Optional[str] = None
+        self.bot_token: bool = False
+        self.proxy: Optional[str] = proxy
+        self.proxy_auth: Optional[aiohttp.BasicAuth] = proxy_auth
+        self.use_clock: bool = not unsync_clock
 
         user_agent = 'DiscordBot (https://github.com/Rapptz/discord.py {0}) Python/{1[0]}.{1[1]} aiohttp/{2}'
-        self.user_agent = user_agent.format(__version__, sys.version_info, aiohttp.__version__)
+        self.user_agent: str = user_agent.format(__version__, sys.version_info, aiohttp.__version__)
 
-    def recreate(self):
+    def recreate(self) -> None:
         if self.__session.closed:
             self.__session = aiohttp.ClientSession(
                 connector=self.connector, ws_response_class=DiscordClientWebSocketResponse
             )
 
-    async def ws_connect(self, url, *, compress=0):
+    async def ws_connect(self, url: str, *, compress: int = 0) -> Any:
         kwargs = {
             'proxy_auth': self.proxy_auth,
             'proxy': self.proxy,
@@ -154,7 +204,14 @@ class HTTPClient:
 
         return await self.__session.ws_connect(url, **kwargs)
 
-    async def request(self, route, *, files=None, form=None, **kwargs) -> Any:
+    async def request(
+        self,
+        route: Route,
+        *,
+        files: Optional[Sequence[File]] = None,
+        form: Optional[Iterable[Dict[str, Any]]] = None,
+        **kwargs: Any
+    ) -> Any:
         bucket = route.bucket
         method = route.method
         url = route.url
@@ -289,7 +346,7 @@ class HTTPClient:
 
             raise HTTPException(r, data)
 
-    async def get_from_cdn(self, url):
+    async def get_from_cdn(self, url: str) -> bytes:
         async with self.__session.get(url) as resp:
             if resp.status == 200:
                 return await resp.read()
@@ -302,13 +359,13 @@ class HTTPClient:
 
     # state management
 
-    async def close(self):
+    async def close(self) -> None:
         if self.__session:
             await self.__session.close()
 
     # login management
 
-    async def static_login(self, token):
+    async def static_login(self, token: str) -> user.User:
         # Necessary to get aiohttp to stop complaining about session creation
         self.__session = aiohttp.ClientSession(connector=self.connector, ws_response_class=DiscordClientWebSocketResponse)
         old_token = self.token
@@ -324,24 +381,24 @@ class HTTPClient:
 
         return data
 
-    def logout(self):
+    def logout(self) -> Response[None]:
         return self.request(Route('POST', '/auth/logout'))
 
     # Group functionality
 
-    def start_group(self, user_id, recipients):
+    def start_group(self, user_id: Snowflake, recipients: List[int]) -> Response[channel.GroupDMChannel]:
         payload = {
             'recipients': recipients,
         }
 
         return self.request(Route('POST', '/users/{user_id}/channels', user_id=user_id), json=payload)
 
-    def leave_group(self, channel_id):
+    def leave_group(self, channel_id) -> Response[None]:
         return self.request(Route('DELETE', '/channels/{channel_id}', channel_id=channel_id))
 
     # Message management
 
-    def start_private_message(self, user_id):
+    def start_private_message(self, user_id: Snowflake) -> Response[channel.DMChannel]:
         payload = {
             'recipient_id': user_id,
         }
@@ -350,16 +407,16 @@ class HTTPClient:
 
     def send_message(
         self,
-        channel_id,
-        content,
+        channel_id: Snowflake,
+        content: str,
         *,
-        tts=False,
-        embed=None,
-        nonce=None,
-        allowed_mentions=None,
-        message_reference=None,
-        components=None,
-    ):
+        tts: bool = False,
+        embed: Optional[embed.Embed] = None,
+        nonce: Optional[str] =  None,
+        allowed_mentions: bool = None,
+        message_reference: bool = None,
+        components: Optional[List[components.Component]] = None,
+    ) -> Response[message.Message]:
         r = Route('POST', '/channels/{channel_id}/messages', channel_id=channel_id)
         payload = {}
 
@@ -386,26 +443,26 @@ class HTTPClient:
 
         return self.request(r, json=payload)
 
-    def send_typing(self, channel_id):
+    def send_typing(self, channel_id: Snowflake) -> Response[None]:
         return self.request(Route('POST', '/channels/{channel_id}/typing', channel_id=channel_id))
 
     def send_multipart_helper(
         self,
-        route,
+        route: Route,
         *,
-        files,
-        content=None,
-        tts=False,
-        embed=None,
-        embeds=None,
-        nonce=None,
-        allowed_mentions=None,
-        message_reference=None,
-        components=None,
-    ):
+        files: Sequence[File],
+        content: Optional[str] = None,
+        tts: bool = False,
+        embed: Optional[embed.Embed] = None,
+        embeds: Iterable[Optional[embed.Embed]] = None,
+        nonce: Optional[str] = None,
+        allowed_mentions: Optional[message.AllowedMentions] = None,
+        message_reference: Optional[message.MessageReference] = None,
+        components: Optional[List[components.Component]] = None,
+    ) -> Response[message.Message]:
         form = []
 
-        payload = {'tts': tts}
+        payload: Dict[str, Any] = {'tts': tts}
         if content:
             payload['content'] = content
         if embed:
@@ -447,17 +504,17 @@ class HTTPClient:
 
     def send_files(
         self,
-        channel_id,
+        channel_id: Snowflake,
         *,
-        files,
-        content=None,
-        tts=False,
-        embed=None,
-        nonce=None,
-        allowed_mentions=None,
-        message_reference=None,
-        components=None,
-    ):
+        files: Sequence[File],
+        content: Optional[str] = None,
+        tts: bool = False,
+        embed: Optional[embed.Embed] = None,
+        nonce: Optional[str] = None,
+        allowed_mentions: Optional[message.AllowedMentions] = None,
+        message_reference: Optional[message.MessageReference] = None,
+        components: Optional[List[components.Component]] = None,
+    ) -> Response[message.Message]:
         r = Route('POST', '/channels/{channel_id}/messages', channel_id=channel_id)
         return self.send_multipart_helper(
             r,
@@ -471,11 +528,11 @@ class HTTPClient:
             components=components,
         )
 
-    def delete_message(self, channel_id, message_id, *, reason=None):
+    def delete_message(self, channel_id: Snowflake, message_id: Snowflake, *, reason: Optional[str] = None) -> Response[None]:
         r = Route('DELETE', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id, message_id=message_id)
         return self.request(r, reason=reason)
 
-    def delete_messages(self, channel_id, message_ids, *, reason=None):
+    def delete_messages(self, channel_id: Snowflake, message_ids: SnowflakeList, *, reason: Optional[str] = None) -> Response[None]:
         r = Route('POST', '/channels/{channel_id}/messages/bulk-delete', channel_id=channel_id)
         payload = {
             'messages': message_ids,
@@ -483,11 +540,11 @@ class HTTPClient:
 
         return self.request(r, json=payload, reason=reason)
 
-    def edit_message(self, channel_id, message_id, **fields):
+    def edit_message(self, channel_id: Snowflake, message_id: Snowflake, **fields: Any) -> Response[message.Message]:
         r = Route('PATCH', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id, message_id=message_id)
         return self.request(r, json=fields)
 
-    def add_reaction(self, channel_id, message_id, emoji):
+    def add_reaction(self, channel_id: Snowflake, message_id: Snowflake, emoji: str) -> Response[None]:
         r = Route(
             'PUT',
             '/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/@me',
@@ -497,7 +554,7 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def remove_reaction(self, channel_id, message_id, emoji, member_id):
+    def remove_reaction(self, channel_id: Snowflake, message_id: Snowflake, emoji: str, member_id: Snowflake) -> Response[None]:
         r = Route(
             'DELETE',
             '/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/{member_id}',
@@ -508,7 +565,7 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def remove_own_reaction(self, channel_id, message_id, emoji):
+    def remove_own_reaction(self, channel_id: Snowflake, message_id: Snowflake, emoji: str) -> Response[None]:
         r = Route(
             'DELETE',
             '/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/@me',
@@ -518,7 +575,14 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def get_reaction_users(self, channel_id, message_id, emoji, limit, after=None):
+    def get_reaction_users(
+        self,
+        channel_id: Snowflake,
+        message_id: Snowflake,
+        emoji: str,
+        limit: int,
+        after: Optional[Snowflake] = None,
+    ) -> Response[List[user.User]]:
         r = Route(
             'GET',
             '/channels/{channel_id}/messages/{message_id}/reactions/{emoji}',
@@ -534,7 +598,7 @@ class HTTPClient:
             params['after'] = after
         return self.request(r, params=params)
 
-    def clear_reactions(self, channel_id, message_id):
+    def clear_reactions(self, channel_id: Snowflake, message_id: Snowflake) -> Response[None]:
         r = Route(
             'DELETE',
             '/channels/{channel_id}/messages/{message_id}/reactions',
@@ -544,7 +608,7 @@ class HTTPClient:
 
         return self.request(r)
 
-    def clear_single_reaction(self, channel_id, message_id, emoji):
+    def clear_single_reaction(self, channel_id: Snowflake, message_id: Snowflake, emoji: str) -> Response[None]:
         r = Route(
             'DELETE',
             '/channels/{channel_id}/messages/{message_id}/reactions/{emoji}',
@@ -554,16 +618,23 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def get_message(self, channel_id, message_id):
+    def get_message(self, channel_id: Snowflake, message_id: Snowflake) -> Response[message.Message]:
         r = Route('GET', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id, message_id=message_id)
         return self.request(r)
 
-    def get_channel(self, channel_id):
+    def get_channel(self, channel_id: Snowflake) -> Response[channel.Channel]:
         r = Route('GET', '/channels/{channel_id}', channel_id=channel_id)
         return self.request(r)
 
-    def logs_from(self, channel_id, limit, before=None, after=None, around=None):
-        params = {
+    def logs_from(
+        self,
+        channel_id: Snowflake,
+        limit: int,
+        before: Optional[Snowflake] = None,
+        after: Optional[Snowflake] = None,
+        around: Optional[Snowflake] = None,
+    ) -> Response[List[message.Message]]:
+        params: Dict[str, Any] = {
             'limit': limit,
         }
 
@@ -576,7 +647,7 @@ class HTTPClient:
 
         return self.request(Route('GET', '/channels/{channel_id}/messages', channel_id=channel_id), params=params)
 
-    def publish_message(self, channel_id, message_id):
+    def publish_message(self, channel_id: Snowflake, message_id: Snowflake) -> Response[message.Message]:
         return self.request(
             Route(
                 'POST',
@@ -586,7 +657,7 @@ class HTTPClient:
             )
         )
 
-    def pin_message(self, channel_id, message_id, reason=None):
+    def pin_message(self, channel_id: Snowflake, message_id: Snowflake, reason: Optional[str] = None) -> Response[None]:
         r = Route(
             'PUT',
             '/channels/{channel_id}/pins/{message_id}',
@@ -595,7 +666,7 @@ class HTTPClient:
         )
         return self.request(r, reason=reason)
 
-    def unpin_message(self, channel_id, message_id, reason=None):
+    def unpin_message(self, channel_id: Snowflake, message_id: Snowflake, reason: Optional[str] = None) -> Response[None]:
         r = Route(
             'DELETE',
             '/channels/{channel_id}/pins/{message_id}',
@@ -604,12 +675,12 @@ class HTTPClient:
         )
         return self.request(r, reason=reason)
 
-    def pins_from(self, channel_id):
+    def pins_from(self, channel_id: Snowflake) -> Response[List[message.Message]]:
         return self.request(Route('GET', '/channels/{channel_id}/pins', channel_id=channel_id))
 
     # Member management
 
-    def kick(self, user_id, guild_id, reason=None):
+    def kick(self, user_id: Snowflake, guild_id: Snowflake, reason: Optional[str] = None) -> Response[None]:
         r = Route('DELETE', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
         if reason:
             # thanks aiohttp
@@ -617,7 +688,13 @@ class HTTPClient:
 
         return self.request(r)
 
-    def ban(self, user_id, guild_id, delete_message_days=1, reason=None):
+    def ban(
+        self,
+        user_id: Snowflake,
+        guild_id: Snowflake,
+        delete_message_days: int = 1,
+        reason: Optional[str] = None,
+    ) -> Response[None]:
         r = Route('PUT', '/guilds/{guild_id}/bans/{user_id}', guild_id=guild_id, user_id=user_id)
         params = {
             'delete_message_days': delete_message_days,
@@ -629,11 +706,19 @@ class HTTPClient:
 
         return self.request(r, params=params)
 
-    def unban(self, user_id, guild_id, *, reason=None):
+    def unban(self, user_id: Snowflake, guild_id: Snowflake, *, reason: Optional[str] = None) -> Response[None]:
         r = Route('DELETE', '/guilds/{guild_id}/bans/{user_id}', guild_id=guild_id, user_id=user_id)
         return self.request(r, reason=reason)
 
-    def guild_voice_state(self, user_id, guild_id, *, mute=None, deafen=None, reason=None):
+    def guild_voice_state(
+        self,
+        user_id: Snowflake,
+        guild_id: Snowflake,
+        *,
+        mute: Optional[bool] = None,
+        deafen: Optional[bool] = None,
+        reason: Optional[str] = None,
+    ) -> Response[member.Member]:
         r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
         payload = {}
         if mute is not None:
@@ -644,7 +729,7 @@ class HTTPClient:
 
         return self.request(r, json=payload, reason=reason)
 
-    def edit_profile(self, username, avatar):
+    def edit_profile(self, username: Optional[str], avatar: Optional[bytes]) -> Response[user.User]:
         payload = {}
         if avatar is not None:
             payload['avatar'] = avatar
@@ -653,35 +738,61 @@ class HTTPClient:
 
         return self.request(Route('PATCH', '/users/@me'), json=payload)
 
-    def change_my_nickname(self, guild_id, nickname, *, reason=None):
+    def change_my_nickname(
+        self,
+        guild_id: Snowflake,
+        nickname: str,
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[member.Nickname]:
         r = Route('PATCH', '/guilds/{guild_id}/members/@me/nick', guild_id=guild_id)
         payload = {
             'nick': nickname,
         }
         return self.request(r, json=payload, reason=reason)
 
-    def change_nickname(self, guild_id, user_id, nickname, *, reason=None):
+    def change_nickname(
+        self,
+        guild_id: Snowflake,
+        user_id: Snowflake,
+        nickname: str,
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[member.Member]:
         r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
         payload = {
             'nick': nickname,
         }
         return self.request(r, json=payload, reason=reason)
 
-    def edit_my_voice_state(self, guild_id, payload):
+    def edit_my_voice_state(self, guild_id: Snowflake, payload: voice.VoiceState) -> Response[None]:
         r = Route('PATCH', '/guilds/{guild_id}/voice-states/@me', guild_id=guild_id)
         return self.request(r, json=payload)
 
-    def edit_voice_state(self, guild_id, user_id, payload):
+    def edit_voice_state(self, guild_id: Snowflake, user_id: Snowflake, payload: voice.VoiceState) -> Response[None]:
         r = Route('PATCH', '/guilds/{guild_id}/voice-states/{user_id}', guild_id=guild_id, user_id=user_id)
         return self.request(r, json=payload)
 
-    def edit_member(self, guild_id, user_id, *, reason=None, **fields):
+    def edit_member(
+        self,
+        guild_id: Snowflake,
+        user_id: Snowflake,
+        *,
+        reason: Optional[str] = None,
+        **fields: Any,
+    ) -> Response[member.Member]:
         r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
         return self.request(r, json=fields, reason=reason)
 
     # Channel management
 
-    def edit_channel(self, channel_id, *, reason=None, **options):
+    def edit_channel(
+        self,
+        channel_id: Snowflake,
+        *,
+        reason: Optional[str] = None,
+        **options: Any,
+    ) -> Response[channel.Channel]:
         r = Route('PATCH', '/channels/{channel_id}', channel_id=channel_id)
         valid_keys = (
             'name',
@@ -703,11 +814,24 @@ class HTTPClient:
         payload = {k: v for k, v in options.items() if k in valid_keys}
         return self.request(r, reason=reason, json=payload)
 
-    def bulk_channel_update(self, guild_id, data, *, reason=None):
+    def bulk_channel_update(
+        self,
+        guild_id: Snowflake,
+        data: List[guild.ChannelPositionUpdate],
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[None]:
         r = Route('PATCH', '/guilds/{guild_id}/channels', guild_id=guild_id)
         return self.request(r, json=data, reason=reason)
 
-    def create_channel(self, guild_id, channel_type, *, reason=None, **options):
+    def create_channel(
+        self,
+        guild_id: Snowflake,
+        channel_type: channel.ChannelType,
+        *,
+        reason: Optional[str] = None,
+        **options: Any,
+    ) -> Response[channel.GuildChannel]:
         payload = {
             'type': channel_type,
         }
@@ -730,19 +854,24 @@ class HTTPClient:
 
         return self.request(Route('POST', '/guilds/{guild_id}/channels', guild_id=guild_id), json=payload, reason=reason)
 
-    def delete_channel(self, channel_id, *, reason=None):
+    def delete_channel(
+        self,
+        channel_id: Snowflake,
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[None]:
         return self.request(Route('DELETE', '/channels/{channel_id}', channel_id=channel_id), reason=reason)
 
     # Thread management
 
     def start_public_thread(
         self,
-        channel_id: int,
-        message_id: int,
+        channel_id: Snowflake,
+        message_id: Snowflake,
         *,
         name: str,
-        auto_archive_duration: int,
-        type: int,
+        auto_archive_duration: threads.ThreadArchiveDuration,
+        type: threads.ThreadType,
     ) -> Response[threads.Thread]:
         payload = {
             'name': name,
@@ -757,11 +886,11 @@ class HTTPClient:
 
     def start_private_thread(
         self,
-        channel_id: int,
+        channel_id: Snowflake,
         *,
         name: str,
-        auto_archive_duration: int,
-        type: int,
+        auto_archive_duration: threads.ThreadArchiveDuration,
+        type: threads.ThreadType,
     ) -> Response[threads.Thread]:
         payload = {
             'name': name,
@@ -772,23 +901,23 @@ class HTTPClient:
         route = Route('POST', '/channels/{channel_id}/threads', channel_id=channel_id)
         return self.request(route, json=payload)
 
-    def join_thread(self, channel_id: int):
+    def join_thread(self, channel_id: Snowflake) -> Response[None]:
         return self.request(Route('POST', '/channels/{channel_id}/thread-members/@me', channel_id=channel_id))
 
-    def add_user_to_thread(self, channel_id: int, user_id: int):
+    def add_user_to_thread(self, channel_id: Snowflake, user_id: Snowflake) -> Response[None]:
         return self.request(
             Route('PUT', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id)
         )
 
-    def leave_thread(self, channel_id: int):
+    def leave_thread(self, channel_id: Snowflake) -> Response[None]:
         return self.request(Route('DELETE', '/channels/{channel_id}/thread-members/@me', channel_id=channel_id))
 
-    def remove_user_from_thread(self, channel_id: int, user_id: int):
+    def remove_user_from_thread(self, channel_id: Snowflake, user_id: Snowflake) -> Response[None]:
         route = Route('DELETE', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id)
         return self.request(route)
 
     def get_public_archived_threads(
-        self, channel_id: int, before=None, limit: int = 50
+        self, channel_id: Snowflake, before: Optional[Snowflake] = None, limit: int = 50
     ) -> Response[threads.ThreadPaginationPayload]:
         route = Route('GET', '/channels/{channel_id}/threads/archived/public', channel_id=channel_id)
 
@@ -799,7 +928,7 @@ class HTTPClient:
         return self.request(route, params=params)
 
     def get_private_archived_threads(
-        self, channel_id: int, before=None, limit: int = 50
+        self, channel_id: Snowflake, before: Optional[Snowflake] = None, limit: int = 50
     ) -> Response[threads.ThreadPaginationPayload]:
         route = Route('GET', '/channels/{channel_id}/threads/archived/private', channel_id=channel_id)
 
@@ -810,7 +939,7 @@ class HTTPClient:
         return self.request(route, params=params)
 
     def get_joined_private_archived_threads(
-        self, channel_id: int, before=None, limit: int = 50
+        self, channel_id: Snowflake, before: Optional[Snowflake] = None, limit: int = 50
     ) -> Response[threads.ThreadPaginationPayload]:
         route = Route('GET', '/channels/{channel_id}/users/@me/threads/archived/private', channel_id=channel_id)
         params = {}
@@ -819,18 +948,25 @@ class HTTPClient:
         params['limit'] = limit
         return self.request(route, params=params)
 
-    def get_active_threads(self, channel_id: int) -> Response[threads.ThreadPaginationPayload]:
+    def get_active_threads(self, channel_id: Snowflake) -> Response[threads.ThreadPaginationPayload]:
         route = Route('GET', '/channels/{channel_id}/threads/active', channel_id=channel_id)
         return self.request(route)
 
-    def get_thread_members(self, channel_id: int) -> Response[List[threads.ThreadMember]]:
+    def get_thread_members(self, channel_id: Snowflake) -> Response[List[threads.ThreadMember]]:
         route = Route('GET', '/channels/{channel_id}/thread-members', channel_id=channel_id)
         return self.request(route)
 
     # Webhook management
 
-    def create_webhook(self, channel_id, *, name, avatar=None, reason=None):
-        payload = {
+    def create_webhook(
+        self,
+        channel_id: Snowflake,
+        *,
+        name: str,
+        avatar: Optional[bytes] = None,
+        reason: Optional[str] = None,
+    ) -> Response[webhook.Webhook]:
+        payload: Dict[str, Any] = {
             'name': name,
         }
         if avatar is not None:
@@ -839,16 +975,21 @@ class HTTPClient:
         r = Route('POST', '/channels/{channel_id}/webhooks', channel_id=channel_id)
         return self.request(r, json=payload, reason=reason)
 
-    def channel_webhooks(self, channel_id):
+    def channel_webhooks(self, channel_id: Snowflake) -> Response[List[webhook.Webhook]]:
         return self.request(Route('GET', '/channels/{channel_id}/webhooks', channel_id=channel_id))
 
-    def guild_webhooks(self, guild_id):
+    def guild_webhooks(self, guild_id: Snowflake) -> Response[List[webhook.Webhook]]:
         return self.request(Route('GET', '/guilds/{guild_id}/webhooks', guild_id=guild_id))
 
-    def get_webhook(self, webhook_id):
+    def get_webhook(self, webhook_id: Snowflake) -> Response[webhook.Webhook]:
         return self.request(Route('GET', '/webhooks/{webhook_id}', webhook_id=webhook_id))
 
-    def follow_webhook(self, channel_id, webhook_channel_id, reason=None):
+    def follow_webhook(
+        self,
+        channel_id: Snowflake,
+        webhook_channel_id: Snowflake,
+        reason: Optional[str] = None,
+    ) -> Response[None]:
         payload = {
             'webhook_channel_id': str(webhook_channel_id),
         }
@@ -858,8 +999,13 @@ class HTTPClient:
 
     # Guild management
 
-    def get_guilds(self, limit, before=None, after=None):
-        params = {
+    def get_guilds(
+        self,
+        limit: int,
+        before: Optional[Snowflake] = None,
+        after: Optional[Snowflake] = None,
+    ) -> Response[List[guild.Guild]]:
+        params: Dict[str, Any] = {
             'limit': limit,
         }
 
@@ -870,16 +1016,16 @@ class HTTPClient:
 
         return self.request(Route('GET', '/users/@me/guilds'), params=params)
 
-    def leave_guild(self, guild_id):
+    def leave_guild(self, guild_id: Snowflake) -> Response[None]:
         return self.request(Route('DELETE', '/users/@me/guilds/{guild_id}', guild_id=guild_id))
 
-    def get_guild(self, guild_id):
+    def get_guild(self, guild_id: Snowflake) -> Response[guild.Guild]:
         return self.request(Route('GET', '/guilds/{guild_id}', guild_id=guild_id))
 
-    def delete_guild(self, guild_id):
+    def delete_guild(self, guild_id: Snowflake) -> Response[None]:
         return self.request(Route('DELETE', '/guilds/{guild_id}', guild_id=guild_id))
 
-    def create_guild(self, name, region, icon):
+    def create_guild(self, name: str, region: str, icon: bytes) -> Response[guild.Guild]:
         payload = {
             'name': name,
             'icon': icon,
@@ -888,7 +1034,7 @@ class HTTPClient:
 
         return self.request(Route('POST', '/guilds'), json=payload)
 
-    def edit_guild(self, guild_id, *, reason=None, **fields):
+    def edit_guild(self, guild_id: Snowflake, *, reason: Optional[str] = None, **fields: Any) -> Response[guild.Guild]:
         valid_keys = (
             'name',
             'region',
@@ -915,19 +1061,19 @@ class HTTPClient:
 
         return self.request(Route('PATCH', '/guilds/{guild_id}', guild_id=guild_id), json=payload, reason=reason)
 
-    def get_template(self, code):
+    def get_template(self, code: str) -> Response[template.Template]:
         return self.request(Route('GET', '/guilds/templates/{code}', code=code))
 
-    def guild_templates(self, guild_id):
+    def guild_templates(self, guild_id: Snowflake) -> Response[List[template.Template]]:
         return self.request(Route('GET', '/guilds/{guild_id}/templates', guild_id=guild_id))
 
-    def create_template(self, guild_id, payload):
+    def create_template(self, guild_id: Snowflake, payload: template.CreateTemplate) -> Response[template.Template]:
         return self.request(Route('POST', '/guilds/{guild_id}/templates', guild_id=guild_id), json=payload)
 
-    def sync_template(self, guild_id, code):
+    def sync_template(self, guild_id: Snowflake, code: str) -> Response[template.Template]:
         return self.request(Route('PUT', '/guilds/{guild_id}/templates/{code}', guild_id=guild_id, code=code))
 
-    def edit_template(self, guild_id, code, payload):
+    def edit_template(self, guild_id: Snowflake, code: str, payload) -> Response[template.Template]:
         valid_keys = (
             'name',
             'description',
@@ -937,10 +1083,10 @@ class HTTPClient:
             Route('PATCH', '/guilds/{guild_id}/templates/{code}', guild_id=guild_id, code=code), json=payload
         )
 
-    def delete_template(self, guild_id, code):
+    def delete_template(self, guild_id: Snowflake, code: str) -> Response[None]:
         return self.request(Route('DELETE', '/guilds/{guild_id}/templates/{code}', guild_id=guild_id, code=code))
 
-    def create_from_template(self, code, name, region, icon):
+    def create_from_template(self, code: str, name: str, region: str, icon: bytes) -> Response[guild.Guild]:
         payload = {
             'name': name,
             'icon': icon,
@@ -948,24 +1094,24 @@ class HTTPClient:
         }
         return self.request(Route('POST', '/guilds/templates/{code}', code=code), json=payload)
 
-    def get_bans(self, guild_id):
+    def get_bans(self, guild_id: Snowflake) -> Response[List[guild.Ban]]:
         return self.request(Route('GET', '/guilds/{guild_id}/bans', guild_id=guild_id))
 
-    def get_ban(self, user_id, guild_id):
+    def get_ban(self, user_id: Snowflake, guild_id: Snowflake) -> Response[guild.Ban]:
         return self.request(Route('GET', '/guilds/{guild_id}/bans/{user_id}', guild_id=guild_id, user_id=user_id))
 
-    def get_vanity_code(self, guild_id):
+    def get_vanity_code(self, guild_id: Snowflake) -> Response[invite.VanityInvite]:
         return self.request(Route('GET', '/guilds/{guild_id}/vanity-url', guild_id=guild_id))
 
-    def change_vanity_code(self, guild_id, code, *, reason=None):
-        payload = {'code': code}
+    def change_vanity_code(self, guild_id: Snowflake, code: str, *, reason: Optional[str] = None) -> Response[None]:
+        payload: Dict[str, Any] = {'code': code}
         return self.request(Route('PATCH', '/guilds/{guild_id}/vanity-url', guild_id=guild_id), json=payload, reason=reason)
 
-    def get_all_guild_channels(self, guild_id):
+    def get_all_guild_channels(self, guild_id: Snowflake) -> Response[List[guild.GuildChannel]]:
         return self.request(Route('GET', '/guilds/{guild_id}/channels', guild_id=guild_id))
 
-    def get_members(self, guild_id, limit, after):
-        params = {
+    def get_members(self, guild_id: Snowflake, limit: int, after: Optional[Snowflake]) -> Response[List[member.Member]]:
+        params: Dict[str, Any] = {
             'limit': limit,
         }
         if after:
@@ -974,11 +1120,19 @@ class HTTPClient:
         r = Route('GET', '/guilds/{guild_id}/members', guild_id=guild_id)
         return self.request(r, params=params)
 
-    def get_member(self, guild_id, member_id):
+    def get_member(self, guild_id: Snowflake, member_id: Snowflake) -> Response[member.Member]:
         return self.request(Route('GET', '/guilds/{guild_id}/members/{member_id}', guild_id=guild_id, member_id=member_id))
 
-    def prune_members(self, guild_id, days, compute_prune_count, roles, *, reason=None):
-        payload = {
+    def prune_members(
+        self,
+        guild_id: Snowflake,
+        days: int,
+        compute_prune_count: bool,
+        roles: List[str],
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[guild.GuildPrune]:
+        payload: Dict[str, Any] = {
             'days': days,
             'compute_prune_count': 'true' if compute_prune_count else 'false',
         }
@@ -987,8 +1141,13 @@ class HTTPClient:
 
         return self.request(Route('POST', '/guilds/{guild_id}/prune', guild_id=guild_id), json=payload, reason=reason)
 
-    def estimate_pruned_members(self, guild_id, days, roles):
-        params = {
+    def estimate_pruned_members(
+        self,
+        guild_id: Snowflake,
+        days: int,
+        roles: List[str],
+    ) -> Response[guild.GuildPrune]:
+        params: Dict[str, Any] = {
             'days': days,
         }
         if roles:
@@ -996,13 +1155,21 @@ class HTTPClient:
 
         return self.request(Route('GET', '/guilds/{guild_id}/prune', guild_id=guild_id), params=params)
 
-    def get_all_custom_emojis(self, guild_id):
+    def get_all_custom_emojis(self, guild_id: Snowflake) -> Response[List[emoji.Emoji]]:
         return self.request(Route('GET', '/guilds/{guild_id}/emojis', guild_id=guild_id))
 
-    def get_custom_emoji(self, guild_id, emoji_id):
+    def get_custom_emoji(self, guild_id: Snowflake, emoji_id: Snowflake) -> Response[emoji.Emoji]:
         return self.request(Route('GET', '/guilds/{guild_id}/emojis/{emoji_id}', guild_id=guild_id, emoji_id=emoji_id))
 
-    def create_custom_emoji(self, guild_id, name, image, *, roles=None, reason=None):
+    def create_custom_emoji(
+        self,
+        guild_id: Snowflake,
+        name: str,
+        image: bytes,
+        *,
+        roles: Optional[SnowflakeList] = None,
+        reason: Optional[str] = None,
+    ) -> Response[emoji.Emoji]:
         payload = {
             'name': name,
             'image': image,
@@ -1012,20 +1179,33 @@ class HTTPClient:
         r = Route('POST', '/guilds/{guild_id}/emojis', guild_id=guild_id)
         return self.request(r, json=payload, reason=reason)
 
-    def delete_custom_emoji(self, guild_id, emoji_id, *, reason=None):
+    def delete_custom_emoji(
+        self,
+        guild_id: Snowflake,
+        emoji_id: Snowflake,
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[None]:
         r = Route('DELETE', '/guilds/{guild_id}/emojis/{emoji_id}', guild_id=guild_id, emoji_id=emoji_id)
         return self.request(r, reason=reason)
 
-    def edit_custom_emoji(self, guild_id: int, emoji_id: int, *, payload, reason: Optional[str] = None):
+    def edit_custom_emoji(
+        self,
+        guild_id: Snowflake,
+        emoji_id: Snowflake,
+        *,
+        payload: Dict[str, Any],
+        reason: Optional[str] = None,
+    ) -> Response[emoji.Emoji]:
         r = Route('PATCH', '/guilds/{guild_id}/emojis/{emoji_id}', guild_id=guild_id, emoji_id=emoji_id)
         return self.request(r, json=payload, reason=reason)
 
-    def get_all_integrations(self, guild_id):
+    def get_all_integrations(self, guild_id: Snowflake) -> Response[List[integration.Integration]]:
         r = Route('GET', '/guilds/{guild_id}/integrations', guild_id=guild_id)
 
         return self.request(r)
 
-    def create_integration(self, guild_id, type, id):
+    def create_integration(self, guild_id: Snowflake, type: integration.IntegrationType, id: int) -> Response[None]:
         payload = {
             'type': type,
             'id': id,
@@ -1034,29 +1214,37 @@ class HTTPClient:
         r = Route('POST', '/guilds/{guild_id}/integrations', guild_id=guild_id)
         return self.request(r, json=payload)
 
-    def edit_integration(self, guild_id, integration_id, **payload):
+    def edit_integration(self, guild_id: Snowflake, integration_id: Snowflake, **payload: Any) -> Response[None]:
         r = Route(
             'PATCH', '/guilds/{guild_id}/integrations/{integration_id}', guild_id=guild_id, integration_id=integration_id
         )
 
         return self.request(r, json=payload)
 
-    def sync_integration(self, guild_id, integration_id):
+    def sync_integration(self, guild_id: Snowflake, integration_id: Snowflake) -> Response[None]:
         r = Route(
             'POST', '/guilds/{guild_id}/integrations/{integration_id}/sync', guild_id=guild_id, integration_id=integration_id
         )
 
         return self.request(r)
 
-    def delete_integration(self, guild_id, integration_id):
+    def delete_integration(self, guild_id: Snowflake, integration_id: Snowflake) -> Response[None]:
         r = Route(
             'DELETE', '/guilds/{guild_id}/integrations/{integration_id}', guild_id=guild_id, integration_id=integration_id
         )
 
         return self.request(r)
 
-    def get_audit_logs(self, guild_id, limit=100, before=None, after=None, user_id=None, action_type=None):
-        params = {'limit': limit}
+    def get_audit_logs(
+        self,
+        guild_id: Snowflake,
+        limit: int = 100,
+        before: Optional[Snowflake] = None,
+        after: Optional[Snowflake] = None,
+        user_id: Optional[Snowflake] = None,
+        action_type: Optional[AuditLogAction] = None,
+    ) -> Response[audit_log.AuditLog]:
+        params: Dict[str, Any] = {'limit': limit}
         if before:
             params['before'] = before
         if after:
@@ -1079,16 +1267,16 @@ class HTTPClient:
 
     def create_invite(
         self,
-        channel_id: int,
+        channel_id: Snowflake,
         *,
         reason: Optional[str] = None,
         max_age: int = 0,
         max_uses: int = 0,
         temporary: bool = False,
         unique: bool = True,
-        target_type: Optional[int] = None,
-        target_user_id: Optional[int] = None,
-        target_application_id: Optional[int] = None
+        target_type: Optional[invite.InviteTargetType] = None,
+        target_user_id: Optional[Snowflake] = None,
+        target_application_id: Optional[Snowflake] = None
     ) -> Response[invite.Invite]:
         r = Route('POST', '/channels/{channel_id}/invites', channel_id=channel_id)
         payload = {
@@ -1122,36 +1310,49 @@ class HTTPClient:
     def invites_from_channel(self, channel_id: Snowflake) -> Response[List[invite.Invite]]:
         return self.request(Route('GET', '/channels/{channel_id}/invites', channel_id=channel_id))
 
-    def delete_invite(self, invite_id: str, *, reason: bool = None) -> Response[None]:
+    def delete_invite(self, invite_id: str, *, reason: Optional[str] = None) -> Response[None]:
         return self.request(Route('DELETE', '/invites/{invite_id}', invite_id=invite_id), reason=reason)
 
     # Role management
 
-    def get_roles(self, guild_id):
+    def get_roles(self, guild_id: Snowflake) -> Response[List[role.Role]]:
         return self.request(Route('GET', '/guilds/{guild_id}/roles', guild_id=guild_id))
 
-    def edit_role(self, guild_id, role_id, *, reason=None, **fields):
+    def edit_role(self, guild_id: Snowflake, role_id: Snowflake, *, reason: Optional[str] = None, **fields: Any) -> Response[role.Role]:
         r = Route('PATCH', '/guilds/{guild_id}/roles/{role_id}', guild_id=guild_id, role_id=role_id)
         valid_keys = ('name', 'permissions', 'color', 'hoist', 'mentionable')
         payload = {k: v for k, v in fields.items() if k in valid_keys}
         return self.request(r, json=payload, reason=reason)
 
-    def delete_role(self, guild_id, role_id, *, reason=None):
+    def delete_role(self, guild_id: Snowflake, role_id: Snowflake, *, reason: Optional[str] = None) -> Response[None]:
         r = Route('DELETE', '/guilds/{guild_id}/roles/{role_id}', guild_id=guild_id, role_id=role_id)
         return self.request(r, reason=reason)
 
-    def replace_roles(self, user_id, guild_id, role_ids, *, reason=None):
+    def replace_roles(
+        self,
+        user_id: Snowflake,
+        guild_id: Snowflake,
+        role_ids: List[int],
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[member.Member]:
         return self.edit_member(guild_id=guild_id, user_id=user_id, roles=role_ids, reason=reason)
 
-    def create_role(self, guild_id, *, reason=None, **fields):
+    def create_role(self, guild_id: Snowflake, *, reason: Optional[str] = None, **fields: Any) -> Response[role.Role]:
         r = Route('POST', '/guilds/{guild_id}/roles', guild_id=guild_id)
         return self.request(r, json=fields, reason=reason)
 
-    def move_role_position(self, guild_id, positions, *, reason=None):
+    def move_role_position(
+        self,
+        guild_id: Snowflake,
+        positions: List[guild.RolePositionUpdate],
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[List[role.Role]]:
         r = Route('PATCH', '/guilds/{guild_id}/roles', guild_id=guild_id)
         return self.request(r, json=positions, reason=reason)
 
-    def add_role(self, guild_id, user_id, role_id, *, reason=None):
+    def add_role(self, guild_id: Snowflake, user_id: Snowflake, role_id: Snowflake, *, reason: Optional[str] = None) -> Response[None]:
         r = Route(
             'PUT',
             '/guilds/{guild_id}/members/{user_id}/roles/{role_id}',
@@ -1161,7 +1362,7 @@ class HTTPClient:
         )
         return self.request(r, reason=reason)
 
-    def remove_role(self, guild_id, user_id, role_id, *, reason=None):
+    def remove_role(self, guild_id: Snowflake, user_id: Snowflake, role_id: Snowflake, *, reason: Optional[str] = None) -> Response[None]:
         r = Route(
             'DELETE',
             '/guilds/{guild_id}/members/{user_id}/roles/{role_id}',
@@ -1171,18 +1372,40 @@ class HTTPClient:
         )
         return self.request(r, reason=reason)
 
-    def edit_channel_permissions(self, channel_id, target, allow, deny, type, *, reason=None):
+    def edit_channel_permissions(
+        self,
+        channel_id: Snowflake,
+        target: Snowflake,
+        allow: str,
+        deny: str,
+        type: channel.OverwriteType,
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[None]:
         payload = {'id': target, 'allow': allow, 'deny': deny, 'type': type}
         r = Route('PUT', '/channels/{channel_id}/permissions/{target}', channel_id=channel_id, target=target)
         return self.request(r, json=payload, reason=reason)
 
-    def delete_channel_permissions(self, channel_id, target, *, reason=None):
+    def delete_channel_permissions(
+        self,
+        channel_id: Snowflake,
+        target: channel.OverwriteType,
+        *,
+        reason: Optional[str] = None
+    ) -> Response[None]:
         r = Route('DELETE', '/channels/{channel_id}/permissions/{target}', channel_id=channel_id, target=target)
         return self.request(r, reason=reason)
 
     # Voice management
 
-    def move_member(self, user_id, guild_id, channel_id, *, reason=None):
+    def move_member(
+        self,
+        user_id: Snowflake,
+        guild_id: Snowflake,
+        channel_id: Snowflake,
+        *,
+        reason: Optional[str] = None,
+    ) -> Response[member.Member]:
         return self.edit_member(guild_id=guild_id, user_id=user_id, channel_id=channel_id, reason=reason)
 
     # Stage instance management
@@ -1214,10 +1437,10 @@ class HTTPClient:
 
     # Application commands (global)
 
-    def get_global_commands(self, application_id) -> Response[List[interactions.ApplicationCommand]]:
+    def get_global_commands(self, application_id: Snowflake) -> Response[List[interactions.ApplicationCommand]]:
         return self.request(Route('GET', '/applications/{application_id}/commands', application_id=application_id))
 
-    def get_global_command(self, application_id, command_id) -> Response[interactions.ApplicationCommand]:
+    def get_global_command(self, application_id: Snowflake, command_id: Snowflake) -> Response[interactions.ApplicationCommand]:
         r = Route(
             'GET',
             '/applications/{application_id}/commands/{command_id}',
@@ -1226,17 +1449,21 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def upsert_global_command(self, application_id, payload) -> Response[interactions.ApplicationCommand]:
+    def upsert_global_command(self, application_id: Snowflake, payload) -> Response[interactions.ApplicationCommand]:
         r = Route('POST', '/applications/{application_id}/commands', application_id=application_id)
         return self.request(r, json=payload)
 
-    def edit_global_command(self, application_id, command_id, payload) -> Response[interactions.ApplicationCommand]:
+    def edit_global_command(self,
+        application_id: Snowflake,
+        command_id: Snowflake,
+        payload: interactions.EditApplicationCommand,
+    ) -> Response[interactions.ApplicationCommand]:
         valid_keys = (
             'name',
             'description',
             'options',
         )
-        payload = {k: v for k, v in payload.items() if k in valid_keys}
+        payload = {k: v for k, v in payload.items() if k in valid_keys}  # type: ignore
         r = Route(
             'PATCH',
             '/applications/{application_id}/commands/{command_id}',
@@ -1245,7 +1472,7 @@ class HTTPClient:
         )
         return self.request(r, json=payload)
 
-    def delete_global_command(self, application_id, command_id):
+    def delete_global_command(self, application_id: Snowflake, command_id: Snowflake) -> Response[None]:
         r = Route(
             'DELETE',
             '/applications/{application_id}/commands/{command_id}',
@@ -1254,13 +1481,13 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def bulk_upsert_global_commands(self, application_id, payload) -> Response[List[interactions.ApplicationCommand]]:
+    def bulk_upsert_global_commands(self, application_id: Snowflake, payload) -> Response[List[interactions.ApplicationCommand]]:
         r = Route('PUT', '/applications/{application_id}/commands', application_id=application_id)
         return self.request(r, json=payload)
 
     # Application commands (guild)
 
-    def get_guild_commands(self, application_id, guild_id) -> Response[List[interactions.ApplicationCommand]]:
+    def get_guild_commands(self, application_id: Snowflake, guild_id: Snowflake) -> Response[List[interactions.ApplicationCommand]]:
         r = Route(
             'GET',
             '/applications/{application_id}/guilds/{guild_id}/commands',
@@ -1269,7 +1496,12 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def get_guild_command(self, application_id, guild_id, command_id) -> Response[interactions.ApplicationCommand]:
+    def get_guild_command(
+        self,
+        application_id: Snowflake,
+        guild_id: Snowflake,
+        command_id: Snowflake,
+    ) -> Response[interactions.ApplicationCommand]:
         r = Route(
             'GET',
             '/applications/{application_id}/guilds/{guild_id}/commands/{command_id}',
@@ -1279,7 +1511,12 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def upsert_guild_command(self, application_id, guild_id, payload) -> Response[interactions.ApplicationCommand]:
+    def upsert_guild_command(
+        self,
+        application_id: Snowflake,
+        guild_id: Snowflake,
+        payload: interactions.EditApplicationCommand,
+    ) -> Response[interactions.ApplicationCommand]:
         r = Route(
             'POST',
             '/applications/{application_id}/guilds/{guild_id}/commands',
@@ -1288,13 +1525,18 @@ class HTTPClient:
         )
         return self.request(r, json=payload)
 
-    def edit_guild_command(self, application_id, guild_id, command_id, payload) -> Response[interactions.ApplicationCommand]:
+    def edit_guild_command(self,
+        application_id: Snowflake,
+        guild_id: Snowflake,
+        command_id: Snowflake,
+        payload: interactions.EditApplicationCommand,
+    ) -> Response[interactions.ApplicationCommand]:
         valid_keys = (
             'name',
             'description',
             'options',
         )
-        payload = {k: v for k, v in payload.items() if k in valid_keys}
+        payload = {k: v for k, v in payload.items() if k in valid_keys}  # type: ignore
         r = Route(
             'PATCH',
             '/applications/{application_id}/guilds/{guild_id}/commands/{command_id}',
@@ -1304,7 +1546,12 @@ class HTTPClient:
         )
         return self.request(r, json=payload)
 
-    def delete_guild_command(self, application_id, guild_id, command_id):
+    def delete_guild_command(
+        self,
+        application_id: Snowflake,
+        guild_id: Snowflake,
+        command_id: Snowflake,
+    ) -> Response[None]:
         r = Route(
             'DELETE',
             '/applications/{application_id}/guilds/{guild_id}/commands/{command_id}',
@@ -1315,7 +1562,10 @@ class HTTPClient:
         return self.request(r)
 
     def bulk_upsert_guild_commands(
-        self, application_id, guild_id, payload
+        self, 
+        application_id: Snowflake,
+        guild_id: Snowflake, 
+        payload: List[interactions.EditApplicationCommand],
     ) -> Response[List[interactions.ApplicationCommand]]:
         r = Route(
             'PUT',
@@ -1329,14 +1579,14 @@ class HTTPClient:
 
     def _edit_webhook_helper(
         self,
-        route,
-        file=None,
-        content=None,
-        embeds=None,
-        allowed_mentions=None,
+        route: Route,
+        file: Optional[File] = None,
+        content: Optional[str] = None,
+        embeds: Optional[List[embed.Embed]] = None,
+        allowed_mentions: Optional[message.AllowedMentions] = None,
     ):
 
-        payload = {}
+        payload: Dict[str, Any] = {}
         if content:
             payload['content'] = content
         if embeds:
@@ -1344,7 +1594,7 @@ class HTTPClient:
         if allowed_mentions:
             payload['allowed_mentions'] = allowed_mentions
 
-        form = [
+        form: List[Dict[str, Any]] = [
             {
                 'name': 'payload_json',
                 'value': utils.to_json(payload),
@@ -1361,16 +1611,23 @@ class HTTPClient:
                 }
             )
 
-        return self.request(route, form=form, files=[file])
+        return self.request(route, form=form, files=[file] if file else None)
 
-    def create_interaction_response(self, interaction_id, token, *, type, data=None):
+    def create_interaction_response(
+        self,
+        interaction_id: Snowflake,
+        token: str,
+        *,
+        type: InteractionResponseType,
+        data: Optional[interactions.InteractionApplicationCommandCallbackData] = None
+    ) -> Response[None]:
         r = Route(
             'POST',
             '/interactions/{interaction_id}/{interaction_token}/callback',
             interaction_id=interaction_id,
             interaction_token=token,
         )
-        payload = {
+        payload: Dict[str, Any] = {
             'type': type,
         }
 
@@ -1381,9 +1638,9 @@ class HTTPClient:
 
     def get_original_interaction_response(
         self,
-        application_id,
-        token,
-    ):
+        application_id: Snowflake,
+        token: str,
+    ) -> Response[message.Message]:
         r = Route(
             'GET',
             '/webhooks/{application_id}/{interaction_token}/messages/@original',
@@ -1394,13 +1651,13 @@ class HTTPClient:
 
     def edit_original_interaction_response(
         self,
-        application_id,
-        token,
-        file=None,
-        content=None,
-        embeds=None,
-        allowed_mentions=None,
-    ):
+        application_id: Snowflake,
+        token: str,
+        file: Optional[File] = None,
+        content: Optional[str] = None,
+        embeds: Optional[List[embed.Embed]] = None,
+        allowed_mentions: Optional[message.AllowedMentions] = None,
+    ) -> Response[message.Message]:
         r = Route(
             'PATCH',
             '/webhooks/{application_id}/{interaction_token}/messages/@original',
@@ -1409,7 +1666,7 @@ class HTTPClient:
         )
         return self._edit_webhook_helper(r, file=file, content=content, embeds=embeds, allowed_mentions=allowed_mentions)
 
-    def delete_original_interaction_response(self, application_id, token):
+    def delete_original_interaction_response(self, application_id: Snowflake, token: str) -> Response[None]:
         r = Route(
             'DELETE',
             '/webhooks/{application_id}/{interaction_token}/messages/@original',
@@ -1420,14 +1677,14 @@ class HTTPClient:
 
     def create_followup_message(
         self,
-        application_id,
-        token,
-        files=None,
-        content=None,
-        tts=False,
-        embeds=None,
-        allowed_mentions=None,
-    ):
+        application_id: Snowflake,
+        token: str,
+        files: List[File] = [],
+        content: Optional[str] = None,
+        tts: bool = False,
+        embeds: Optional[List[embed.Embed]] = None,
+        allowed_mentions: Optional[message.AllowedMentions] = None,
+    ) -> Response[message.Message]:
         r = Route(
             'POST',
             '/webhooks/{application_id}/{interaction_token}',
@@ -1445,14 +1702,14 @@ class HTTPClient:
 
     def edit_followup_message(
         self,
-        application_id,
-        token,
-        message_id,
-        file=None,
-        content=None,
-        embeds=None,
-        allowed_mentions=None,
-    ):
+        application_id: Snowflake,
+        token: str,
+        message_id: Snowflake,
+        file: Optional[File] = None,
+        content: Optional[str] = None,
+        embeds: Optional[List[embed.Embed]] = None,
+        allowed_mentions: Optional[message.AllowedMentions] = None,
+    )-> Response[message.Message]:
         r = Route(
             'PATCH',
             '/webhooks/{application_id}/{interaction_token}/messages/{message_id}',
@@ -1462,7 +1719,7 @@ class HTTPClient:
         )
         return self._edit_webhook_helper(r, file=file, content=content, embeds=embeds, allowed_mentions=allowed_mentions)
 
-    def delete_followup_message(self, application_id, token, message_id):
+    def delete_followup_message(self, application_id: Snowflake, token: str, message_id: Snowflake) -> Response[None]:
         r = Route(
             'DELETE',
             '/webhooks/{application_id}/{interaction_token}/messages/{message_id}',
@@ -1473,7 +1730,9 @@ class HTTPClient:
         return self.request(r)
 
     def get_guild_application_command_permissions(
-        self, application_id, guild_id
+        self,
+        application_id: Snowflake,
+        guild_id: Snowflake,
     ) -> Response[List[interactions.GuildApplicationCommandPermissions]]:
         r = Route(
             'GET',
@@ -1484,7 +1743,10 @@ class HTTPClient:
         return self.request(r)
 
     def get_application_command_permissions(
-        self, application_id, guild_id, command_id
+        self,
+        application_id: Snowflake,
+        guild_id: Snowflake,
+        command_id: Snowflake,
     ) -> Response[interactions.GuildApplicationCommandPermissions]:
         r = Route(
             'GET',
@@ -1495,7 +1757,13 @@ class HTTPClient:
         )
         return self.request(r)
 
-    def edit_application_command_permissions(self, application_id, guild_id, command_id, payload):
+    def edit_application_command_permissions(
+        self,
+        application_id: Snowflake,
+        guild_id: Snowflake,
+        command_id: Snowflake,
+        payload: interactions.BaseGuildApplicationCommandPermissions,
+    ) -> Response[None]:
         r = Route(
             'PUT',
             '/applications/{application_id}/guilds/{guild_id}/commands/{command_id}/permissions',
@@ -1505,7 +1773,12 @@ class HTTPClient:
         )
         return self.request(r, json=payload)
 
-    def bulk_edit_guild_application_command_permissions(self, application_id, guild_id, payload):
+    def bulk_edit_guild_application_command_permissions(
+        self,
+        application_id: Snowflake,
+        guild_id: Snowflake,
+        payload: List[interactions.PartialGuildApplicationCommandPermissions],
+    ) -> Response[None]:
         r = Route(
             'PUT',
             '/applications/{application_id}/guilds/{guild_id}/commands/permissions',
@@ -1516,10 +1789,10 @@ class HTTPClient:
 
     # Misc
 
-    def application_info(self):
+    def application_info(self) -> Response[appinfo.AppInfo]:
         return self.request(Route('GET', '/oauth2/applications/@me'))
 
-    async def get_gateway(self, *, encoding='json', zlib=True):
+    async def get_gateway(self, *, encoding: str = 'json', zlib: bool = True) -> str:
         try:
             data = await self.request(Route('GET', '/gateway'))
         except HTTPException as exc:
@@ -1530,7 +1803,7 @@ class HTTPClient:
             value = '{0}?encoding={1}&v=9'
         return value.format(data['url'], encoding)
 
-    async def get_bot_gateway(self, *, encoding='json', zlib=True):
+    async def get_bot_gateway(self, *, encoding: str = 'json', zlib: bool = True) -> Tuple[int, str]:
         try:
             data = await self.request(Route('GET', '/gateway/bot'))
         except HTTPException as exc:
@@ -1542,5 +1815,5 @@ class HTTPClient:
             value = '{0}?encoding={1}&v=9'
         return data['shards'], value.format(data['url'], encoding)
 
-    def get_user(self, user_id):
+    def get_user(self, user_id: Snowflake) -> Response[user.User]:
         return self.request(Route('GET', '/users/{user_id}', user_id=user_id))
diff --git a/discord/types/channel.py b/discord/types/channel.py
index d4f4cf3d2..ca6c54da6 100644
--- a/discord/types/channel.py
+++ b/discord/types/channel.py
@@ -28,9 +28,12 @@ from .snowflake import Snowflake
 from .threads import ThreadMetadata, ThreadMember
 
 
+OverwriteType = Literal[0, 1]
+
+
 class PermissionOverwrite(TypedDict):
     id: Snowflake
-    type: Literal[0, 1]
+    type: OverwriteType
     allow: str
     deny: str
 
diff --git a/discord/types/emoji.py b/discord/types/emoji.py
index 94121bf9b..d54690c14 100644
--- a/discord/types/emoji.py
+++ b/discord/types/emoji.py
@@ -39,3 +39,8 @@ class Emoji(PartialEmoji, total=False):
     managed: bool
     animated: bool
     available: bool
+
+
+class EditEmoji(TypedDict):
+    name: str
+    roles: Optional[SnowflakeList]
diff --git a/discord/types/gateway.py b/discord/types/gateway.py
new file mode 100644
index 000000000..bcf3e4673
--- /dev/null
+++ b/discord/types/gateway.py
@@ -0,0 +1,41 @@
+"""
+The MIT License (MIT)
+
+Copyright (c) 2015-present Rapptz
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+"""
+
+from typing import TypedDict
+
+
+class SessionStartLimit(TypedDict):
+    total: int
+    remaining: int
+    reset_after: int
+    max_concurrency: int
+
+
+class Gateway(TypedDict):
+    url: str
+
+
+class GatewayBot(Gateway):
+    shards: int
+    session_start_limit: SessionStartLimit
diff --git a/discord/types/guild.py b/discord/types/guild.py
index c5e24b2f1..57a4b115f 100644
--- a/discord/types/guild.py
+++ b/discord/types/guild.py
@@ -140,3 +140,20 @@ class InviteGuild(Guild, total=False):
 
 class GuildWithCounts(Guild, _GuildPreviewUnique):
     ...
+
+
+class GuildPrune(TypedDict):
+    pruned: Optional[int]
+
+
+class ChannelPositionUpdate(TypedDict):
+    id: Snowflake
+    position: Optional[int]
+    lock_permissions: Optional[bool]
+    parent_id: Optional[Snowflake]
+
+class _RolePositionRequired(TypedDict):
+    id: Snowflake
+
+class RolePositionUpdate(_RolePositionRequired, total=False):
+    position: Optional[Snowflake]
diff --git a/discord/types/interactions.py b/discord/types/interactions.py
index 6740aef39..466e4192d 100644
--- a/discord/types/interactions.py
+++ b/discord/types/interactions.py
@@ -24,7 +24,7 @@ DEALINGS IN THE SOFTWARE.
 
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, Dict, TypedDict, Union, List, Literal
+from typing import Optional, TYPE_CHECKING, Dict, TypedDict, Union, List, Literal
 from .snowflake import Snowflake
 from .components import Component, ComponentType
 from .embed import Embed
@@ -77,11 +77,14 @@ class ApplicationCommandPermissions(TypedDict):
     permission: bool
 
 
-class PartialGuildApplicationCommandPermissions(TypedDict):
-    id: Snowflake
+class BaseGuildApplicationCommandPermissions(TypedDict):
     permissions: List[ApplicationCommandPermissions]
 
 
+class PartialGuildApplicationCommandPermissions(BaseGuildApplicationCommandPermissions):
+    id: Snowflake
+
+
 class GuildApplicationCommandPermissions(PartialGuildApplicationCommandPermissions):
     application_id: Snowflake
     guild_id: Snowflake
@@ -95,7 +98,9 @@ class _ApplicationCommandInteractionDataOptionOptional(TypedDict, total=False):
     options: List[ApplicationCommandInteractionDataOption]
 
 
-class ApplicationCommandInteractionDataOption(_ApplicationCommandInteractionDataOptionOptional):
+class ApplicationCommandInteractionDataOption(
+    _ApplicationCommandInteractionDataOptionOptional
+):
     name: str
     type: ApplicationCommandOptionType
 
@@ -149,6 +154,7 @@ class Interaction(_InteractionOptional):
     token: str
     version: int
 
+
 class InteractionApplicationCommandCallbackData(TypedDict, total=False):
     tts: bool
     content: str
@@ -174,3 +180,10 @@ class MessageInteraction(TypedDict):
     type: InteractionType
     name: str
     user: User
+
+
+class EditApplicationCommand(TypedDict):
+    name: str
+    description: str
+    options: Optional[List[ApplicationCommandOption]]
+    default_permission: bool
diff --git a/discord/types/invite.py b/discord/types/invite.py
index 7290d36fe..50b69bd4a 100644
--- a/discord/types/invite.py
+++ b/discord/types/invite.py
@@ -52,6 +52,10 @@ class _InviteMetadata(TypedDict, total=False):
     expires_at: Optional[str]
 
 
+class VanityInvite(_InviteMetadata):
+    code: Optional[str]
+
+
 class IncompleteInvite(_InviteMetadata):
     code: str
     channel: PartialChannel
diff --git a/discord/types/member.py b/discord/types/member.py
index 4c162ef1a..b80ab6130 100644
--- a/discord/types/member.py
+++ b/discord/types/member.py
@@ -27,6 +27,10 @@ from .snowflake import SnowflakeList
 from .user import User
 
 
+class Nickname(TypedDict):
+    nick: str
+
+
 class PartialMember(TypedDict):
     roles: SnowflakeList
     joined_at: str
diff --git a/discord/types/template.py b/discord/types/template.py
index eaf5e756e..85c698911 100644
--- a/discord/types/template.py
+++ b/discord/types/template.py
@@ -30,6 +30,11 @@ from .user import User
 from .guild import Guild
 
 
+class CreateTemplate(TypedDict):
+    name: str
+    icon: Optional[bytes]
+
+
 class Template(TypedDict):
     code: str
     name: str
diff --git a/discord/types/threads.py b/discord/types/threads.py
index c0f0c10b4..baf8def40 100644
--- a/discord/types/threads.py
+++ b/discord/types/threads.py
@@ -27,7 +27,7 @@ from typing import List, Literal, Optional, TypedDict
 
 from .snowflake import Snowflake
 
-ThreadTypes = Literal[10, 11, 12]
+ThreadType = Literal[10, 11, 12]
 ThreadArchiveDuration = Literal[60, 1440, 4320, 10080]
 
 
@@ -61,7 +61,7 @@ class Thread(_ThreadOptional):
     parent_id: Snowflake
     owner_id: Snowflake
     name: str
-    type: ThreadTypes
+    type: ThreadType
     member_count: int
     message_count: int
     rate_limit_per_user: int