2021-06-26 15:08:48 +00:00
|
|
|
import asyncio, traceback
|
2020-04-01 14:36:53 +00:00
|
|
|
import anyio
|
2020-04-02 17:00:28 +00:00
|
|
|
from typing import Dict
|
2020-04-01 14:36:53 +00:00
|
|
|
|
2020-04-20 11:04:01 +00:00
|
|
|
from ircstates.server import ServerDisconnectedException
|
|
|
|
|
2020-04-06 12:22:17 +00:00
|
|
|
from .server import ConnectionParams, Server
|
|
|
|
from .transport import TCPTransport
|
2020-04-19 22:04:56 +00:00
|
|
|
from .interface import IBot, IServer
|
2020-04-01 14:36:53 +00:00
|
|
|
|
2020-04-19 22:04:56 +00:00
|
|
|
class Bot(IBot):
|
2020-04-01 14:36:53 +00:00
|
|
|
def __init__(self):
|
|
|
|
self.servers: Dict[str, Server] = {}
|
|
|
|
self._server_queue: asyncio.Queue[Server] = asyncio.Queue()
|
|
|
|
|
|
|
|
def create_server(self, name: str):
|
2020-04-19 22:04:56 +00:00
|
|
|
return Server(self, name)
|
2021-06-26 15:08:48 +00:00
|
|
|
|
2020-04-19 22:04:56 +00:00
|
|
|
async def disconnected(self, server: IServer):
|
|
|
|
if (server.name in self.servers and
|
2020-04-26 00:19:16 +00:00
|
|
|
server.params is not None and
|
2020-04-19 22:04:56 +00:00
|
|
|
server.disconnected):
|
2021-06-26 15:08:48 +00:00
|
|
|
|
|
|
|
reconnect = server.params.reconnect
|
|
|
|
|
|
|
|
while True:
|
|
|
|
await asyncio.sleep(reconnect)
|
|
|
|
try:
|
|
|
|
await self.add_server(server.name, server.params)
|
|
|
|
except Exception as e:
|
|
|
|
traceback.print_exc()
|
|
|
|
# let's try again, exponential backoff up to 5 mins
|
|
|
|
reconnect = min(reconnect*2, 300)
|
|
|
|
else:
|
|
|
|
break
|
2020-04-19 22:04:56 +00:00
|
|
|
|
|
|
|
async def disconnect(self, server: IServer):
|
|
|
|
del self.servers[server.name]
|
2021-06-26 15:08:48 +00:00
|
|
|
await server.disconnect()
|
2020-04-01 22:06:41 +00:00
|
|
|
|
2020-04-01 14:36:53 +00:00
|
|
|
async def add_server(self, name: str, params: ConnectionParams) -> Server:
|
|
|
|
server = self.create_server(name)
|
|
|
|
self.servers[name] = server
|
2020-04-19 20:51:33 +00:00
|
|
|
await server.connect(TCPTransport(), params)
|
2020-04-01 14:36:53 +00:00
|
|
|
await self._server_queue.put(server)
|
|
|
|
return server
|
|
|
|
|
|
|
|
async def _run_server(self, server: Server):
|
2020-09-24 19:43:03 +00:00
|
|
|
try:
|
|
|
|
async with anyio.create_task_group() as tg:
|
|
|
|
await tg.spawn(server._read_lines)
|
|
|
|
await tg.spawn(server._send_lines)
|
|
|
|
except ServerDisconnectedException:
|
|
|
|
server.disconnected = True
|
2020-04-03 12:04:02 +00:00
|
|
|
|
2020-04-01 14:36:53 +00:00
|
|
|
await self.disconnected(server)
|
|
|
|
|
|
|
|
async def run(self):
|
|
|
|
async with anyio.create_task_group() as tg:
|
|
|
|
while not tg.cancel_scope.cancel_called:
|
|
|
|
server = await self._server_queue.get()
|
|
|
|
await tg.spawn(self._run_server, server)
|