import html
import json
import logging
import websockets
from tools.commons import AbstractResponse, Message, BotMessage, AttackCommand, Sound, UserList
from tools.processors import MessageDispatcher, ConnectionDispatcher
class CoboBot:
def __init__(self, cookie : str, channel : str, domain : str, port : int, method : str,
messages_dispatcher : MessageDispatcher,
connect_dispatcher : ConnectionDispatcher):
# setting up variables required by the server. The default is a Kabutops on the main lou server, I think
self.cookie = cookie
self.channel = "" if channel == "root" else channel
self.domain = domain
self.port = port
self.method = method
self.msg_dispatch = messages_dispatcher
self.cnt_dispatch = connect_dispatcher
self.user_list = None # type: UserList
async def _send_message(self, message):
if isinstance(message, dict):
await self.socket.send(json.dumps(message))
elif isinstance(message, bytes):
await self.socket.send(message)
async def _dispatch_response(self, response_obj : AbstractResponse):
if isinstance(response_obj, (Message, BotMessage, AttackCommand)):
await self._send_message(response_obj.to_dict())
elif isinstance(response_obj, Sound):
await self._send_message(response_obj.get_bytes())
async def _on_connect(self, msg_data):
# registering the user to the user list
self.user_list.add_user(msg_data["userid"], msg_data["params"])
logging.info("%s connected" % self.user_list.name(msg_data["userid"]))
message = self.cnt_dispatch.dispatch(msg_data["userid"], self.user_list)
await self._send_message(message)
async def _on_disconnect(self, msg_data):
# removing the user from the userlist
logging.info("%s disconnected" % self.user_list.name(msg_data["userid"]))
self.user_list.del_user(msg_data["userid"])
async def _on_message(self, msg_data):
msg_data["msg"] = html.unescape(msg_data["msg"]) # removing HTML shitty encoding
# logging the message to the DB
logging.info("%s says : \"%s\"" % (self.user_list.name(msg_data["userid"]), msg_data["msg"]))
response = None
# dispatching the message to the processors. If there's a response, send it to the chat
if not self.user_list.itsme(msg_data["userid"]):
response = self.msg_dispatch.dispatch(msg_data["msg"], msg_data["userid"], self.user_list)
if isinstance(response, list):
for response_obj in response:
await self._dispatch_response(response_obj)
elif isinstance(response, AbstractResponse):
await self._dispatch_response(response)
async def listen(self):
if self.method == "https":
socket_address = 'wss://%s/socket/%s' % (self.domain, self.channel)
else:
socket_address = 'ws://%s:%i/socket/%s' % (self.domain, self.port, self.channel)
logging.info("Listening to socket on %s" % socket_address)
async with websockets.connect(socket_address,
extra_headers={"cookie": "id=%s" % self.cookie}) as websocket:
self.socket = websocket
while True:
msg = await websocket.recv()
websocket.recv()
if type(msg) != bytes:
msg_data = json.loads(msg, encoding="utf-8")
msg_type = msg_data.get("type", "")
if msg_type == "userlist":
self.user_list = UserList(msg_data["users"])
logging.info(str(self.user_list))
elif msg_type == "msg":
await self._on_message(msg_data)
elif msg_type == "connect":
await self._on_connect(msg_data)
elif msg_type == "disconnect":
await self._on_disconnect(msg_data)
else:
logging.debug("Received sound file")