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.
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)
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()
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)
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()
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!')
#!/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')
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
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:
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()
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]: