Source code for horetu.interfaces.irc

import os
import logging
import shlex
from io import BytesIO
from traceback import format_exc
from .cli import from_argv, cli as _horetu_cli
from ._bind import web_section
from ._util import stream
from .. import exceptions
from ..program import Program
from ..annotations import Port
try:
    from irc.strings import lower
except ImportError:
    pass

logger = logging.getLogger(__name__)

def _irc(program, server, channel, nick, port, start=True, IRCBot=None):
    '''
    :param bool start: Whether to start the bot. The main reason not to is
        for testing.
    :param type IRCBot: IRCBot to subclass. The default is
        :py:class:`irc.bot.SingleServerIRCBot`. The main reason to change it is
        for testing.
    '''
    from irc.client import ip_numstr_to_quad, ip_quad_to_numstr
    if not IRCBot:
        from irc.bot import SingleServerIRCBot as IRCBot

    if not isinstance(program, Program):
        program = Program(program)
    if not nick:
        nick = program.name
    if not (server and channel and nick):
        raise ValueError('You must set the server, channel, and nick.')

    class HoretuBot(IRCBot):
        def on_nicknameinuse(self, c, e):
            c.nick(c.get_nickname() + "_")

        def on_welcome(self, c, e):
            c.join(channel)

        def on_privmsg(self, c, e):
            _respond(program, e.source.nick, c.notice, c.get_nickname(), e.arguments[0])

        def on_pubmsg(self, c, e):
            line = e.arguments[0]
            nickname = c.get_nickname()
            zero = line.lstrip().split()[0]
            mentioned = zero.startswith(nickname)
            if mentioned:
                _respond(program, e.target, c.privmsg, zero, line)

    bot = HoretuBot([(server, port)], nick, nick)
    if start:
        bot.start()
    else:
        return bot

[docs]def irc(program, server, channel, nick=None, *, port: Port=6667, cli=False, only_mentions=False, debug=False): ''' Render a Python function as an IRC bot. :type program: Program, callable, list, or dict :param program: The program for which to produce the interface :param server: IRC server to connect to :param channel: IRC channel to join :param nick: IRC handle :param int port: IRC server port :param bool cli: If True, render a command-line program that starts an IRC bot with the configured values as defaults. ''' if cli: def wrapper(server=server, channel=channel, nick=nick, *, port: Port=port): _irc(program, server, channel, nick, port) wrapper.__doc__ = ''' Run %s as an IRC bot. :param server: IRC server to run on :param channel: Channel on the IRC server to run on :param nick: Nick to connect with :param int port: Port on the server to connect to ''' % (program.name or 'the program') name = program.name if isinstance(program, Program) else None _horetu_cli(Program(wrapper, name)) else: _irc(program, server, channel, nick, port)
def _respond(program, target, method, nickname, line): def success(x): method(target, x.decode('utf-8')) def error(x): method(target, x.decode('utf-8')) class Exit(Exception): pass def _exit(code=0): raise Exit out = BytesIO() try: _horetu_cli(program, argv=[nickname] + shlex.split(line), exit_=_exit, stdout=out, stderr=out) success(out.getvalue().decode('utf-8')) except Exit: pass except UnicodeDecodeError: error(b'error: Bad bot output encoding')