Add basic functionality
Bots can now - stay connected - set their nick
This commit is contained in:
parent
d0ad542b72
commit
04364c6b3f
5 changed files with 137 additions and 34 deletions
|
|
@ -9,8 +9,9 @@ class TestBot(Controller):
|
||||||
def __init__(self, roomname):
|
def __init__(self, roomname):
|
||||||
super().__init__(roomname)
|
super().__init__(roomname)
|
||||||
|
|
||||||
#async def on_connected(self):
|
async def on_snapshot(self, user_id, session_id, version, listing, log, nick=None,
|
||||||
#await self.room.set_nick("TestBot")
|
pm_with_nick=None, pm_with_user_id=None):
|
||||||
|
await self.room.nick("TestBot")
|
||||||
|
|
||||||
async def on_hello(self, user_id, session, room_is_private, version, account=None,
|
async def on_hello(self, user_id, session, room_is_private, version, account=None,
|
||||||
account_has_access=None, account_email_verified=None):
|
account_has_access=None, account_email_verified=None):
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,14 @@ class Connection:
|
||||||
self.cookie = cookie
|
self.cookie = cookie
|
||||||
self.packet_hook = packet_hook
|
self.packet_hook = packet_hook
|
||||||
|
|
||||||
stopped = False
|
self.stopped = False
|
||||||
|
|
||||||
self._ws = None
|
self._ws = None
|
||||||
self._pid = 0
|
self._pid = 0
|
||||||
self._pending_responses = {}
|
self._pending_responses = {}
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
self._ws = await websockets.connect(self.url)
|
self._ws = await websockets.connect(self.url, max_size=None)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
|
|
@ -35,31 +35,33 @@ class Connection:
|
||||||
self._ws = None
|
self._ws = None
|
||||||
stopped = True
|
stopped = True
|
||||||
|
|
||||||
for futures in self._pending_responses:
|
for future in self._pending_responses:
|
||||||
for future in futures:
|
future.set_error(ConnectionClosed)
|
||||||
future.set_error(ConnectionClosed)
|
future.cancel() # TODO: Is this needed?
|
||||||
future.cancel()
|
|
||||||
|
|
||||||
async def stop(self):
|
async def stop(self):
|
||||||
if not stopped and self._ws:
|
if not self.stopped and self._ws:
|
||||||
await self._ws.close()
|
await self._ws.close()
|
||||||
|
|
||||||
async def send(self, ptype, data=None, await_response=True):
|
async def send(self, ptype, data=None, await_response=True):
|
||||||
if stopped:
|
if self.stopped:
|
||||||
raise ConnectionClosed
|
raise ConnectionClosed
|
||||||
|
|
||||||
pid = self._new_pid()
|
pid = self._new_pid()
|
||||||
packet["type"] = ptype
|
packet = {
|
||||||
packet["data"] = data
|
"type": ptype,
|
||||||
packet["id"] = pid
|
"data": data,
|
||||||
|
"id": str(pid)
|
||||||
|
}
|
||||||
|
|
||||||
if await_response:
|
if await_response:
|
||||||
wait_for = self._wait_for_response(pid)
|
wait_for = self._wait_for_response(pid)
|
||||||
await self._ws.send(json.dumps(packet))
|
|
||||||
|
await self._ws.send(json.dumps(packet, separators=(',', ':')))
|
||||||
|
|
||||||
|
if await_response:
|
||||||
await wait_for
|
await wait_for
|
||||||
return wait_for.result()
|
return wait_for.result()
|
||||||
else:
|
|
||||||
await self._ws.send(json.dumps(packet))
|
|
||||||
|
|
||||||
def _new_pid(self):
|
def _new_pid(self):
|
||||||
self._pid += 1
|
self._pid += 1
|
||||||
|
|
@ -70,7 +72,8 @@ class Connection:
|
||||||
|
|
||||||
# Deal with pending responses
|
# Deal with pending responses
|
||||||
pid = packet.get("id")
|
pid = packet.get("id")
|
||||||
for future in self._pending_responses.pop(pid, []):
|
future = self._pending_responses.pop(pid, None)
|
||||||
|
if future:
|
||||||
future.set_result(packet)
|
future.set_result(packet)
|
||||||
|
|
||||||
# Pass packet onto room
|
# Pass packet onto room
|
||||||
|
|
@ -78,19 +81,17 @@ class Connection:
|
||||||
|
|
||||||
def _wait_for_response(self, pid):
|
def _wait_for_response(self, pid):
|
||||||
future = asyncio.Future()
|
future = asyncio.Future()
|
||||||
|
self._pending_responses[pid] = future
|
||||||
if pid not in self._pending_responses:
|
|
||||||
self._pending_responses[pid] = []
|
|
||||||
self._pending_responses[pid].append(future)
|
|
||||||
|
|
||||||
return future
|
return future
|
||||||
|
|
||||||
def do_nothing(*args, **kwargs):
|
#async def handle_packet(packet):
|
||||||
pass
|
#if packet.get("type") == "ping-event":
|
||||||
|
#await c._ws.send('{"type":"ping-reply","data":{"time":' + str(packet.get("data").get("time")) + '}}')
|
||||||
|
##await c.send("ping-reply", {"time": packet.get("data").get("time")}, False)
|
||||||
|
|
||||||
def run():
|
#c = Connection("wss://euphoria.io/room/test/ws", handle_packet)
|
||||||
conn = Connection("wss://echo.websocket.org", do_nothing)
|
|
||||||
loop = asyncio.get_event_loop()
|
#def run():
|
||||||
#loop.call_later(3, conn.stop)
|
#loop = asyncio.get_event_loop()
|
||||||
|
#loop.run_until_complete(asyncio.ensure_future(c.run()))
|
||||||
loop.run_until_complete(asyncio.ensure_future(conn.run()))
|
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,17 @@ class Controller:
|
||||||
await self.room.stop()
|
await self.room.stop()
|
||||||
|
|
||||||
async def on_start(self):
|
async def on_start(self):
|
||||||
|
"""
|
||||||
|
The first callback called when the controller is run.
|
||||||
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def on_stop(self):
|
async def on_stop(self):
|
||||||
|
"""
|
||||||
|
The last callback called when the controller is run.
|
||||||
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def on_connected(self):
|
async def on_connected(self):
|
||||||
|
|
@ -124,6 +132,6 @@ class Controller:
|
||||||
async def on_send(self, message):
|
async def on_send(self, message):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def on_snapshot(self, user_id, snapshot_id, version, listing, log, nick=None,
|
async def on_snapshot(self, user_id, session_id, version, listing, log, nick=None,
|
||||||
pm_with_nick=None, pm_with_user_id=None):
|
pm_with_nick=None, pm_with_user_id=None):
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ class Room:
|
||||||
self.account_email_verified = None
|
self.account_email_verified = None
|
||||||
self.room_is_private = None
|
self.room_is_private = None
|
||||||
self.version = None # the version of the code being run and served by the server
|
self.version = None # the version of the code being run and served by the server
|
||||||
|
self.pm_with_nick = None
|
||||||
|
self.pm_with_user_id = None
|
||||||
|
|
||||||
self._callbacks = {}
|
self._callbacks = {}
|
||||||
self._add_callbacks()
|
self._add_callbacks()
|
||||||
|
|
@ -46,7 +48,15 @@ class Room:
|
||||||
pass # TODO
|
pass # TODO
|
||||||
|
|
||||||
async def ping_reply(self, time):
|
async def ping_reply(self, time):
|
||||||
pass # TODO
|
"""
|
||||||
|
The ping command initiates a client-to-server ping. The server will
|
||||||
|
send back a ping-reply with the same timestamp as soon as possible.
|
||||||
|
|
||||||
|
ping-reply is a response to a ping command or ping-event.
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = {"time": time}
|
||||||
|
await self._conn.send("ping-reply", data, await_response=False)
|
||||||
|
|
||||||
# CATEGORY: CHAT ROOM COMMANDS
|
# CATEGORY: CHAT ROOM COMMANDS
|
||||||
|
|
||||||
|
|
@ -57,7 +67,28 @@ class Room:
|
||||||
pass # TODO
|
pass # TODO
|
||||||
|
|
||||||
async def nick(self, name):
|
async def nick(self, name):
|
||||||
pass # TODO
|
"""
|
||||||
|
session_id, user_id, from_nick, to_nick = await nick(name)
|
||||||
|
|
||||||
|
The nick command sets the name you present to the room. This name
|
||||||
|
applies to all messages sent during this session, until the nick
|
||||||
|
command is called again.
|
||||||
|
|
||||||
|
nick-reply confirms the nick command. It returns the session’s former
|
||||||
|
and new names (the server may modify the requested nick).
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = {"name": name}
|
||||||
|
response = await self._conn.send("nick", data)
|
||||||
|
|
||||||
|
session_id = response.get("session_id")
|
||||||
|
user_id = response.get("id")
|
||||||
|
from_nick = response.get("from")
|
||||||
|
to_nick = response.get("to")
|
||||||
|
|
||||||
|
self.session.nick = to_nick
|
||||||
|
|
||||||
|
return session_id, user_id, from_nick, to_nick
|
||||||
|
|
||||||
async def pm_initiate(self, user_id):
|
async def pm_initiate(self, user_id):
|
||||||
pass # TODO
|
pass # TODO
|
||||||
|
|
@ -164,7 +195,11 @@ class Room:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data = packet.get("data")
|
data = packet.get("data")
|
||||||
await self.controller.on_ping(data.get("time"), data.get("next"))
|
|
||||||
|
await self.controller.on_ping(
|
||||||
|
data.get("time"),
|
||||||
|
data.get("next")
|
||||||
|
)
|
||||||
|
|
||||||
async def _handle_pm_initiate(self, packet):
|
async def _handle_pm_initiate(self, packet):
|
||||||
pass # TODO
|
pass # TODO
|
||||||
|
|
@ -173,4 +208,33 @@ class Room:
|
||||||
pass # TODO
|
pass # TODO
|
||||||
|
|
||||||
async def _handle_snapshot(self, packet):
|
async def _handle_snapshot(self, packet):
|
||||||
pass # TODO
|
"""
|
||||||
|
A snapshot-event indicates that a session has successfully joined a
|
||||||
|
room. It also offers a snapshot of the room’s state and recent history.
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = packet.get("data")
|
||||||
|
|
||||||
|
for session_data in data.get("listing"):
|
||||||
|
session = utils.Session.from_dict(session_data)
|
||||||
|
self.listing.add(session)
|
||||||
|
|
||||||
|
log = [utils.Message.from_dict(d) for d in data.get("log")]
|
||||||
|
|
||||||
|
self.session.nick = data.get("nick")
|
||||||
|
|
||||||
|
self.pm_with_nick = data.get("pm_with_nick"),
|
||||||
|
self.pm_with_user_id = data.get("pm_with_user_id")
|
||||||
|
|
||||||
|
await self.controller.on_connected()
|
||||||
|
|
||||||
|
await self.controller.on_snapshot(
|
||||||
|
data.get("identity"),
|
||||||
|
data.get("session_id"),
|
||||||
|
self.version,
|
||||||
|
self.listing,
|
||||||
|
log,
|
||||||
|
nick=self.session.nick,
|
||||||
|
pm_with_nick=self.pm_with_nick,
|
||||||
|
pm_with_user_id=self.pm_with_user_id
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -64,3 +64,32 @@ class Listing:
|
||||||
def get_bots(self):
|
def get_bots(self):
|
||||||
return {uid: ses for uid, ses in self._sessions.items()
|
return {uid: ses for uid, ses in self._sessions.items()
|
||||||
if ses.client_type is "bot"}
|
if ses.client_type is "bot"}
|
||||||
|
|
||||||
|
class Message():
|
||||||
|
def __init__(self, message_id, time, sender, content, parent=None, previous_edit_id=None,
|
||||||
|
encryption_key=None, edited=None, deleted=None, truncated=None):
|
||||||
|
self.message_id = message_id
|
||||||
|
self.time = time
|
||||||
|
self.sender = sender
|
||||||
|
self.content = content
|
||||||
|
self.parent = parent
|
||||||
|
self.previous_edit_id = previous_edit_id
|
||||||
|
self.encryption_key = encryption_key
|
||||||
|
self.edited = edited
|
||||||
|
self.deleted = deleted
|
||||||
|
self.truncated = truncated
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, d):
|
||||||
|
return cls(
|
||||||
|
d.get("id"),
|
||||||
|
d.get("time"),
|
||||||
|
Session.from_dict(d.get("sender")),
|
||||||
|
d.get("content"),
|
||||||
|
d.get("parent"),
|
||||||
|
d.get("previous_edit_id"),
|
||||||
|
d.get("encryption_key"),
|
||||||
|
d.get("edited"),
|
||||||
|
d.get("deleted"),
|
||||||
|
d.get("truncated")
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue