2022-08-09 20:36:27 +10:00
|
|
|
import aiohttp as ah
|
|
|
|
import time
|
|
|
|
import asyncio
|
|
|
|
import datetime
|
|
|
|
import traceback
|
2022-08-10 00:00:55 +10:00
|
|
|
from dataclasses import dataclass
|
|
|
|
from asyncio import iscoroutinefunction
|
2022-08-09 20:36:27 +10:00
|
|
|
|
|
|
|
func=type(lambda:1) # Gross, but I can't actually find it.
|
|
|
|
# And yes, lamdas are <class 'function'> too.
|
|
|
|
|
|
|
|
tracing=False
|
|
|
|
def trace(*msg):
|
|
|
|
if tracing: print(datetime.datetime.now(),*msg)
|
|
|
|
|
2022-08-10 00:00:55 +10:00
|
|
|
class ChatClient():
|
2022-08-09 20:36:27 +10:00
|
|
|
def __init__(self,homeserver,token):
|
|
|
|
self.event_queue=asyncio.Queue() #Contains Events. Everything in here must be an Event.
|
|
|
|
self.listeners=[]
|
|
|
|
self.timers=[]
|
|
|
|
|
|
|
|
def addlistener(self,name=None,match=None):
|
|
|
|
if isinstance(name,func) and match==None: match=name; name=None
|
|
|
|
def __wrap__(funky):
|
|
|
|
self.listeners.append(Listener(name,match,funky))
|
|
|
|
return funky
|
|
|
|
|
|
|
|
def loop(timer=0):
|
|
|
|
def _loop(funky):
|
|
|
|
@functools.wraps(funky)
|
|
|
|
async def _wrapper(*args,**kwargs):
|
|
|
|
while True:
|
|
|
|
try: await funky(*args,**kwargs)
|
|
|
|
except Exception: open('error '+str(datetime.datetime.now()),'w').write(traceback.format_exc())
|
|
|
|
await asyncio.sleep(timer)
|
|
|
|
self.timers.append(_wrapper)
|
|
|
|
return _wrapper
|
|
|
|
return _loop
|
|
|
|
|
|
|
|
async def process_queue(self):
|
|
|
|
item=await self.event_queue.get():
|
|
|
|
for listener in self.listeners:
|
|
|
|
if listener==item:
|
|
|
|
await listener(item)
|
2022-08-10 00:00:55 +10:00
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class Event():
|
|
|
|
event_type:str
|
|
|
|
data:Object=None
|
|
|
|
raw_data:dict=None
|
|
|
|
outbound:bool=False
|
|
|
|
|
|
|
|
class Listener():
|
|
|
|
def __init__(self,name,match,function):
|
|
|
|
self.name=name or function.__name__
|
|
|
|
self.match=match
|
|
|
|
self._matchstr=isinstance(match,str)
|
|
|
|
self.function=function
|
|
|
|
self._async=iscoroutinefunction(function)
|
|
|
|
|
|
|
|
async def __call__(self,*args,**kwargs):
|
|
|
|
if not self._async: return self.function(*args,**kwargs)
|
|
|
|
return await self.function(*args,**kwargs)
|
|
|
|
|
|
|
|
def __eq__(self,other):
|
|
|
|
if isinstance(other,Event):
|
|
|
|
if self._matchstr: return self.match==other.event_type
|
|
|
|
return self.match(other) # If it's not a string, assume it's a callable.
|
|
|
|
else: return super.__eq__(self,other)
|
|
|
|
def __str__(self): return self.name
|