Still splitting matrix out from corelib
This commit is contained in:
parent
80856ef17d
commit
9dd3b82bf8
44
chatlib.py
44
chatlib.py
|
@ -3,7 +3,8 @@ import time
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
import traceback
|
import traceback
|
||||||
from .utils import Event,Listener
|
from dataclasses import dataclass
|
||||||
|
from asyncio import iscoroutinefunction
|
||||||
|
|
||||||
func=type(lambda:1) # Gross, but I can't actually find it.
|
func=type(lambda:1) # Gross, but I can't actually find it.
|
||||||
# And yes, lamdas are <class 'function'> too.
|
# And yes, lamdas are <class 'function'> too.
|
||||||
|
@ -12,26 +13,12 @@ tracing=False
|
||||||
def trace(*msg):
|
def trace(*msg):
|
||||||
if tracing: print(datetime.datetime.now(),*msg)
|
if tracing: print(datetime.datetime.now(),*msg)
|
||||||
|
|
||||||
class MatrixClient():
|
class ChatClient():
|
||||||
def __init__(self,homeserver,token):
|
def __init__(self,homeserver,token):
|
||||||
self.event_queue=asyncio.Queue() #Contains Events. Everything in here must be an Event.
|
self.event_queue=asyncio.Queue() #Contains Events. Everything in here must be an Event.
|
||||||
self.listeners=[]
|
self.listeners=[]
|
||||||
self.timers=[]
|
self.timers=[]
|
||||||
|
|
||||||
async def request(self,endpoint='sync',method='GET', ver=0,headers={} *args,**kwargs):
|
|
||||||
async with self.session.request(method, f'{self.baseurl}/r{ver}/{endpoint}', headers=headers|{'Authorization':f'Bearer {self.token}'}, *args,**kwargs) as fetched:
|
|
||||||
if fetched.status_code!=200: raise Exception('fix ur shit')
|
|
||||||
try: return await fetched.json()
|
|
||||||
except JSONDecodeError: pass # TODO: Figure out what this is called
|
|
||||||
|
|
||||||
# This function just dumps /sync blobs in the event queue as a raw event.
|
|
||||||
# ALL handling is deferred to handlers.
|
|
||||||
# ... Except updating the since token. That's important to do here to guarantee that it never calls with the same token twice.
|
|
||||||
async def sync(self):
|
|
||||||
blob=await self.request(params={'timeout':30000,'since':self.since})
|
|
||||||
self.since=blob['next_batch']
|
|
||||||
self.event_queue.put(Event('m.sync',None,blob))
|
|
||||||
|
|
||||||
def addlistener(self,name=None,match=None):
|
def addlistener(self,name=None,match=None):
|
||||||
if isinstance(name,func) and match==None: match=name; name=None
|
if isinstance(name,func) and match==None: match=name; name=None
|
||||||
def __wrap__(funky):
|
def __wrap__(funky):
|
||||||
|
@ -56,3 +43,28 @@ class MatrixClient():
|
||||||
if listener==item:
|
if listener==item:
|
||||||
await 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
|
|
@ -1,5 +1,6 @@
|
||||||
from .utils import Listener as _l, Event as _e, get_or_create as goc
|
from .utils import get_or_create as goc
|
||||||
import .models
|
import .models
|
||||||
|
from .chatlib import Listener as _l, Event as _e
|
||||||
|
|
||||||
# Default handlers will be given two parts each:
|
# Default handlers will be given two parts each:
|
||||||
# 1) Mould the raw event into a parsed event (update internal state)
|
# 1) Mould the raw event into a parsed event (update internal state)
|
||||||
|
|
5
matrixapi.py
Normal file
5
matrixapi.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
async def request(self,endpoint='sync',method='GET', ver=0,headers={} *args,**kwargs):
|
||||||
|
async with self.session.request(method, f'{self.baseurl}/r{ver}/{endpoint}', headers=headers|{'Authorization':f'Bearer {self.token}'}, *args,**kwargs) as fetched:
|
||||||
|
if fetched.status_code!=200: raise Exception('fix ur shit')
|
||||||
|
try: return await fetched.json()
|
||||||
|
except JSONDecodeError: pass # TODO: Figure out what this is called
|
|
@ -1,4 +1,4 @@
|
||||||
from .matrix import *
|
from .chatlib import *
|
||||||
import .listeners
|
import .listeners
|
||||||
real_listeners=dict(filter(lambda x:isinstance(x,Listener),listeners.__dict__.items()))
|
real_listeners=dict(filter(lambda x:isinstance(x,Listener),listeners.__dict__.items()))
|
||||||
|
|
||||||
|
|
14
models.py
14
models.py
|
@ -1,6 +1,6 @@
|
||||||
from .utils import redc
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
@redc
|
@dataclass
|
||||||
class Account():
|
class Account():
|
||||||
mxid:str
|
mxid:str
|
||||||
username:str
|
username:str
|
||||||
|
@ -9,7 +9,7 @@ class Account():
|
||||||
nickname:str=''
|
nickname:str=''
|
||||||
rooms:List[Room]=field(default_factory=list)
|
rooms:List[Room]=field(default_factory=list)
|
||||||
|
|
||||||
@redc
|
@dataclass
|
||||||
class Room():
|
class Room():
|
||||||
id:str
|
id:str
|
||||||
name:str=''
|
name:str=''
|
||||||
|
@ -17,23 +17,23 @@ class Room():
|
||||||
parents:List[Space]=field(default_factory=list)
|
parents:List[Space]=field(default_factory=list)
|
||||||
messages:List[Message]=field(default_factory=list)
|
messages:List[Message]=field(default_factory=list)
|
||||||
|
|
||||||
@redc
|
@dataclass
|
||||||
class Space(Room):
|
class Space(Room):
|
||||||
children:List[Room]=field(default_factory=list)
|
children:List[Room]=field(default_factory=list)
|
||||||
|
|
||||||
@redc
|
@dataclass
|
||||||
class Message():
|
class Message():
|
||||||
id:str
|
id:str
|
||||||
contents:str
|
contents:str
|
||||||
author:Member
|
author:Member
|
||||||
|
|
||||||
@redc
|
@dataclass
|
||||||
class User():
|
class User():
|
||||||
mxid:str
|
mxid:str
|
||||||
nick:str
|
nick:str
|
||||||
avatar:str
|
avatar:str
|
||||||
|
|
||||||
@redc
|
@dataclass
|
||||||
class Member(User):
|
class Member(User):
|
||||||
room_av:str
|
room_av:str
|
||||||
room_nick:str
|
room_nick:str
|
7
timers.py
Normal file
7
timers.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This function just dumps /sync blobs in the event queue as a raw event.
|
||||||
|
# ALL handling is deferred to handlers.
|
||||||
|
# ... Except updating the since token. That's important to do here to guarantee that it never calls with the same token twice.
|
||||||
|
async def sync(self):
|
||||||
|
blob=await self.request(params={'timeout':30000,'since':self.since})
|
||||||
|
self.since=blob['next_batch']
|
||||||
|
self.event_queue.put(Event('m.sync',None,blob))
|
29
utils.py
29
utils.py
|
@ -1,32 +1,3 @@
|
||||||
from dataclasses import dataclass, field, _MISSING_TYPE as mt
|
|
||||||
from asyncio import iscoroutinefunction
|
|
||||||
|
|
||||||
@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
|
|
||||||
|
|
||||||
def get_or_create(needle,haystack,default):
|
def get_or_create(needle,haystack,default):
|
||||||
"""
|
"""
|
||||||
This is a wrapper for filter that can add stuff. Nothing special. Needle is a function, default isn't. Haystack is a list. I might fix that later.
|
This is a wrapper for filter that can add stuff. Nothing special. Needle is a function, default isn't. Haystack is a list. I might fix that later.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user