about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--discord/__init__.py5
-rw-r--r--discord/client.py24
-rw-r--r--discord/user.py4
-rw-r--r--discord/utils/__init__.py1
-rw-r--r--discord/utils/event_emitter.py29
5 files changed, 51 insertions, 12 deletions
diff --git a/discord/__init__.py b/discord/__init__.py
index 066d9f5..000b15d 100644
--- a/discord/__init__.py
+++ b/discord/__init__.py
@@ -1,3 +1,6 @@
 """
 .. include:: ../README.md
-"""
\ No newline at end of file
+"""
+
+from .client import *
+from .intents import *
diff --git a/discord/client.py b/discord/client.py
index c61c4b9..4c6be14 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -2,10 +2,12 @@ import asyncio
 import json
 import sys
 import threading
-import websockets
 from typing import Coroutine
-from discord.intents import Intents, gen_number
-from discord.user import User
+import websockets
+
+from .utils import EventEmitter
+from .intents import Intents, gen_number
+from .user import User
 
 
 class Client:
@@ -13,6 +15,7 @@ class Client:
         self.gateway = None
         self.loop = asyncio.get_event_loop()
         self.code = gen_number(intents)
+        self.event_emitter = EventEmitter()
 
     async def connect(self, token: str, intent_code: int):
         async with websockets.connect("wss://gateway.discord.gg/?v=10&encoding=json") as gateway:
@@ -35,8 +38,7 @@ class Client:
             }
             await gateway.send(json.dumps(identify))
             ready = await gateway.recv()
-            if (hasattr(self, 'on_ready')):
-                await getattr(self, 'on_ready')()
+            self.event_emitter.emit('on_ready', False)
             self.user = User(json.loads(ready)['d']['user'])
 
     async def heartbeat(self, gateway: websockets.WebSocketClientProtocol, interval: int):
@@ -50,12 +52,16 @@ class Client:
             ack = await gateway.recv()
 
     def event(self, coro: Coroutine, /) -> Coroutine:
+        """
+        Registers a coroutine to be called when an event is emitted.
+        """
         if not asyncio.iscoroutinefunction(coro):
             raise TypeError('event registered must be a coroutine function')
-
-        setattr(self, coro.__name__, coro)
+        self.event_emitter.add_listener(coro.__name__, coro)
         return coro
 
     def run(self, token: str):
-        self.token = token
-        asyncio.run(self.connect(self.token, self.code))
\ No newline at end of file
+        """
+        Run the client.
+        """
+        asyncio.run(self.connect(token, self.code))
diff --git a/discord/user.py b/discord/user.py
index 838b6e2..16ddf1b 100644
--- a/discord/user.py
+++ b/discord/user.py
@@ -18,5 +18,5 @@ class User:
     )
 
     def __init__(self, data: dict):
-        for k, v in data:
-            setattr(self, k, v)
+        for k in data:
+            setattr(self, k, data[k])
diff --git a/discord/utils/__init__.py b/discord/utils/__init__.py
new file mode 100644
index 0000000..7fdb52b
--- /dev/null
+++ b/discord/utils/__init__.py
@@ -0,0 +1 @@
+from .event_emitter import *
\ No newline at end of file
diff --git a/discord/utils/event_emitter.py b/discord/utils/event_emitter.py
new file mode 100644
index 0000000..77fff72
--- /dev/null
+++ b/discord/utils/event_emitter.py
@@ -0,0 +1,29 @@
+import asyncio
+from types import NoneType
+from typing import Coroutine
+
+class EventEmitter():
+    def __init__(self):
+        self.listeners = {}
+
+    def add_listener(self, event_name: str, func: Coroutine):
+        if not self.listeners.get(event_name, None):
+            self.listeners[event_name] = {func}
+        else:
+            self.listeners[event_name].add(func)
+
+    def remove_listener(self, event_name: str, func: Coroutine):
+        self.listeners[event_name].remove(func)
+        if len(self.listeners[event_name]) == 0:
+            del self.listeners[event_name]
+
+    def emit(self, event_name: str, args_required=False, *args, **kwargs):
+        listeners = self.listeners.get(event_name, [])
+        for func in listeners:
+            if args_required:
+                if len(args) == 0:
+                    raise TypeError('event registered must have arguments')
+                else:
+                    asyncio.create_task(func(*args, **kwargs))
+            else:
+                asyncio.create_task(func(*args, **kwargs))