Start building client functionality
This commit is contained in:
parent
03fd706642
commit
a947e558bf
@ -12,7 +12,7 @@ MATRIX_MEDIA = "/_matrix/media/r0"
|
||||
|
||||
|
||||
@dataclass
|
||||
class HTTPConfig:
|
||||
class APIConfig:
|
||||
max_retry: int = 10
|
||||
max_wait_time: int = 3600
|
||||
backoff_factor: float = 0.1
|
||||
@ -20,20 +20,20 @@ class HTTPConfig:
|
||||
proxy: str = None
|
||||
|
||||
|
||||
class HTTP:
|
||||
class API:
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
base_url: str,
|
||||
username: str,
|
||||
user_id: str,
|
||||
password: str = None,
|
||||
token: str = None,
|
||||
device_id: str = None,
|
||||
device_name: str = None,
|
||||
config: HTTPConfig = HTTPConfig(),
|
||||
config: APIConfig = APIConfig(),
|
||||
):
|
||||
self.base_url = base_url
|
||||
self.username = username
|
||||
self.user_id = user_id
|
||||
self.password = password
|
||||
self.token = token
|
||||
self.device_id = device_id
|
||||
@ -120,14 +120,16 @@ class HTTP:
|
||||
path = self.build_url("login")
|
||||
|
||||
data = {}
|
||||
if self.password:
|
||||
if self.password and self.user_id:
|
||||
data = {
|
||||
"type": "m.login.password",
|
||||
"identifier": {"user": self.username, "type": "m.id.user"},
|
||||
"identifier": {"user": self.user_id, "type": "m.id.user"},
|
||||
"password": self.password,
|
||||
}
|
||||
elif self.token:
|
||||
data = {"type": "m.login.token", "token": self.token}
|
||||
else:
|
||||
raise RuntimeError("No valid login types configured")
|
||||
if self.device_id:
|
||||
data["device_id"] = self.device_id
|
||||
if self.device_name:
|
||||
@ -137,6 +139,8 @@ class HTTP:
|
||||
resp = await self._send("post", path, data=data, headers=headers)
|
||||
self.access_token = resp.get("access_token")
|
||||
self.device_id = resp.get("device_id")
|
||||
if not self.user_id:
|
||||
self.user_id = resp.get("user_id")
|
||||
return resp
|
||||
|
||||
async def logout(self):
|
||||
@ -165,3 +169,34 @@ class HTTP:
|
||||
raise RuntimeWarning(f"{room_id} is not a valid room id or alias")
|
||||
|
||||
return await self.send("PUT", path, data=content)
|
||||
|
||||
async def get_joined_rooms(self):
|
||||
path = self.build_url("joined_rooms")
|
||||
resp = await self.send("GET", path)
|
||||
if resp.get("joined_rooms"):
|
||||
return resp["joined_rooms"]
|
||||
else:
|
||||
return []
|
||||
|
||||
async def get_sync(
|
||||
self,
|
||||
query_filter: str = None,
|
||||
since: str = None,
|
||||
full_state: bool = False,
|
||||
set_presence: str = "online",
|
||||
timeout: int = 10000,
|
||||
):
|
||||
query = {
|
||||
"full_state": full_state,
|
||||
"set_presence": set_presence,
|
||||
"timeout": timeout,
|
||||
}
|
||||
if query_filter:
|
||||
query["filter"] = query_filter
|
||||
if since:
|
||||
query["since"] = since
|
||||
|
||||
path = self.build_url("sync", query=query)
|
||||
resp = await self.send("GET", path)
|
||||
|
||||
return resp
|
||||
70
lib/client.py
Normal file
70
lib/client.py
Normal file
@ -0,0 +1,70 @@
|
||||
import asyncio
|
||||
from typing import Union, Optional
|
||||
|
||||
from .api import API, APIConfig
|
||||
|
||||
|
||||
class Client:
|
||||
def __init__(
|
||||
self,
|
||||
prefix: Union[str, list, tuple],
|
||||
homeserver: str = "https://matrixcoding.chat",
|
||||
):
|
||||
self.prefix = prefix
|
||||
self.homeserver = homeserver
|
||||
self.username: Optional[str] = None
|
||||
self.password: Optional[str] = None
|
||||
self.token: Optional[str] = None
|
||||
self.rooms: list = []
|
||||
self.api: Optional[API] = None
|
||||
self.running: bool = False
|
||||
self.sync_timeout: int = 1000
|
||||
self.sync_since: Optional[str] = None
|
||||
self.sync_full_state: bool = False
|
||||
self.sync_set_presence: str = "online"
|
||||
self.sync_filter: Optional[str] = None
|
||||
self.sync_delay: Optional[str] = None
|
||||
|
||||
async def run(self, user_id: str = None, password: str = None, token: str = None):
|
||||
if not password and not token:
|
||||
raise RuntimeError("Either the password or a token is required")
|
||||
self.api = API(
|
||||
base_url=self.homeserver, user_id=user_id, password=password, token=token
|
||||
)
|
||||
resp = await self.api.login()
|
||||
if resp.get("errcode"):
|
||||
raise RuntimeError(resp)
|
||||
self.running = True
|
||||
while self.running:
|
||||
if self.sync_delay:
|
||||
await asyncio.sleep(self.sync_delay)
|
||||
await self.sync()
|
||||
|
||||
async def sync(self):
|
||||
resp = await self.api.get_sync(
|
||||
self.sync_filter,
|
||||
self.sync_since,
|
||||
self.sync_full_state,
|
||||
self.sync_set_presence,
|
||||
self.sync_timeout,
|
||||
)
|
||||
if resp.get("errcode"):
|
||||
self.running = False
|
||||
raise RuntimeError(resp)
|
||||
self.sync_since = resp["next_batch"]
|
||||
for key, value in resp.iteritems():
|
||||
if key == "next_batch":
|
||||
self.sync_since = value
|
||||
else:
|
||||
self.process_events(key, value)
|
||||
|
||||
def process_events(self, event_type: str, event: dict):
|
||||
if event_type == "rooms":
|
||||
joined_room_events = event["join"]
|
||||
invited_rooms = event["invite"]
|
||||
left_rooms = event["leave"]
|
||||
# TODO process events
|
||||
|
||||
def process_timeline(self, room, timeline):
|
||||
# TODO process the timeline
|
||||
pass
|
||||
1
lib/context.py
Normal file
1
lib/context.py
Normal file
@ -0,0 +1 @@
|
||||
# TODO Create Context
|
||||
1
lib/events.py
Normal file
1
lib/events.py
Normal file
@ -0,0 +1 @@
|
||||
# TODO Add Event classes
|
||||
1
lib/room.py
Normal file
1
lib/room.py
Normal file
@ -0,0 +1 @@
|
||||
# TODO Add Room class
|
||||
Loading…
x
Reference in New Issue
Block a user