68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
import aiohttp as ah
|
|
import time
|
|
import asyncio
|
|
import datetime
|
|
import traceback
|
|
from dataclasses import dataclass
|
|
from asyncio import iscoroutinefunction
|
|
|
|
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)
|
|
|
|
event_queue=asyncio.Queue() #Contains Events. Everything in here must be an Event.
|
|
listeners=[] # These respond to events. They're executed by workers processing the event queue. They should all be Listeners
|
|
timers=[] # These just execute on a schedule. That schedule can be "as soon as it exits". Should all be Timers, which include the property of whether to wait for exit before starting the next call or not (rarely relevant, so defaults to "no").
|
|
|
|
def addlistener(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)
|
|
timers.append(_wrapper)
|
|
return _wrapper
|
|
return _loop
|
|
|
|
async def process_queue():
|
|
item=await event_queue.get():
|
|
for listener in listeners:
|
|
if listener==item:
|
|
await listener(item)
|
|
|
|
@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 |