Fix some bugs. The TestBot can now connect to a room and stay connected.

This commit is contained in:
Joscha 2017-09-02 08:55:50 +00:00
parent 97b98c29f7
commit d0ad542b72
5 changed files with 148 additions and 31 deletions

View file

@ -1,15 +1,21 @@
import asyncio
from controller import Bot
#from controller import Bot
from controller import Controller
class TestBot(Bot):
def __init__(self):
pass
#class TestBot(Bot):
class TestBot(Controller):
def __init__(self, roomname):
super().__init__(roomname)
async def on_connected(self):
await self.room.set_nick("TestBot")
#async def on_connected(self):
#await self.room.set_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))
if __name__ == "__main__":
bot = TestBot()
bot = TestBot("test")
asyncio.get_event_loop().run_until_complete(bot.run())

View file

@ -44,7 +44,7 @@ class Connection:
if not stopped and self._ws:
await self._ws.close()
async def send(ptype, data=None, await_response=True):
async def send(self, ptype, data=None, await_response=True):
if stopped:
raise ConnectionClosed
@ -65,7 +65,7 @@ class Connection:
self._pid += 1
return self._pid
async def _handle_json(text):
async def _handle_json(self, text):
packet = json.loads(text)
# Deal with pending responses
@ -76,7 +76,7 @@ class Connection:
# Pass packet onto room
await self.packet_hook(packet)
def _wait_for_response(pid):
def _wait_for_response(self, pid):
future = asyncio.Future()
if pid not in self._pending_responses:

View file

@ -1,4 +1,4 @@
from .room import Room
from room import Room
@ -53,7 +53,12 @@ class Controller:
if self.room:
await self.room.stop()
# room successfully connected
async def on_start(self):
pass
async def on_stop(self):
pass
async def on_connected(self):
"""
Client has successfully (re-)joined the room.
@ -81,7 +86,8 @@ class Controller:
async def on_disconnect(self, reason):
pass
async def on_hello(self, user_id, session, room_is_private, version, account=None, account_has_access=None, account_email_verified=None):
async def on_hello(self, user_id, session, room_is_private, version, account=None,
account_has_access=None, account_email_verified=None):
pass
async def on_join(self, session):
@ -96,7 +102,7 @@ class Controller:
async def on_network(self, ntype, server_id, server_era):
pass
async def on_nick(self, session_id, user_id, from, to):
async def on_nick(self, session_id, user_id, from_name, to_name):
pass
async def on_edit_message(self, edit_id, message):
@ -112,11 +118,12 @@ class Controller:
await self.room.ping_reply(ptime)
async def on_pm_initiate(self, from, from_nick, from_room, pm_id):
async def on_pm_initiate(self, from_id, from_nick, from_room, pm_id):
pass
async def on_send(self, message):
pass
async def on_snapshot(self, user_id, snapshot_id, version, listing, log, nick=None, pm_with_nick=None, pm_with_user_id=None):
async def on_snapshot(self, user_id, snapshot_id, version, listing, log, nick=None,
pm_with_nick=None, pm_with_user_id=None):
pass

View file

@ -1,5 +1,6 @@
import asyncio
from .connection import Connection
from connection import Connection
import utils
class Room:
ROOM_FORMAT = "wss://euphoria.io/room/{}/ws"
@ -15,15 +16,22 @@ class Room:
# with differently by different controllers.
# If you need to keep track of messages, use utils.Log.
self.session = None
self.sessions = None
self.account = None
self.listing = utils.Listing()
# Various room information
self.account_has_access = None
self.account_email_verified = None
self.room_is_private = None
self.version = None # the version of the code being run and served by the server
self._callbacks = {}
self._add_callbacks()
if human:
url = HUMAN_FORMAT.format(self.roomname)
url = self.HUMAN_FORMAT.format(self.roomname)
else:
url = ROOM_FORMAT.format(self.roomname)
url = self.ROOM_FORMAT.format(self.roomname)
self._conn = Connection(url, self._handle_packet, self.cookie)
async def run(self):
@ -34,30 +42,30 @@ class Room:
# CATEGORY: SESSION COMMANDS
async def auth(atype, passcode):
async def auth(self, atype, passcode):
pass # TODO
async def ping_reply(time):
async def ping_reply(self, time):
pass # TODO
# CATEGORY: CHAT ROOM COMMANDS
async def get_message(message_id):
async def get_message(self, message_id):
pass # TODO
async def log(n, before=None):
async def log(self, n, before=None):
pass # TODO
async def nick(name):
async def nick(self, name):
pass # TODO
async def pm_initiate(user_id):
async def pm_initiate(self, user_id):
pass # TODO
async def send(content, parent=None):
async def send(self, content, parent=None):
pass # TODO
async def who()
async def who(self):
pass # TODO
# CATEGORY: ACCOUNT COMMANDS
@ -102,7 +110,29 @@ class Room:
pass # TODO
async def _handle_hello(self, packet):
pass # TODO
"""
From api.euphoria.io:
A hello-event is sent by the server to the client when a session is
started. It includes information about the clients authentication and
associated identity.
"""
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")
await self.controller.on_hello(
data.get("id"),
self.session,
self.room_is_private,
self.version,
account=self.account,
account_has_access=self.account_has_access,
account_email_verified=self.account_email_verified
)
async def _handle_join(self, packet):
pass # TODO
@ -126,7 +156,15 @@ class Room:
pass # TODO
async def _handle_ping(self, packet):
pass # TODO
"""
From api.euphoria.io:
A ping-event represents a server-to-client ping. The client should send
back a ping-reply with the same value for the time field as soon as
possible (or risk disconnection).
"""
data = packet.get("data")
await self.controller.on_ping(data.get("time"), data.get("next"))
async def _handle_pm_initiate(self, packet):
pass # TODO

66
yaboli/utils.py Normal file
View file

@ -0,0 +1,66 @@
class Session:
def __init__(self, user_id, name, 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.server_id = server_id
self.server_era = server_era
self.session_id = session_id
self.is_staff = is_staff
self.is_manager = is_manager
self.client_address = client_address
self.real_address = real_address
@classmethod
def from_dict(cls, d):
return cls(
d.get("id"),
d.get("name"),
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")
)
@property
def client_type(self):
# account, agent or bot
return self.user_id.split(":")[0]
class Listing:
def __init__(self):
self._sessions = {}
def __len__(self):
return len(self._sessions)
def add(self, session):
self._sessions[session.session_id] = session
def remove(self, session_id):
self._sessions.pop(session_id)
def by_sid(self, session_id):
return self._sessions.get(session_id);
def by_uid(self, user_id):
return [ses for ses in self._sessions if ses.user_id == user_id]
def get_people(self):
return {uid: ses for uid, ses in self._sessions.items()
if ses.client_type in ["agent", "account"]}
def get_accounts(self):
return {uid: ses for uid, ses in self._sessions.items()
if ses.client_type is "account"}
def get_agents(self):
return {uid: ses for uid, ses in self._sessions.items()
if ses.client_type is "agent"}
def get_bots(self):
return {uid: ses for uid, ses in self._sessions.items()
if ses.client_type is "bot"}