diff --git a/src/snekbot.egg-info/PKG-INFO b/src/snekbot.egg-info/PKG-INFO index 19bdd90..0d49e78 100644 --- a/src/snekbot.egg-info/PKG-INFO +++ b/src/snekbot.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: snekbot -Version: 1.0.0 +Version: 1.1.0 Summary: Bot API for Snek chat Author-email: retoor Keywords: chat,snek,molodetz,bot diff --git a/src/snekbot/bot.py b/src/snekbot/bot.py index f83bead..9e99a02 100644 --- a/src/snekbot/bot.py +++ b/src/snekbot/bot.py @@ -89,7 +89,7 @@ class Bot: async def get_channels(self, refresh=False): if refresh or not self._channels: - self._channels = await (await self.rpc.get_channels())() + self._channels = await self.rpc.get_channels() return self._channels async def run_once(self): @@ -101,8 +101,8 @@ class Bot: rpc = RPC(self.ws) self.rpc = rpc - await (await rpc.login(self.username, self.password))() - self.user = await (await rpc.get_user(None))() + await rpc.login(self.username, self.password) + self.user = await rpc.get_user(None) logger.debug("Logged in as: " + self.user["username"]) if is_initial: @@ -118,17 +118,31 @@ class Bot: while True: data = await rpc.receive() - if not data: return + + event = "?" + try: + event = data.event + except AttributeError: + pass try: message = data.message.strip() + event = "message" except AttributeError: + pass + + if event == "?": continue - else: + elif event == "message": break + try: + await getattr(self, "on_" + data.event)(**data.data) + except AttributeError: + logger.debug("Not implemented event: " + event) + if data.username == self.user["username"]: await self.on_own_message(data.channel_uid, message) elif message.startswith("ping"): diff --git a/src/snekbot/rpc.py b/src/snekbot/rpc.py index 02f6a47..cb51028 100644 --- a/src/snekbot/rpc.py +++ b/src/snekbot/rpc.py @@ -13,7 +13,7 @@ import logging import pathlib import subprocess import uuid - +import asyncio import aiohttp logger = logging.getLogger("snekbot.rpc") @@ -53,13 +53,15 @@ class RPC: def __init__(self, ws): self.ws = ws self.current_call_id = None + self.queue = asyncio.Queue() - async def echo(self, data): + async def queue(self, data): logger.debug("Schedule for retry: " + str(data)) - await self.ws.send_json({"method": "echo", "args": [data]}) + await self.queue.put(data) def __getattr__(self, name): async def method(*args, **kwargs): + no_response = kwargs.pop("_no_response", False) self.current_call_id = str(uuid.uuid4()) payload = { "method": name, @@ -73,12 +75,16 @@ class RPC: while True: response = await self.ws.receive() data = response.json() - if not data.get("callId") == self.current_call_id: - await self.echo(data) + if data.get("callId") != self.current_call_id: + await self.queue.put(data) continue + self.current_call_id = None return self.Response(data) - return returner + if no_response: + return True + + return await returner() return method @@ -108,6 +114,16 @@ class RPC: return response async def receive(self): + + popped = [] + while not self.queue.empty(): + msg = await self.queue.get() + if self.current_call_id == msg.get("callId"): + for m in popped: + await self.queue.put(m) + self.current_call_id = None + return self.Response(msg) + while True: try: msg = await self.ws.receive() @@ -121,12 +137,10 @@ class RPC: logger.exception("WebSocket error.") break elif msg.type == aiohttp.WSMsgType.TEXT: - if ( - self.current_call_id - and not msg.json().get("callId") != self.current_call_id + msg.json().get("callId") != self.current_call_id ): - await self.echo(msg.json()) + await self.queue.put(msg.json()) continue try: response = self.Response(msg.json())