def numeric(self, source, numeric, *args): """Numeric Event. Triggered by the irc Protocol Component when we have received an irc Numberic Event from server we are connected to """ # if nick is in use add an _ to the end of our name if numeric == ERR_NICKNAMEINUSE: self.fire(NICK("{0:s}_".format(args[0]))) # else wait for end of motd to start sending commands elif numeric in (RPL_ENDOFMOTD, ERR_NOMOTD): self.fire(PRIVMSG("NICKSERV", "IDENTIFY " + self.password))
def _okay_privmsg(self, event, source, target, message): match = self.WC.search(message) if not match: return server = self.parent.parent.servers[event.channels[0]] dest = source[0] if target == server.nick else target event.stop() user = match.group(1) chall = match.group(2) site = match.group(3) or 'wc' if site.lower() in ('wc', 'wechall') and match.group('bot') != 'tehbot': part = solvers(chall, user=user) self.fire(PRIVMSG(dest, part), server.channel)
def privmsg(self, source, target, message): """Message Event. Triggered by the irc Protocol Component for each message we receieve from the server """ if message[:1] == self.command_char: self.parse(message, source, target) else: urls = findall( "http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", message) if urls: title = self.linkresolver.get_title(urls[0]) self.fire(PRIVMSG(target, title))
def run(self): while self.running: for sub in self.watch: mutex.acquire() if len(self.watch[sub]) > 0: # Reddit API policy says to use a unique user-agent headers = {'User-Agent': 'Fluffybot IRC Bot by /u/astonex'} response = get(self.base_url + sub + "/new.json", timeout=3, headers=headers) json = loads(response.text) data = json['data'] for child in data['children']: post = child['data'] if post['name'] in self.seen[sub]: continue for keyword in self.watch[sub]: if (keyword.lower() in post.get('title', '').lower() or keyword.lower() in post.get( 'selftext', '').lower()): self.seen[sub].append(post['name']) for sender in self.sender[keyword]: self.ircbot.fire( PRIVMSG( sender, "New '" + str(keyword) + "' thread found on /r/" + str(sub) + " " + self.base_url + str(post['permalink'][3:]))) mutex.release() sleep(60)
def parse(self, message, source, target): keywords = message.split(' ') key = keywords[0][1:] # Check it is a valid command if self.commands[key]: command = self.commands[key] else: return response = 0 # Can anyone use it? if command[1]: response = command[0].execute(keywords, target, source, self) # Else check source is in whitelist elif source[2] in self.commands['allow'][0].whitelist: response = command[0].execute(keywords, target, source, self) if response == -1: self.fire(PRIVMSG(target, command[0].usage()))
def privmsg(self, event, source, target, raw): server = self.parent.servers[event.channels[0]] message = strip(raw, True) if source[0] not in ('spaceone', ) and target == server.nick: self.fire( PRIVMSG('spaceone', '%s wrote: %r' % ( source[0], message, )), server.channel) destination = source[0] if target == server.nick else target dest = destination if source[0] in self.ignore: return if source[0] in self._get_master( server, True) and source[0] not in self._get_master(server): self.fire(PRIVMSG('NickServ', 'STATUS %s' % (source[0], )), server.channel) messages = message for trigger in self.get_trigger(source, server): if messages.startswith(trigger): messages = messages[len(trigger):] break else: return stdout = None while messages: message, separator, messages = self.pop_next(messages) if not message: break from_stdin, to_stdout = None, None if separator in ('<', '<<'): from_stdin, separator, messages = self.pop_next(messages) elif separator in ('>', '>>'): to_stdout, separator, messages = self.pop_next(messages) command, args = (message.split(None, 1) + [''])[:2] # command = command.encode('utf-8') try: if from_stdin and from_stdin not in ('/dev/stdin'): stdout = from_stdin if self.commands.get(command) and self.commands[ command].get_default('threaded'): def execute(*args, **kwargs): try: return self.execute(*args, **kwargs) except: return sys.exc_info() cmd = task(execute, server, command, args, source, target, dest, stdin=stdout) else: cmd = Event.create('execute', server, command, args, source, target, dest, stdin=stdout) value = (yield self.call(cmd)).value if len(value) == 3: six.reraise(value[0], value[1], value[2]) dest, stdout = value if to_stdout and to_stdout not in ('/dev/stdout', ): if not to_stdout.startswith('/') and to_stdout not in ( 'spaceone', ) and source[0] not in ('spaceone', ): raise ArgumentInfos( 'Cannot redirect to other users/channels! login or redirect to /foo.' ) elif not to_stdout.startswith('/') and source[0] in ( 'spaceone', ): if dest == destination: dest = to_stdout elif to_stdout in ('spaceone', 'livinskull', 'tehron', 'dloser', '#wechall', '#wechalladmin', '#spaceone'): if dest == destination: dest = to_stdout else: stdout = [] if separator == '||': break elif separator in ('&&', ';', '&'): self.respond(dest, stdout, server) dest = destination stdout = [] except ArgumentInfos as exc: stdout = str(exc).splitlines() if not separator or separator == '&&': break except ArgumentParserError as exc: stdout = ("Error: %s" % (exc)).splitlines() if not separator or separator == '&&': break except BaseException as exc: print(traceback.format_exc()) stdout = ("Error: %s" % (exc)).splitlines() for line in self.wrap( traceback.format_exception(*sys.exc_info())): self.fire( PRIVMSG('spaceone', repr(line).lstrip('u').strip('\'"')), server.channel) break self.respond(dest, stdout, server)
def nickserv(self, bot): for server in bot.servers.values(): masters = self.master.get(server.channel, self.master['*']) for master in masters: self.fire(PRIVMSG('NickServ', 'STATUS %s' % (master, )), server)
def __call__(self, args): self._commander.fire( PRIVMSG('NickServ', 'STATUS %s' % (args.source[0], )), args.ircserver.channel)
def __call__(self, args): self._commander.fire(PRIVMSG(args.channel, ' '.join(args.message)), args.ircserver.channel)
def execute(self, keywords, target, source, ircbot): if len(keywords) < 2: return -1 if keywords[1] == "add": # Check they gave at least a one word quote if len(keywords) < 3: return -1 # Combine list into string quote = ' '.join(keywords[2:]) # Prefix date and time quote_time = time.strftime("%H:%M:%S") quote_date = time.strftime("%d/%m/%Y") quote = "" + quote_date + " " + quote_time + " || " + quote self.quotes.append(quote) with open('saved_quotes', 'w') as f: dump(self.quotes, f) # do we need to save entire structure each time? ircbot.fire( PRIVMSG(target, "Added quote #" + str(len(self.quotes) - 1))) elif keywords[1] == "del": if len(keywords) != 3: return -1 quote = int(keywords[2]) if quote < 0 or quote >= len(self.quotes): ircbot.fire(PRIVMSG(target, "Invalid quote id")) return del self.quotes[quote] ircbot.fire(PRIVMSG(target, "Deleted quote")) elif keywords[1] == "random": if len(self.quotes) == 0: ircbot.fire(PRIVMSG(target, "No quotes in system")) return elif len(self.quotes ) == 1: # randrange wouldnt work with randrange(0) quote = self.quotes[0] quote = "#0 " + quote ircbot.fire(PRIVMSG(target, quote)) else: num = random.randrange(len(self.quotes)) quote = "#" + str(num) + " " + self.quotes[num] ircbot.fire(PRIVMSG(target, quote)) elif keywords[1] == "get": if len(keywords) != 3: return -1 quote_id = int(keywords[2]) if quote_id < 0 or quote_id >= len(self.quotes): ircbot.fire(PRIVMSG(target, "Invalid quote id")) else: quote = self.quotes[quote_id] quote = "#" + str(quote_id) + " " + quote ircbot.fire(PRIVMSG(target, quote)) else: return -1
def sendaction(self, target, action): print('{}Sending {} {}{}'.format(Fore.RED, target, action, Fore.RESET)) self.fire(PRIVMSG(target, '\x01ACTION {}\x01'.format(action)))
def send_irc_message(self, event): """Transmit a message to a user""" self.log('Transmitting IRC message', lvl=debug) self.fireEvent(PRIVMSG(event.username, "[%s] %s : %s" % (event.msg_type, event.subject, event.body)))
def execute(self, keywords, target, source, ircbot): ircbot.fire( PRIVMSG( target, "Source available here: https://github.com/Astonex/IRC-Bot/"))
def execute(self, keywords, target, source, ircbot): ircbot.fire(PRIVMSG(target, ircbot.list_commands()))
def respond(self, dest, stdout, server): for line in self.wrap(stdout or []): self.fire(PRIVMSG(dest, line), server.channel)
def sendmessage(self, target, message): print('{}Sending {}: {}{}'.format(Fore.RED, target, message, Fore.RESET)) self.fire(PRIVMSG(target, message))
assert host is None @pytest.mark.parametrize("event,data", [ (PASS("secret"), b"PASS secret\r\n"), (USER("foo", "localhost", "localhost", "Test Client"), b"USER foo localhost localhost :Test Client\r\n"), (NICK("test"), b"NICK test\r\n"), (PONG("localhost"), b"PONG :localhost\r\n"), (QUIT(), b"QUIT Leaving\r\n"), (QUIT("Test"), b"QUIT Test\r\n"), (QUIT("Test Message"), b"QUIT :Test Message\r\n"), (JOIN("#test"), b"JOIN #test\r\n"), (JOIN("#test", "secret"), b"JOIN #test secret\r\n"), (PART("#test"), b"PART #test\r\n"), (PRIVMSG("test", "Hello"), b"PRIVMSG test Hello\r\n"), (PRIVMSG("test", "Hello World"), b"PRIVMSG test :Hello World\r\n"), (NOTICE("test", "Hello"), b"NOTICE test Hello\r\n"), (NOTICE("test", "Hello World"), b"NOTICE test :Hello World\r\n"), (KICK("#test", "test"), b"KICK #test test :\r\n"), (KICK("#test", "test", "Bye"), b"KICK #test test Bye\r\n"), (KICK("#test", "test", "Good Bye!"), b"KICK #test test :Good Bye!\r\n"), (TOPIC("#test", "Hello World!"), b"TOPIC #test :Hello World!\r\n"), (MODE("+i"), b"MODE +i\r\n"), (MODE("#test", "+o", "test"), b"MODE #test +o test\r\n"), (INVITE("test", "#test"), b"INVITE test #test\r\n"), (NAMES(), b"NAMES\r\n"), (NAMES("#test"), b"NAMES #test\r\n"), (AWAY("I am away."), b"AWAY :I am away.\r\n"), (WHOIS("somenick"), b"WHOIS :somenick\r\n"), ])
def run(self): while self.running: try: # Dont want to kill thread if some exception is raised with mutex: keywords_exist = len(self.watch) > 0 if keywords_exist: response = get(self.base_url + "archive", timeout=3) html = response.text pastes = re.findall( '<td><img src="/i/t.gif" class="i_p0" alt="" border="0" /><a href="/(\w+)">.+</a></td>', html) for paste in pastes: with mutex: if paste in self.seen: continue paste_content = get(self.base_url + paste) doc = fromstring(paste_content.text) # wtf are all these deeply nested tags pastebin content = doc.cssselect( "div#super_frame div#monster_frame div#content_frame div#content_left form#myform.paste_form div.textarea_border textarea#paste_code.paste_code" ) title = doc.cssselect( "div#super_frame div#monster_frame div#content_frame div#content_left div.paste_box_frame div.paste_box_info div.paste_box_line1 h1" ) # Check content for a particularly spammy occurence on pastebin if len( re.findall( 'Free \S+ Premium Account \S+ \S+ Password \w+ \w+ \w+', content[0].text, re.IGNORECASE)) > 0: continue # Copy lists so I don't have to hold the lock for the entire # for loop below which could be a 'long' time with mutex: watch = self.watch sender = self.sender # Search for keywords in paste content for keyword in watch: if (len( re.findall(keyword, title[0].text, re.IGNORECASE)) > 0 or len( re.findall(keyword, content[0].text, re.IGNORECASE)) > 0): for sender in sender[keyword]: self.ircbot.fire( PRIVMSG( sender, "New '" + str(keyword) + "' paste found: https://pastebin.com/" + str(paste))) with mutex: self.seen.append(paste) # If reached max seen then clear oldest 25 with mutex: if len(self.seen) > self.max_seen: del self.seen[0:25] except: pass sleep(30)