Start building client functionality
This commit is contained in:
parent
03fd706642
commit
a947e558bf
@ -12,7 +12,7 @@ MATRIX_MEDIA = "/_matrix/media/r0"
|
|||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class HTTPConfig:
|
class APIConfig:
|
||||||
max_retry: int = 10
|
max_retry: int = 10
|
||||||
max_wait_time: int = 3600
|
max_wait_time: int = 3600
|
||||||
backoff_factor: float = 0.1
|
backoff_factor: float = 0.1
|
||||||
@ -20,20 +20,20 @@ class HTTPConfig:
|
|||||||
proxy: str = None
|
proxy: str = None
|
||||||
|
|
||||||
|
|
||||||
class HTTP:
|
class API:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
base_url: str,
|
base_url: str,
|
||||||
username: str,
|
user_id: str,
|
||||||
password: str = None,
|
password: str = None,
|
||||||
token: str = None,
|
token: str = None,
|
||||||
device_id: str = None,
|
device_id: str = None,
|
||||||
device_name: str = None,
|
device_name: str = None,
|
||||||
config: HTTPConfig = HTTPConfig(),
|
config: APIConfig = APIConfig(),
|
||||||
):
|
):
|
||||||
self.base_url = base_url
|
self.base_url = base_url
|
||||||
self.username = username
|
self.user_id = user_id
|
||||||
self.password = password
|
self.password = password
|
||||||
self.token = token
|
self.token = token
|
||||||
self.device_id = device_id
|
self.device_id = device_id
|
||||||
@ -120,14 +120,16 @@ class HTTP:
|
|||||||
path = self.build_url("login")
|
path = self.build_url("login")
|
||||||
|
|
||||||
data = {}
|
data = {}
|
||||||
if self.password:
|
if self.password and self.user_id:
|
||||||
data = {
|
data = {
|
||||||
"type": "m.login.password",
|
"type": "m.login.password",
|
||||||
"identifier": {"user": self.username, "type": "m.id.user"},
|
"identifier": {"user": self.user_id, "type": "m.id.user"},
|
||||||
"password": self.password,
|
"password": self.password,
|
||||||
}
|
}
|
||||||
elif self.token:
|
elif self.token:
|
||||||
data = {"type": "m.login.token", "token": self.token}
|
data = {"type": "m.login.token", "token": self.token}
|
||||||
|
else:
|
||||||
|
raise RuntimeError("No valid login types configured")
|
||||||
if self.device_id:
|
if self.device_id:
|
||||||
data["device_id"] = self.device_id
|
data["device_id"] = self.device_id
|
||||||
if self.device_name:
|
if self.device_name:
|
||||||
@ -137,6 +139,8 @@ class HTTP:
|
|||||||
resp = await self._send("post", path, data=data, headers=headers)
|
resp = await self._send("post", path, data=data, headers=headers)
|
||||||
self.access_token = resp.get("access_token")
|
self.access_token = resp.get("access_token")
|
||||||
self.device_id = resp.get("device_id")
|
self.device_id = resp.get("device_id")
|
||||||
|
if not self.user_id:
|
||||||
|
self.user_id = resp.get("user_id")
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
async def logout(self):
|
async def logout(self):
|
||||||
@ -165,3 +169,34 @@ class HTTP:
|
|||||||
raise RuntimeWarning(f"{room_id} is not a valid room id or alias")
|
raise RuntimeWarning(f"{room_id} is not a valid room id or alias")
|
||||||
|
|
||||||
return await self.send("PUT", path, data=content)
|
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