Make more events work (and use an annoying bot to test them)

This commit is contained in:
Joscha 2017-09-02 12:27:38 +00:00
parent 04364c6b3f
commit dfad3241fb
5 changed files with 208 additions and 41 deletions

View file

@ -1,6 +1,7 @@
import asyncio
#from controller import Bot
from controller import Controller
from utils import *
@ -12,10 +13,34 @@ class TestBot(Controller):
async def on_snapshot(self, user_id, session_id, version, listing, log, nick=None,
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,
account_has_access=None, account_email_verified=None):
print(repr(session.user_id), repr(session.session_id), repr(session.name))
async def on_send(self, message):
await self.room.send("Hey, a message!", message.message_id)
async def on_join(self, session):
if session.nick != "":
await self.room.send(f"Hey, a @{mention(session.nick)}!")
else:
await self.room.send("Hey, a lurker!")
async def on_nick(self, session_id, user_id, from_nick, to_nick):
if from_nick != "" and to_nick != "":
if from_nick == to_nick:
await self.room.send(f"You didn't even change your nick, @{mention(to_nick)} :(")
else:
await self.room.send(f"Bye @{mention(from_nick)}, hi @{mention(to_nick)}")
elif from_nick != "":
await self.room.send(f"Bye @{mention(from_nick)}? This message should never appear...")
elif to_nick != "":
await self.room.send(f"Hey, a @{mention(to_nick)}!")
else:
await self.room.send("I have no idea how you did that. This message should never appear...")
async def on_part(self, session):
if session.nick != "":
await self.room.send(f"Bye, you @{mention(session.nick)}!")
else:
await self.room.send("Bye, you lurker!")
if __name__ == "__main__":
bot = TestBot("test")

View file

@ -36,8 +36,8 @@ class Connection:
stopped = True
for future in self._pending_responses:
future.set_error(ConnectionClosed)
future.cancel() # TODO: Is this needed?
#future.set_error(ConnectionClosed)
future.cancel()
async def stop(self):
if not self.stopped and self._ws:
@ -92,6 +92,16 @@ class Connection:
#c = Connection("wss://euphoria.io/room/test/ws", handle_packet)
#def run():
#loop = asyncio.get_event_loop()
#loop.run_until_complete(asyncio.ensure_future(c.run()))
async def await_future(f):
await f
print(f.result())
def run():
f = asyncio.Future()
#f.set_result("Hello World!")
f.cancel()
#f.set_result("Hello World!")
loop = asyncio.get_event_loop()
loop.run_until_complete(await_future(f))
#loop.run_until_complete(c.run())

View file

@ -110,7 +110,7 @@ class Controller:
async def on_network(self, ntype, server_id, server_era):
pass
async def on_nick(self, session_id, user_id, from_name, to_name):
async def on_nick(self, session_id, user_id, from_nick, to_nick):
pass
async def on_edit_message(self, edit_id, message):

View file

@ -49,6 +49,7 @@ class Room:
async def ping_reply(self, time):
"""
From api.euphoria.io:
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.
@ -70,6 +71,7 @@ class Room:
"""
session_id, user_id, from_nick, to_nick = await nick(name)
From api.euphoria.io:
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.
@ -79,7 +81,9 @@ class Room:
"""
data = {"name": name}
response = await self._conn.send("nick", data)
self._check_for_errors(response)
session_id = response.get("session_id")
user_id = response.get("id")
@ -94,7 +98,28 @@ class Room:
pass # TODO
async def send(self, content, parent=None):
pass # TODO
"""
From api.euphoria.io:
The send command sends a message to a room. The session must be
successfully joined with the room. This message will be broadcast to
all sessions joined with the room.
If the room is private, then the message content will be encrypted
before it is stored and broadcast to the rest of the room.
The caller of this command will not receive the corresponding
send-event, but will receive the same information in the send-reply.
"""
data = {"content": content}
if parent:
data["parent"] = parent
response = await self._conn.send("send", data)
self._check_for_errors(response)
message = utils.Message.from_dict(response.get("data"))
return message
async def who(self):
pass # TODO
@ -129,16 +154,52 @@ class Room:
self._callbacks["snapshot-event"] = self._handle_snapshot
async def _handle_packet(self, packet):
self._check_for_errors(packet)
ptype = packet.get("type")
callback = self._callbacks.get(ptype)
if callback:
await callback(packet)
try:
await callback(packet)
except asyncio.CancelledError as e:
# TODO: log error
print("HEHEHEHEY, CANCELLEDERROR", e)
pass
def _check_for_errors(self, packet):
# TODO: log throttled
if "error" in packet:
raise utils.ResponseError(response.get("error"))
async def _handle_bounce(self, packet):
pass # TODO
"""
From api.euphoria.io:
A bounce-event indicates that access to a room is denied.
"""
data = packet.get("data")
await self.controller.on_bounce(
reason=data.get("reason", None),
auth_options=data.get("auth_options", None),
agent_id=data.get("agent_id", None),
ip=data.get("ip", None)
)
async def _handle_disconnect(self, packet):
pass # TODO
"""
From api.euphoria.io:
A disconnect-event indicates that the session is being closed. The
client will subsequently be disconnected.
If the disconnect reason is authentication changed, the client should
immediately reconnect.
"""
data = packet.get("data")
await self.controller.on_disconnect(data.get("reason"))
async def _handle_hello(self, packet):
"""
@ -150,10 +211,11 @@ class Room:
data = packet.get("data")
self.session = utils.Session.from_dict(data.get("session"))
self.account_has_access = data.get("account_has_access")
self.account_email_verified = data.get("account_email_verified")
self.room_is_private = data.get("room_is_private")
self.version = data.get("version")
self.account = data.get("account", None)
self.account_has_access = data.get("account_has_access", None)
self.account_email_verified = data.get("account_email_verified", None)
await self.controller.on_hello(
data.get("id"),
@ -166,7 +228,18 @@ class Room:
)
async def _handle_join(self, packet):
pass # TODO
"""
From api.euphoria.io:
A join-event indicates a session just joined the room.
"""
data = packet.get("data")
session = utils.Session.from_dict(data)
# update self.listing
self.listing.add(session)
await self.controller.on_join(session)
async def _handle_login(self, packet):
pass # TODO
@ -178,13 +251,43 @@ class Room:
pass # TODO
async def _handle_nick(self, packet):
pass # TODO
"""
From api.euphoria.io:
nick-event announces a nick change by another session in the room.
"""
data = packet.get("data")
session_id = data.get("session_id")
to_nick = data.get("to")
# update self.listing
session = self.listing.by_sid(session_id)
if session:
session.nick = to_nick
await self.controller.on_nick(
session_id,
data.get("id"),
data.get("from"),
to_nick
)
async def _handle_edit_message(self, packet):
pass # TODO
async def _handle_part(self, packet):
pass # TODO
"""
From api.euphoria.io:
A part-event indicates a session just disconnected from the room.
"""
data = packet.get("data")
session = utils.Session.from_dict(data)
# update self.listing
self.listing.remove(session.session_id)
await self.controller.on_part(session)
async def _handle_ping(self, packet):
"""
@ -205,26 +308,37 @@ class Room:
pass # TODO
async def _handle_send(self, packet):
pass # TODO
"""
From api.euphoria.io:
A send-event indicates a message received by the room from another
session.
"""
data = packet.get("data")
message = utils.Message.from_dict(data)
await self.controller.on_send(message)
async def _handle_snapshot(self, packet):
"""
From api.euphoria.io:
A snapshot-event indicates that a session has successfully joined a
room. It also offers a snapshot of the rooms state and recent history.
"""
data = packet.get("data")
for session_data in data.get("listing"):
session = utils.Session.from_dict(session_data)
sessions = [utils.Session.from_dict(d) for d in data.get("listing")]
messages = [utils.Message.from_dict(d) for d in data.get("log")]
# update self.listing
for session in sessions:
self.listing.add(session)
log = [utils.Message.from_dict(d) for d in data.get("log")]
self.session.nick = data.get("nick")
self.session.nick = data.get("nick", None)
self.pm_with_nick = data.get("pm_with_nick"),
self.pm_with_user_id = data.get("pm_with_user_id")
self.pm_with_nick = data.get("pm_with_nick", None),
self.pm_with_user_id = data.get("pm_with_user_id", None)
await self.controller.on_connected()
@ -232,8 +346,8 @@ class Room:
data.get("identity"),
data.get("session_id"),
self.version,
self.listing,
log,
sessions, # listing
messages, # log
nick=self.session.nick,
pm_with_nick=self.pm_with_nick,
pm_with_user_id=self.pm_with_user_id

View file

@ -1,8 +1,23 @@
import re
__all__ = ["mention", "mention_reduced", "similar", "Session", "Listing", "Message", "Log"]
def mention(nick):
return "".join(c for c in nick if c not in ".!?;&<'\"" and not c.isspace())
def mention_reduced(nick):
return mention(nick).lower()
def similar(nick1, nick2):
return mention_reduced(nick1) == mention_reduced(nick2)
class Session:
def __init__(self, user_id, name, server_id, server_era, session_id, is_staff=None,
def __init__(self, user_id, nick, server_id, server_era, session_id, is_staff=None,
is_manager=None, client_address=None, real_address=None):
self.user_id = user_id
self.name = name
self.nick = nick
self.server_id = server_id
self.server_era = server_era
self.session_id = session_id
@ -19,10 +34,10 @@ class Session:
d.get("server_id"),
d.get("server_era"),
d.get("session_id"),
d.get("is_staff"),
d.get("is_manager"),
d.get("client_address"),
d.get("real_address")
d.get("is_staff", None),
d.get("is_manager", None),
d.get("client_address", None),
d.get("real_address", None)
)
@property
@ -86,10 +101,13 @@ class Message():
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")
d.get("parent", None),
d.get("previous_edit_id", None),
d.get("encryption_key", None),
d.get("edited", None),
d.get("deleted", None),
d.get("truncated", None)
)
class Log:
pass # TODO