コード例 #1
0
ファイル: test_discord.py プロジェクト: GOATS2K/chitanda
async def test_discord_listener_message_embed():
    with patch.object(DiscordListener, 'get_channel') as gc:
        gc.return_value.send.return_value = Future()
        gc.return_value.send.return_value.set_result(123)
        listener = DiscordListener(Mock())
        await listener.message(123, 'message', embed=True)
        assert gc.return_value.send.called_with(embed='message')
コード例 #2
0
async def test_on_message():
    bot = Mock(handle_message=AsyncMock(return_value=None))
    message = Mock(author=Mock(id=1, bot=False), channel=Mock(id=2), content="abc")

    listener = DiscordListener(bot)
    await listener.on_message(message)
    bot.handle_message.assert_called()
コード例 #3
0
async def test_is_not_admin(monkeypatch):
    listener = DiscordListener(None)
    monkeypatch.setattr(
        "chitanda.listeners.discord.config",
        {"admins": {str(listener): ["zad"]}},
    )
    assert not await listener.is_admin("azul")
コード例 #4
0
ファイル: test_discord.py プロジェクト: GOATS2K/chitanda
async def test_discord_listener_error():
    with patch.object(DiscordListener, 'get_channel') as gc:
        gc.return_value.send.return_value = Future()
        gc.return_value.send.return_value.set_exception(Exception)
        listener = DiscordListener(Mock())
        with pytest.raises(Exception):
            await listener.message(123, 'message')
        assert not listener.message_lock[123]
コード例 #5
0
async def test_discord_listener_message():
    mock = Mock(return_value=Mock(send=AsyncMock(return_value=123)))
    with patch.object(DiscordListener, "get_channel", mock) as gc:
        listener = DiscordListener(Mock())
        await listener.message(123, "message")
        assert gc.return_value.send.called_with(content="message")
        assert not listener.message_queue[123]
        assert not listener.message_lock[123]
コード例 #6
0
ファイル: test_discord.py プロジェクト: GOATS2K/chitanda
async def test_discord_listener_message():
    with patch.object(DiscordListener, 'get_channel') as gc:
        gc.return_value.send.return_value = Future()
        gc.return_value.send.return_value.set_result(123)
        listener = DiscordListener(Mock())
        await listener.message(123, 'message')
        assert gc.return_value.send.called_with(content='message')
        assert not listener.message_queue[123]
        assert not listener.message_lock[123]
コード例 #7
0
ファイル: test_discord.py プロジェクト: GOATS2K/chitanda
async def test_is_not_admin(monkeypatch):
    listener = DiscordListener(None)
    monkeypatch.setattr(
        'chitanda.listeners.discord.config',
        {'admins': {
            str(listener): ['zad']
        }},
    )
    assert not await listener.is_admin('azul')
コード例 #8
0
ファイル: test_discord.py プロジェクト: GOATS2K/chitanda
async def test_on_message_bot():
    bot = Mock()
    bot.handle_message.return_value = coroutine(lambda **kwargs: None)()
    message = Mock(author=Mock(id=1, bot=True),
                   channel=Mock(id=2),
                   content='abc')

    listener = DiscordListener(bot)
    await listener.on_message(message)
    bot.handle_message.assert_not_called()
コード例 #9
0
async def test_discord_listener_message_private():
    with patch.object(
        DiscordListener, "get_dm_channel_id", return_value=AsyncMock(return_value=789)
    ):
        mock = Mock(return_value=Mock(send=AsyncMock(return_value=123)))
        with patch.object(DiscordListener, "get_channel", mock) as gc:
            listener = DiscordListener(Mock())
            await listener.message(123, "message", private=True)
            assert gc.called_with(789)
            assert gc.return_value.send.called_with(embed="message")
コード例 #10
0
ファイル: test_discord.py プロジェクト: GOATS2K/chitanda
async def test_discord_listener_message_private():
    with patch.object(DiscordListener,
                      'get_dm_channel_id',
                      return_value=Future()) as gdmcid:
        with patch.object(DiscordListener, 'get_channel') as gc:
            gdmcid.return_value.set_result('789')
            gc.return_value.send.return_value = Future()
            gc.return_value.send.return_value.set_result(123)
            listener = DiscordListener(Mock())
            await listener.message(123, 'message', private=True)
            assert gc.called_with(789)
            assert gc.return_value.send.called_with(embed='message')
コード例 #11
0
ファイル: test_help.py プロジェクト: azuline/chitanda
def test_applicable_listeners():
    call = Mock(listeners={DiscordListener})
    assert _applicable_listener(DiscordListener(None), call)
コード例 #12
0
ファイル: bot.py プロジェクト: GOATS2K/chitanda
 def _connect_discord(self):
     self.discord_listener = DiscordListener(self)
     self.discord_listener.run(config['discord_token'])
コード例 #13
0
ファイル: bot.py プロジェクト: GOATS2K/chitanda
class Chitanda:

    commands = {}

    def __init__(self):
        self.irc_listeners = {}
        self.discord_listener = None
        self.message_handlers = []
        self.response_handlers = []
        if config['webserver']['enable']:
            self.web_application = web.Application()

    def start(self):
        load_commands(self)
        if hasattr(self, 'web_application'):
            self.webserver = self._start_webserver()

        self.connect()

    def _start_webserver(self):
        try:
            return asyncio.ensure_future(
                asyncio.get_event_loop().create_server(
                    self.web_application.make_handler(),
                    port=int(config['webserver']['port']),
                ))
        except ValueError:
            logging.critical('Invalid port value for webserver.')
            sys.exit(1)

    def connect(self):
        logger.info('Initiating connection to listeners.')
        if config['irc_servers']:
            logger.info('IRC Servers found, connecting...')
            self._connect_irc()
        if config['discord_token']:
            logger.info('Discord token found, connecting...')
            self._connect_discord()

    def _connect_irc(self):
        for hostname, server in config['irc_servers'].items():
            logger.info(f'Connecting to IRC server: {hostname}.')
            self.irc_listeners[hostname] = IRCListener(self,
                                                       server['nickname'],
                                                       hostname)
            asyncio.ensure_future(self.irc_listeners[hostname].connect(
                hostname,
                server['port'],
                tls=server['tls'],
                tls_verify=server['tls_verify'],
            ))

    def _connect_discord(self):
        self.discord_listener = DiscordListener(self)
        self.discord_listener.run(config['discord_token'])

    async def handle_message(self, message):
        logger.debug(f'New message in {message.target} on {message.listener} '
                     f'from {message.author}: {message.contents}')
        try:
            for handler in self.message_handlers:
                await self.handle_response(handler(message), source=message)

            await self.dispatch_command(message)
        except BotError as e:
            logger.info(f'Error triggered by {message.author}: {e}.')
            await message.listener.message(message.target, f'Error: {e}')

    async def dispatch_command(self, message):
        try:
            response = message.call_command()
            if response:
                await self.handle_response(response, source=message)
        except NoCommandFound:
            pass

    async def handle_response(self, response, source):
        logger.debug(f'Response received of type: {type(response)}.')
        if isinstance(response, AsyncGeneratorType):
            async for resp in response:
                await self._handle_response_message(resp, source)
            return

        response = await response

        if isinstance(response, GeneratorType):
            for resp in response:
                await self._handle_response_message(resp, source)
        elif response:
            await self._handle_response_message(response, source)

    async def _handle_response_message(self, response, source):
        response = Response.wrap(response, source)
        await self.call_response_handlers(response)
        await response.listener.message(
            target=response.target,
            message=response.contents,
            **response.kwargs,
        )

    async def call_response_handlers(self, response):
        for handler in self.response_handlers:
            await handler(response)
コード例 #14
0
ファイル: bot.py プロジェクト: World-Wide-hACKers/chitanda
class Chitanda:

    commands = {}

    def __init__(self):
        self.irc_listeners = {}
        self.discord_listener = None
        self.message_handlers = []
        self.response_handlers = []
        if config['webserver']['enable']:
            self.web_application = web.Application()

    def start(self):
        load_commands(self)
        if self.web_application():
            self.webserver = self._start_webserver()

        self.connect()

    def _start_webserver(self):
        try:
            return asyncio.ensure_future(
                asyncio.get_event_loop().create_server(
                    self.web_application.make_handler(),
                    port=int(config['webserver']['port']),
                )
            )
        except ValueError:
            logging.critical('Invalid port value for webserver.')
            sys.exit(1)

    def connect(self):
        logger.info('Initiating connection to listeners.')
        if config['irc_servers']:
            logger.info('IRC Servers found, connecting...')
            self._connect_irc()
        if config['discord_token']:
            logger.info('Discord token found, connecting...')
            self._connect_discord()

    def _connect_irc(self):
        for hostname, server in config['irc_servers'].items():
            logger.info(f'Connecting to IRC server: {hostname}.')
            self.irc_listeners[hostname] = IRCListener(
                self, server['nickname'], hostname
            )
            asyncio.ensure_future(
                self.irc_listeners[hostname].connect(
                    hostname,
                    server['port'],
                    tls=server['tls'],
                    tls_verify=server['tls_verify'],
                )
            )

    def _connect_discord(self):
        self.discord_listener = DiscordListener(self)
        self.discord_listener.run(config['discord_token'])

    async def handle_message(self, listener, target, author, message, private):
        logger.debug(
            f'New message in {target} on {listener} from {author}: {message}'
        )
        for handler in self.message_handlers:
            response = handler(listener, target, author, message, private)
            await self.handle_response(listener, target, response)

        await self.dispatch_command(listener, target, author, message, private)

    async def dispatch_command(
        self, listener, target, author, message, private
    ):
        try:
            trigger, command, message = self._parse_command(message)
            logger.info(f'Command triggered: {trigger}.')

            response = command.call(
                bot=self,
                listener=listener,
                target=target,
                author=author,
                message=message,
                private=private,
            )

            if response:
                await self.handle_response(listener, target, response)
        except NoCommandFound:
            pass
        except BotError as e:
            logger.info(f'Error triggered by {author}: {e}.')
            await listener.message(target, f'Error: {e}')

    def _parse_command(self, message):
        try:
            if message.startswith(config['trigger_character']):
                split_message = message[1:].split(' ', 1)
                trigger, message = self._resolve_alias(*split_message)
                return trigger, self.commands[trigger], message
        except (IndexError, KeyError):
            pass
        raise NoCommandFound

    def _resolve_alias(self, trigger, message=''):
        try:
            return (f'{config["aliases"][trigger]} {message}').split(' ', 1)
        except KeyError:
            return trigger, message

    async def handle_response(self, listener, target, response):
        logger.debug(f'Response received of type: {type(response)}.')

        if isinstance(response, AsyncGeneratorType):
            async for resp in response:
                await self._handle_response_message(listener, target, resp)
            return

        response = await response

        if isinstance(response, GeneratorType):
            for resp in response:
                await self._handle_response_message(listener, target, resp)
        elif response:
            await self._handle_response_message(listener, target, response)

    async def _handle_response_message(self, listener, target, response):
        pr = self._pack_response(response, target)
        await self.call_response_handlers(listener, target, pr['message'])
        await listener.message(**pr)

    def _pack_response(self, response, target):
        if isinstance(response, dict):
            return response
        return {'target': target, 'message': str(response)}

    async def call_response_handlers(self, listener, target, response):
        for handler in self.response_handlers:
            handler(listener, target, response)