Implement rewind/fast-forward system
This commit is contained in:
parent
7e28c6e3dd
commit
55798a5b88
1 changed files with 64 additions and 11 deletions
|
|
@ -19,6 +19,7 @@ class Room:
|
|||
CONNECTED = 1
|
||||
DISCONNECTED = 2
|
||||
CLOSED = 3
|
||||
FORWARDING = 4
|
||||
|
||||
def __init__(self, inhabitant, roomname, nick, password=None, human=False, cookiejar=None):
|
||||
# TODO: Connect to room etc.
|
||||
|
|
@ -48,6 +49,10 @@ class Room:
|
|||
self._status = Room.DISCONNECTED
|
||||
self._connected_future = asyncio.Future()
|
||||
|
||||
self._last_known_mid = None
|
||||
self._forwarding = None # task that downloads messages and fowards
|
||||
self._forward_new = [] # new messages received while downloading old messages
|
||||
|
||||
# TODO: Allow for all parameters of Connection() to be specified in Room().
|
||||
self._connection = Connection(
|
||||
self.format_room_url(self.roomname, human=self.human),
|
||||
|
|
@ -78,15 +83,16 @@ class Room:
|
|||
|
||||
return Message.from_dict(data)
|
||||
|
||||
async def log(self, n, before_mid=None):
|
||||
# The log returned is sorted from old to new
|
||||
async def log(self, n, before=None):
|
||||
if self._status == Room.CLOSED:
|
||||
raise RoomClosed()
|
||||
|
||||
if before_mid:
|
||||
if before:
|
||||
ptype, data, error, throttled = await self._send_while_connected(
|
||||
"log",
|
||||
n=n,
|
||||
before=before_mid
|
||||
before=before
|
||||
)
|
||||
else:
|
||||
ptype, data, error, throttled = await self._send_while_connected(
|
||||
|
|
@ -128,12 +134,12 @@ class Room:
|
|||
to_nick = data.get("to_nick")
|
||||
return pm_id, to_nick
|
||||
|
||||
async def send(self, content, parent_mid=None):
|
||||
if parent_mid:
|
||||
async def send(self, content, parent=None):
|
||||
if parent:
|
||||
ptype, data, error, throttled = await self._send_while_connected(
|
||||
"send",
|
||||
content=content,
|
||||
parent=parent_mid
|
||||
parent=parent
|
||||
)
|
||||
else:
|
||||
ptype, data, error, throttled = await self._send_while_connected(
|
||||
|
|
@ -141,7 +147,9 @@ class Room:
|
|||
content=content
|
||||
)
|
||||
|
||||
return Message.from_dict(data)
|
||||
message = Message.from_dict(data)
|
||||
self._last_known_mid = message.mid
|
||||
return message
|
||||
|
||||
async def who(self):
|
||||
ptype, data, error, throttled = await self._send_while_connected("who")
|
||||
|
|
@ -156,6 +164,9 @@ class Room:
|
|||
self.status = Room.DISCONNECTED
|
||||
self._connected_future = asyncio.Future()
|
||||
|
||||
if self._forwarding is not None:
|
||||
self._forwarding.cancel()
|
||||
|
||||
await self._inhabitant.disconnected(self)
|
||||
|
||||
async def _receive_packet(self, ptype, data, error, throttled):
|
||||
|
|
@ -254,14 +265,20 @@ class Room:
|
|||
async def _event_send(self, data):
|
||||
message = Message.from_dict(data)
|
||||
|
||||
await self._inhabitant.send(self, message)
|
||||
if self._status == Room.FORWARDING:
|
||||
self._forward_new.append(message)
|
||||
else:
|
||||
self._last_known_mid = message.mid
|
||||
await self._inhabitant.send(self, message)
|
||||
|
||||
# TODO: Figure out a way to bring fast-forwarding into this
|
||||
|
||||
async def _event_snapshot(self, data):
|
||||
log = [Message.from_dict(m) for m in data.get("log")]
|
||||
sessions = [Session.from_dict(d) for d in data.get("listing")]
|
||||
|
||||
# Update listing
|
||||
self.listing = Listing()
|
||||
sessions = [Session.from_dict(d) for d in data.get("listing")]
|
||||
for session in sessions:
|
||||
self.listing.add(session)
|
||||
self.listing.add(self.session)
|
||||
|
|
@ -280,13 +297,23 @@ class Room:
|
|||
return # Aww, we've lost connection again
|
||||
|
||||
# Now, we're finally connected again!
|
||||
self.status = Room.CONNECTED
|
||||
if self._last_known_mid is None:
|
||||
self._status = Room.CONNECTED
|
||||
if log: # log goes from old to new
|
||||
self._last_known_mid = log[-1].mid
|
||||
else:
|
||||
self._status = Room.FORWARDING
|
||||
self._forward_new = []
|
||||
|
||||
if self._forwarding is not None:
|
||||
self._forwarding.cancel()
|
||||
self._forwarding = asyncio.ensure_future(self._forward(log))
|
||||
|
||||
if not self._connected_future.done(): # Should never be done already, I think
|
||||
self._connected_future.set_result(None)
|
||||
|
||||
# Let's let the inhabitant know.
|
||||
logger.debug("Letting inhabitant know")
|
||||
log = [Message.from_dict(m) for m in data.get("log")]
|
||||
await self._inhabitant.connected(self, log)
|
||||
|
||||
# TODO: Figure out a way to bring fast-forwarding into this
|
||||
|
|
@ -311,6 +338,32 @@ class Room:
|
|||
|
||||
# REST OF THE IMPLEMENTATION
|
||||
|
||||
async def _forward(self, log):
|
||||
old_messages = []
|
||||
while True:
|
||||
found_last_known = True
|
||||
for message in reversed(log):
|
||||
if message.mid <= self._last_known_mid:
|
||||
break
|
||||
old_messages.append(message)
|
||||
else:
|
||||
found_last_known = False
|
||||
|
||||
if found_last_known:
|
||||
break
|
||||
|
||||
log = await self.log(100, before=log[0].mid)
|
||||
|
||||
for message in reversed(old_messages):
|
||||
self._last_known_mid = message.mid
|
||||
asyncio.ensure_future(self._inhabitant.forward(self, message))
|
||||
for message in self._forward_new:
|
||||
self._last_known_mid = message.mid
|
||||
asyncio.ensure_future(self._inhabitant.forward(self, message))
|
||||
|
||||
self._forward_new = []
|
||||
self._status = Room.CONNECTED
|
||||
|
||||
async def _send_while_connected(self, *args, **kwargs):
|
||||
while True:
|
||||
if self._status == Room.CLOSED:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue