Пример #1
0
    def __init__(self) -> None:
        log.info(f"Initializing bot as: {subprocess.check_output('id', text=True).rstrip()}")  # pylint: disable=unexpected-keyword-arg
        instance = config.INSTANCE
        self._active = True
        self._outgoing_msg_lock = threading.Lock()  # Used for rate limiting across multiple channels.
        self._db = Database()
        self._url_shortener = bitlyshortener.Shortener(
            tokens=[token.strip() for token in os.environ["BITLY_TOKENS"].strip().split(",")], max_cache_size=config.CACHE_MAXSIZE__BITLY_SHORTENER
        )
        self._publishers = [getattr(getattr(publishers, p), "Publisher")() for p in dir(publishers) if ((not p.startswith("_")) and (p in (instance.get("publish") or {})))]
        self._searchers = {s: getattr(getattr(searchers, s), "Searcher")() for s in dir(searchers) if ((not s.startswith("_")) and (s in (instance.get("publish") or {})))}

        # Setup miniirc
        log.debug("Initializing IRC client.")
        config.runtime.nick_casefold = instance["nick"].casefold()  # Prevents AttributeError if RPL_LOGGEDIN (900) is not sent by server, but is not always an accurate value.
        config.runtime.channel_topics = {}
        self._irc = miniirc.IRC(
            ip=instance["host"],
            port=instance["ssl_port"],
            nick=instance["nick"],
            channels=instance["feeds"],
            ssl=True,
            debug=log.info if instance.get("log", {}).get("irc") else False,
            ns_identity=(instance["nick"], os.environ["IRC_PASSWORD"]),
            connect_modes=instance.get("mode"),
            quit_message="",
            ping_interval=30,
        )
        log.info("Initialized IRC client.")
        self._setup_alerter()
        self._setup_channels()
        self._log_config()
        threading.Thread(target=self._search, name="Searcher").start()
        self._exit()  # Blocks.
Пример #2
0
    def __init__(self) -> None:
        log.info("Initializing bot as: %s",
                 subprocess.check_output("id", text=True).rstrip())  # pylint: disable=unexpected-keyword-arg
        instance = config.INSTANCE
        self._setup_channel_queues(
        )  # Sets up executors and queues required by IRC handler.

        log.debug("Initializing IRC client.")
        self._irc = miniirc.IRC(
            ip=instance["host"],
            port=instance["ssl_port"],
            nick=instance["nick"],
            channels=instance["channels"],
            ssl=True,
            debug=False,
            ns_identity=(instance["nick"], os.environ["IRC_PASSWORD"]),
            connect_modes=instance.get("mode"),
            quit_message="",
        )
        log.info("Initialized IRC client.")

        self._setup_channel_threads()  # Threads require IRC client.
        log.info("Alerts will be sent to %s.",
                 config.INSTANCE["alerts_channel"])

        while True:  # This is intended to prevent a concurrent.futures error.
            time.sleep(1234567890)
Пример #3
0
    def __init__(self) -> None:
        log.info('Initializing bot as: %s',
                 subprocess.check_output('id', text=True).rstrip())
        instance = config.INSTANCE
        self._outgoing_msg_lock = threading.Lock(
        )  # Used for rate limiting across multiple channels.
        self._db = Database()
        self._url_shortener = bitlyshortener.Shortener(
            tokens=[
                token.strip()
                for token in os.environ['BITLY_TOKENS'].strip().split(',')
            ],
            max_cache_size=config.BITLY_SHORTENER_MAX_CACHE_SIZE)

        # Setup miniirc
        log.debug('Initializing IRC client.')
        self._irc = miniirc.IRC(
            ip=instance['host'],
            port=instance['ssl_port'],
            nick=instance['nick'],
            channels=instance['feeds'],
            ssl=True,
            debug=False,
            ns_identity=(instance['nick'], os.environ['IRC_PASSWORD']),
            connect_modes=instance.get('mode'),
            quit_message='',
            ping_interval=30,
        )
        config.runtime.alert = lambda *args: _alert(self._irc, *args)
        log.info('Initialized IRC client.')

        self._setup_channels()
        self._log_config()
Пример #4
0
def _ircs_scheme(url: str, ssl: Optional[bool] = True, **kwargs) \
        -> miniirc.IRC:
    match = _irc_scheme_re.match(url)
    if not match:
        raise URLError('Invalid IRC URL.')
    nick, ip, raw_port, chans = match.groups()

    nick = nick or kwargs.get('nick', '')
    if 'nick' in kwargs:
        del kwargs['nick']
    elif not nick:
        raise URLError('No nickname specified in the URL or kwargs.')

    ip = ip
    port: int = 6697
    if raw_port:
        port = int(raw_port)
    elif 'port' in kwargs:
        port = kwargs.pop('port')

    channels: set = set(kwargs.pop('channels', ()))
    if chans:
        for chan in chans.split(','):
            if not chan:
                continue
            elif chan[0].isalnum():
                chan = '#' + chan
            channels.add(chan)

    return miniirc.IRC(ip, port, nick, channels, ssl=ssl, **kwargs)
Пример #5
0
def main():
    token = authenticate()
    if(token == ""):
        print("Could not authenticate to Twitch. Exiting.")
        quit()

    headers = {"Client-Id": CLIENT_ID, "Authorization": "Bearer " + token}
    # Set up IRC connection
    irc = miniirc.IRC('irc.dtek.se', 6697, 'PhixxBot', ['#dtek'], verify_ssl=False)
    irc.send('PRIVMSG', '#dtek', "I'm alive!")

    while(True):
        try:
            for channel in CHANNELS:
                parameters = {"user_login": channel}
                try:
                    response = requests.request("GET", TWITCH_API_URL, params=parameters, headers=headers)
                    print("Twitch repsonse:", response.status_code)
                    responseJson = response.json()
                except Exception as e:
                    print(e)
                    time.sleep(60)
                    continue

                # Channel has gone live
                if(response.ok and (len(responseJson["data"]) > 0) and not CHANNELS[channel]):
                    CHANNELS[channel] = True
                    print("Channel twitch.tv/" + channel + " is live with " + responseJson["data"][0]["game_name"] + "!")
                    irc.send('PRIVMSG', '#dtek', "Channel twitch.tv/" + channel + " is live with " + responseJson["data"][0]["game_name"] + "!")

                # Channel was live and gone offline
                elif(response.ok and CHANNELS[channel] and len(responseJson["data"]) == 0):
                    print("Channel twitch.tv/" + channel + " has gone offline. See you next time!")
                    CHANNELS[channel] = False

                # Twitch error
                elif(not response.ok):
                    print("Twitch error:", response.text)

                # None of the selected channels are live
                else:
                    print("Channel twitch.tv/" + channel + " is not live. *cricket noise*")
            time.sleep(45)
        except KeyboardInterrupt:
            print("Keyboard interrupt detected. Exiting.")
            irc.send('PRIVMSG', '#dtek', "Bye bye!")
            quit()
Пример #6
0
    def __init__(self, config, *, debug=False):
        self.config = config
        if 'core' not in config:
            err('Invalid or non-existent config file!')
        self._conf_assert('core', 'command_db', 'prefix')
        self.ignores = self.process_ignores('core')
        self._prefs = {}

        # Create the commands database
        if 'tempcmds' in config:
            tempcmds_config = config['tempcmds']
        else:
            tempcmds_config = {}
        self.cmd_db = tempcmds.CommandDatabase(
            config['core']['command_db'],
            config=tempcmds_config,
            prefix=config['core']['prefix'],
            reply_on_invalid=self._conf_bool('core', 'reply_on_invalid'))

        # Get the "enable_static_cmds" flag
        global static_cmds
        self.static_cmds = self._conf_bool('core', 'enable_static_cmds', True)

        if self.static_cmds:
            if static_cmds is None:
                import lurklite.static_cmds as static_cmds

            # Get the custom commands file
            custom_cmds = config['core'].get('custom_cmds')
            if custom_cmds:
                static_cmds.load_cmd_file(custom_cmds)
        elif 'custom_cmds' in config['core']:
            print(
                'WARNING: A custom commands path is specified, but static co'
                'mmands are disabled! The custom commands will not be loaded.')

        # Get the disable yay/ouch flags
        self.disable_yay = self._conf_bool('core', 'disable_yay')
        self.disable_ouch = self._conf_bool('core', 'disable_ouch')

        # Get the IRC servers to connect to
        _servers = {}
        kwargs = None
        for section in config.sections():
            if section == 'irc' or section.startswith('irc.'):
                self._conf_assert(section, 'ip', ('port', int), 'nick',
                                  'channels')

                c = config[section]
                kwargs = {}

                for i in 'ident', 'realname', 'ns_identity', 'connect_modes', \
                  'quit_message':
                    if i in c:
                        kwargs[i] = c[i]

                # Add the SSL option
                ssl = None
                if 'tls' in c:
                    ssl = 'tls'
                elif 'ssl' in c:
                    ssl = 'ssl'

                if ssl:
                    kwargs['ssl'] = self._conf_bool(section, ssl)

                # Create the IRC object
                irc = miniirc.IRC(c['ip'],
                                  int(c['port']),
                                  c['nick'],
                                  c['channels'].split(','),
                                  auto_connect=False,
                                  debug=debug,
                                  **kwargs)
                _servers[section] = irc

                # Add the ignores list
                self._add_extras(section, c, irc)

        # Get the Discord bot account (if any)
        if 'discord' in config:
            try:
                import miniirc_discord
            except ImportError:
                err('miniirc_discord is not installed, and a Discord account'
                    ' has been specified in the config file!')

            if getattr(miniirc_discord, 'ver', ()) < (0, 5, 18):
                print('Support for this version of miniirc_discord will be '
                      'removed in the future.')
                kw = {}
            else:
                kw = {'stateless_mode': True}

            self._conf_assert('discord', 'token')

            c = config['discord']

            # Create the Discord object
            irc = miniirc_discord.Discord(c['token'],
                                          0,
                                          c.get('nick', '???'),
                                          debug=debug,
                                          **kw)
            _servers['Discord'] = irc

            # Add the ignores list
            self._add_extras('discord', c, irc)
            self._prefs[irc]['next_update'] = 0

        # Mass connect
        for name in _servers:
            irc = _servers[name]
            irc.debug('Connecting to ' + repr(name) + '...')
            irc.Handler('PRIVMSG', colon=False)(self.handle_privmsg)
            try:
                irc.connect()
            except Exception as exc:
                print(f'Failed to connect to {name!r} - '
                      f'{exc.__class__.__name__}: {exc}')
        irc.debug('Finished connecting to servers!')
Пример #7
0
#!/usr/bin/python3
#
# Minetest player tracker
# This is the deprectated version 1 code, please visit
# https://gitlab.com/luk3yx/minetest-trackr or
# https://github.com/luk3yx/minetest-trackr for the latest version.
#
# © 2018 by luk3yx
#

import miniirc, os, time

# Create the IRC object
_irc = miniirc.IRC('xeroxirc.net',
                   6697,
                   'trackr', ['#Edgy1'],
                   realname='Minetest player tracker',
                   ns_identity='username password',
                   auto_connect=False)

servers = {}
admins = {'invalid/your-hostmask-here'}
cooldown = 15

# Odd/even
plural = lambda n: '' if n == 1 else 's'

# Handle PRIVMSGs
last_list = 0


@miniirc.Handler('PRIVMSG')
Пример #8
0
    def from_parsed_config(cls, config: Mapping[str, Mapping[str, str]], *,
            require: Optional[Union[tuple[str, ...], list[str]]] = None) \
            -> Bot:
        """
        Similar to from_config(), however expects a parsed config similar to
        this dict (the config provided can be a collections.abc.Mapping if
        required):

        {
            'core': {
                'prefix': '$',
            },
            'irc.network1': {
                'url': 'irc://irc.example.com/#channel1,#channel2',
                'nick': 'Test',
            },
            'irc.network2': {
                'ip': 'irc.example.com',
                'port': '6697',
                'nick': 'Test2',
                'channels': '#channel1, #channel2',
            },
        }
        """

        prefix: Optional[str] = None
        if 'core' in config:
            prefix = config['core'].get('prefix')

        self = cls(prefix=prefix)
        self.config = config
        for section in config:
            if not section.startswith('irc.'):
                continue

            data = config[section]

            kwargs: dict[str, Any] = {'auto_connect': False}
            # Get generic keyword arguments
            for i in 'ident', 'realname', 'ns_identity', 'connect_modes', \
                    'quit_message':
                if i in data:
                    kwargs[i] = data[i]

            # Add URL-based IRCs
            url = data.get('url') or data.get('uri')
            name = section[4:]
            if url:
                if 'nick' in data:
                    kwargs['nick'] = data['nick']
                self.add_irc_from_url(url, name, **kwargs)
                continue

            # Add "standard" IRC objects
            for i in 'ip', 'port', 'nick', 'channels':
                if i not in data:
                    raise ConfigError(('Required configuration entry {!r}'
                                       ' missing!').format(i))

            try:
                port = int(data['port'])
            except ValueError as e:
                raise ConfigError("Configuration entry 'port' contains an "
                                  'invalid number!') from e

            self.add_irc(
                miniirc.IRC(data['ip'], port, data['nick'],
                            map(str.strip, data['channels'].split(','))), name)

        # Sanity check
        if not self.ircs:
            raise ConfigError('No IRC networks specified!')

        # Add irc.require() features.
        if require:
            for feature in require:
                self.require(feature)

        # Connect to everything
        self.connect()
        return self
Пример #9
0
import miniirc
import miniirc_discord
import re
irc = miniirc.IRC('chat.freenode.net',
                  6667,
                  'SobieskiCodesBot',
                  channels='#sobieskicodes',
                  ssl=None,
                  ident=None,
                  realname=None,
                  persist=True,
                  debug=False,
                  ns_identity='user pass',
                  auto_connect=True,
                  ircv3_caps=set(),
                  quit_message='I grew sick and died.',
                  ping_interval=60,
                  verify_ssl=True)
discord = miniirc_discord.Discord(ip='discordtoken',
                                  nick=None,
                                  port=0,
                                  ident=None,
                                  realname=None,
                                  channels='#general')


#currently unused - will revamp for chan, user, and emoji's on discord handler
def discord_object_check(arg):
    #discord_object_check(args[1])
    reg = re.search('<(\@\!|:(.*?):|\#)([^<>]+)>', arg)
    if reg:
Пример #10
0
def test_connection(monkeypatch):
    irc = err = None

    # Prevent miniirc catching fakesocket errors
    def catch_errors(func):
        @functools.wraps(func)
        def wrapper(self, *args, **kwargs):
            nonlocal err
            try:
                return func(self, *args, **kwargs)
            except Exception as e:
                err = err or e
                if MINIIRC_V2:
                    self._sock.close()
                else:
                    self.sock.close()

        return wrapper

    fixed_responses = {
        'CAP LS 302':
        'CAP * LS :abc sasl account-tag',
        'CAP REQ :account-tag sasl':
        'CAP miniirc-test ACK :sasl account-tag',
        'CAP REQ :sasl account-tag':
        'CAP miniirc-test ACK :account-tag sasl',
        'AUTHENTICATE PLAIN':
        'AUTHENTICATE +',
        'AUTHENTICATE dGVzdAB0ZXN0AGh1bnRlcjI=':
        '903',
        'CAP END': ('001 parameter test :with colon\n'
                    '005 * CAP=END :isupport description\n'),
        'USER miniirc-test 0 * :miniirc-test':
        ':a PRIVMSG miniirc-test :\x01VERSION\x01',
        'NICK miniirc-test':
        '432',
        'NICK miniirc-test_':
        '',
        'NOTICE a :\x01VERSION ' + miniirc.version + '\x01':
        '005 miniirc-test CTCP=VERSION :are supported by this server',
        'QUIT :I grew sick and died.':
        '',
    }

    class fakesocket(socket.socket):
        @catch_errors
        def __init__(self, __family, __type):
            assert __family in (socket.AF_INET, socket.AF_INET6)
            assert __type == socket.SOCK_STREAM

        @catch_errors
        def connect(self, __addr):
            assert __addr[1] == 6667
            self._recvq = queue.Queue()

        @catch_errors
        def send(self, data):
            raise ValueError('socket.send() used in place of socket.sendall()')

        @catch_errors
        def sendall(self, data):
            msg = data.decode('utf-8')
            assert msg.endswith('\r\n')
            msg = msg[:-2]
            assert msg in fixed_responses
            if self._recvq is None:
                return
            for line in fixed_responses[msg].split('\n'):
                self._recvq.put(
                    line.encode('utf-8') +
                    random.choice((b'\r', b'\n', b'\r\n', b'\n\r')))

        @catch_errors
        def recv(self, chunk_size):
            assert chunk_size == 8192
            if err is not None or self._recvq is None:
                return b''
            else:
                return self._recvq.get()

        def close(self):
            nonlocal err
            err = err or BrokenPipeError('Socket closed')
            event.set()
            if self._recvq:
                self._recvq.put(b'')
                self._recvq = None

        def settimeout(self, t):
            assert t == 60

    monkeypatch.setattr(socket, 'socket', fakesocket)

    try:
        event = threading.Event()
        irc = miniirc.IRC('example.com',
                          6667,
                          'miniirc-test',
                          auto_connect=False,
                          ns_identity=('test', 'hunter2'),
                          persist=False,
                          debug=True)
        assert irc.connected is None

        @irc.Handler('001', colon=False)
        @catch_errors
        def _handle_001(irc, hostmask, args):
            for i in range(100):
                if 'CAP' in irc.isupport and 'CTCP' in irc.isupport:
                    break
                time.sleep(0.001)
            assert args == ['parameter', 'test', 'with colon']
            assert irc.isupport == {'CTCP': 'VERSION', 'CAP': 'END'}
            event.set()

        irc.connect()
        assert event.wait(3) or err is not None
        if err is not None:
            raise err
        assert irc.connected
        if MINIIRC_V2:
            assert irc.nick == 'miniirc-test'
            assert irc.current_nick == 'miniirc-test_'
        else:
            assert irc.nick == irc.current_nick == 'miniirc-test_'
    finally:
        irc.disconnect()
Пример #11
0
CHANNELS = ["#italy"]

MAX_LENGHT = 50
USERNAME_PLACEHOLDER = "#username#"
CHANNEL_PLACEHOLDER = "#channel#"
AFTER_PLACEHOLDER = "#after#"
BOT_PLACEHOLDER = "#bot#"
JSON_FILE = 'boe.json'

irc = miniirc.IRC(IP,
                  PORT,
                  NICK,
                  CHANNELS,
                  ident=NICK,
                  realname=NICK,
                  ns_identity="{} {}".format(NICK, PASSWORD),
                  auto_connect=True,
                  ssl=True,
                  verify_ssl=False,
                  debug=False,
                  persist=True,
                  ping_interval=20,
                  quit_message="Bye")

with open(JSON_FILE) as json_file:
    command_db = json.load(json_file)


@irc.Handler('NOTICE', colon=False)
def notice(irc, hostmask, args):
    username = hostmask[0]
    if 'NickServ' in username and "identify via" in args[1]: