about summary refs log tree commit diff stats
path: root/discord/client.py
diff options
context:
space:
mode:
Diffstat (limited to 'discord/client.py')
-rw-r--r--discord/client.py91
1 files changed, 71 insertions, 20 deletions
diff --git a/discord/client.py b/discord/client.py
index d6cfd50..5f5c3b0 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -3,42 +3,69 @@ from enum import IntEnum
 import json
 import sys
 import threading
+import warnings
 from typing import Optional, Coroutine, Any, Callable
 import zlib
 import aiohttp
 import websockets
 
-from .utils import EventEmitter
-from .utils.rest import RESTClient
+from .utils import EventEmitter, RESTClient
 from .intents import Intents, get_number
 from .user import User
 
+
 class GatewayEvents(IntEnum):
-    DISPATCH           = 0
-    HEARTBEAT          = 1
-    IDENTIFY           = 2
-    PRESENCE           = 3
-    VOICE_STATE        = 4
-    VOICE_PING         = 5
-    RESUME             = 6
-    RECONNECT          = 7
-    REQUEST_MEMBERS    = 8
+    """
+    Contains constants for the gateway opcodes.
+    """
+    DISPATCH = 0
+    """An event was dispatched."""
+    HEARTBEAT = 1
+    """Sent at regular intervals by the client to keep the gateway connection alive."""
+    IDENTIFY = 2
+    """Used to identify yourself with the token during the initial handshake."""
+    PRESENCE = 3
+    """Used to update the client's presence."""
+    VOICE_STATE = 4
+    """Used to join and leave voice channels."""
+    VOICE_PING = 5
+    RESUME = 6
+    """Used to resume a disconnected session."""
+    RECONNECT = 7
+    """Used to reconnect to the session."""
+    REQUEST_MEMBERS = 8
+    """Used to request information about guild members when there are too many for """
     INVALIDATE_SESSION = 9
-    HELLO              = 10
-    HEARTBEAT_ACK      = 11
-    GUILD_SYNC         = 12
+    """Means that the session is invalid. When this is received, you must reconnect and re-identify."""
+    HELLO = 10
+    """Acknowledgement of gateway connection."""
+    HEARTBEAT_ACK = 11
+    """Acknowledgement of gateway heartbeat."""
+    GUILD_SYNC = 12
+
 
 class Client:
+    """
+    Represents a Discord client (i.e. a bot).
+    You need to initialise one of these and then use `run()` with a token to login.
+    """
     _token: str
 
     @property
     async def user(self):
+        """The `discord.user.User` associated with the client."""
         data = await self.rest_client.get('/users/@me')
         return User(data)
 
     def __init__(self, intents: list[Intents]):
         self.gateway = None
         self.loop = asyncio.get_event_loop()
+        if Intents.MESSAGE_CONTENT in intents:
+            warnings.warn("Message Content will become a privileged intent in August 2022. You must enable it in the "
+                          "Discord developer portal.")
+        if Intents.GUILD_MEMBERS in intents or Intents.GUILD_PRESENCES in intents:
+            warnings.warn("You are using one or more privileged intent (Guild Members and/or Guild Presences). You "
+                          "must enable them in the Discord developer portal.")
         self.code: int = get_number(intents)
         self.event_emitter = EventEmitter()
         self.buffer = bytearray()
@@ -51,18 +78,29 @@ class Client:
         }))
 
     async def connect(self):
+        """
+        Connects to the Discord gateway and begins sending heartbeats.
+        This should not be called manually.
+
+        **Parameters:**
+        - token: Your bot token.
+        - intent_code: The number which represents the `discord.intents.Intents` being used.
+        """
         async with websockets.connect("wss://gateway.discord.gg/?v=10&encoding=json") as gateway:
             self.gateway = gateway
             threading.Thread(target=self.loop.run_forever).start()
             while True:
                 await self.poll_event()
-    
+
     async def send(self, data: dict):
         """
         Send data to the gateway.
+
+        **Parameters:**
+        - data: The data to send to the gateway.
         """
         await self.gateway.send(json.dumps(data))
-    
+
     async def recv(self, msg):
         """
         Receive data from the gateway.
@@ -91,7 +129,7 @@ class Client:
 
             if opcode == GatewayEvents.HEARTBEAT_ACK.value:
                 return await self.heartbeat(self.heartbeat_interval)
-            
+
             if opcode == GatewayEvents.HEARTBEAT.value:
                 return await self.heartbeat(self.heartbeat_interval)
 
@@ -102,7 +140,6 @@ class Client:
 
         self.event_emitter.emit('on_' + event.lower())
 
-
     async def close(self):
         """
         Close the client.
@@ -113,9 +150,16 @@ class Client:
     async def poll_event(self):
         msg = await self.gateway.recv()
         await self.recv(msg)
-    
 
     async def heartbeat(self, interval: int):
+        """
+        Sends a heartbeat through the gateway to keep the connection active.
+        This should not be called manually.
+
+        **Parameters:**
+        - gateway: The gateway to keep open.
+        - interval: How often to send a heartbeat. This is given by the gateway in a Hello packet.
+        """
         await asyncio.sleep(interval / 1000)
         heartbeat = {
             "op": 1,
@@ -141,9 +185,13 @@ class Client:
         }
         await self.send(identify)
 
-    def event(self, coro: Optional[Callable[..., Coroutine[Any, Any, Any]]]=None, /) -> Optional[Callable[..., Coroutine[Any, Any, Any]]]:
+    def event(self, coro: Optional[Callable[..., Coroutine[Any, Any, Any]]] = None, /) -> Optional[
+        Callable[..., Coroutine[Any, Any, Any]]]:
         """
         Registers a coroutine to be called when an event is emitted.
+
+        **Parameters:**
+        - coro: The coroutine to be registered.
         """
         if not asyncio.iscoroutinefunction(coro):
             raise TypeError('event registered must be a coroutine function')
@@ -153,6 +201,9 @@ class Client:
     def run(self, token: str):
         """
         Run the client.
+
+        **Parameters:**
+        - token: Your bot token. Do not share this with anyone!
         """
         self._token = token
         asyncio.run(self.connect())