Past events loading (with two bugs)

This commit is contained in:
miruka
2019-07-05 02:45:30 -04:00
parent 83694d387b
commit ecba7c47ec
5 changed files with 83 additions and 29 deletions

View File

@@ -2,7 +2,7 @@ import asyncio
import json
import random
from pathlib import Path
from typing import Dict, Optional, Tuple
from typing import Dict, Optional, Set, Tuple
from atomicfile import AtomicFile
@@ -18,8 +18,12 @@ CONFIG_LOCK = asyncio.Lock()
class Backend:
def __init__(self, app: App) -> None:
self.app = app
self.clients: Dict[str, MatrixClient] = {}
self.past_tokens: Dict[str, str] = {} # {room_id: token}
self.fully_loaded_rooms: Set[str] = set() # {room_id}
def __repr__(self) -> str:
return f"{type(self).__name__}(clients={self.clients!r})"

View File

@@ -114,7 +114,7 @@ class MatrixClient(nio.AsyncClient):
response = await self.get_profile(user_id)
if isinstance(response, nio.ProfileGetError):
log.warning("Error getting profile for %r: %s", user_id, response)
log.warning("%s: %s", user_id, response)
users.UserUpdated(
user_id = user_id,
@@ -124,6 +124,11 @@ class MatrixClient(nio.AsyncClient):
)
@property
def all_rooms(self) -> Dict[str, MatrixRoom]:
return {**self.invited_rooms, **self.rooms}
async def send_markdown(self, room_id: str, text: str) -> None:
content = {
"body": text,
@@ -149,6 +154,35 @@ class MatrixClient(nio.AsyncClient):
log.error("Failed to send message: %s", response)
async def load_past_events(self, room_id: str, limit: int = 100) -> bool:
if room_id in self.backend.fully_loaded_rooms:
return False
response = await self.room_messages(
room_id = room_id,
start = self.backend.past_tokens[room_id],
limit = limit,
)
more_to_load = True
print(len(response.chunk))
if self.backend.past_tokens[room_id] == response.end:
self.backend.fully_loaded_rooms.add(room_id)
more_to_load = False
self.backend.past_tokens[room_id] = response.end
for event in response.chunk:
for cb in self.event_callbacks:
if (cb.filter is None or isinstance(event, cb.filter)):
await cb.func(
self.all_rooms[room_id], event, from_past=True
)
return more_to_load
# Callbacks for nio responses
@staticmethod
@@ -176,9 +210,12 @@ class MatrixClient(nio.AsyncClient):
inviter = room.inviter or "",
)
for room_id, _ in resp.rooms.join.items():
for room_id, info in resp.rooms.join.items():
room = self.rooms[room_id]
if room_id not in self.backend.past_tokens:
self.backend.past_tokens[room_id] = info.timeline.prev_batch
rooms.RoomUpdated(
user_id = self.user_id,
category = "Rooms",
@@ -208,7 +245,9 @@ class MatrixClient(nio.AsyncClient):
# %S = sender's displayname
# %T = target (ev.state_key)'s displayname
async def onRoomMessageText(self, room, ev) -> None:
# pylint: disable=unused-argument
async def onRoomMessageText(self, room, ev, from_past=False) -> None:
co = HTML_FILTER.filter(
ev.formatted_body
if ev.format == "org.matrix.custom.html" else html.escape(ev.body)
@@ -217,26 +256,27 @@ class MatrixClient(nio.AsyncClient):
TimelineMessageReceived.from_nio(room, ev, content=co)
async def onRoomCreateEvent(self, room, ev) -> None:
async def onRoomCreateEvent(self, room, ev, from_past=False) -> None:
co = "%S allowed users on other matrix servers to join this room." \
if ev.federate else \
"%S blocked users on other matrix servers from joining this room."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onRoomGuestAccessEvent(self, room, ev) -> None:
async def onRoomGuestAccessEvent(self, room, ev, from_past=False) -> None:
allowed = "allowed" if ev.guest_access else "forbad"
co = f"%S {allowed} guests to join the room."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onRoomJoinRulesEvent(self, room, ev) -> None:
async def onRoomJoinRulesEvent(self, room, ev, from_past=False) -> None:
access = "public" if ev.join_rule == "public" else "invite-only"
co = f"%S made the room {access}."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onRoomHistoryVisibilityEvent(self, room, ev) -> None:
async def onRoomHistoryVisibilityEvent(self, room, ev, from_past=False
) -> None:
if ev.history_visibility == "shared":
to = "all room members"
elif ev.history_visibility == "world_readable":
@@ -254,7 +294,7 @@ class MatrixClient(nio.AsyncClient):
TimelineEventReceived.from_nio(room, ev, content=co)
async def onPowerLevelsEvent(self, room, ev) -> None:
async def onPowerLevelsEvent(self, room, ev, from_past=False) -> None:
co = "%S changed the room's permissions." # TODO: improve
TimelineEventReceived.from_nio(room, ev, content=co)
@@ -322,9 +362,8 @@ class MatrixClient(nio.AsyncClient):
return None
async def onRoomMemberEvent(self, room, ev) -> None:
# TODO: ignore for past events
if ev.content["membership"] != "leave":
async def onRoomMemberEvent(self, room, ev, from_past=False) -> None:
if not from_past and ev.content["membership"] != "leave":
users.UserUpdated(
user_id = ev.state_key,
display_name = ev.content["displayname"] or "",
@@ -338,40 +377,40 @@ class MatrixClient(nio.AsyncClient):
TimelineEventReceived.from_nio(room, ev, content=co)
async def onRoomAliasEvent(self, room, ev) -> None:
async def onRoomAliasEvent(self, room, ev, from_past=False) -> None:
co = f"%S set the room's main address to {ev.canonical_alias}."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onRoomNameEvent(self, room, ev) -> None:
async def onRoomNameEvent(self, room, ev, from_past=False) -> None:
co = f"%S changed the room's name to \"{ev.name}\"."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onRoomTopicEvent(self, room, ev) -> None:
async def onRoomTopicEvent(self, room, ev, from_past=False) -> None:
co = f"%S changed the room's topic to \"{ev.topic}\"."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onRoomEncryptionEvent(self, room, ev) -> None:
async def onRoomEncryptionEvent(self, room, ev, from_past=False) -> None:
co = f"%S turned on encryption for this room."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onOlmEvent(self, room, ev) -> None:
async def onOlmEvent(self, room, ev, from_past=False) -> None:
co = f"%S hasn't sent your device the keys to decrypt this message."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onMegolmEvent(self, room, ev) -> None:
await self.onOlmEvent(room, ev)
async def onMegolmEvent(self, room, ev, from_past=False) -> None:
await self.onOlmEvent(room, ev, from_past=False)
async def onBadEvent(self, room, ev) -> None:
async def onBadEvent(self, room, ev, from_past=False) -> None:
co = f"%S sent a malformed event."
TimelineEventReceived.from_nio(room, ev, content=co)
async def onUnknownBadEvent(self, room, ev) -> None:
async def onUnknownBadEvent(self, room, ev, from_past=False) -> None:
co = f"%S sent an event this client doesn't understand."
TimelineEventReceived.from_nio(room, ev, content=co)