def getFromRelay(bot): #global logger if not "#crimbogrotto" in bot.channels: return sid = bot.getForumSID() if not 'lastMChatID' in bot.memory.keys(): text = web.post( 'http://www.crimbogrotto.com/mchat.php','mode=read&room_id=0&sid={0}'.format(sid) ) messageList = re.findall( mchatPattern, text ) bot.memory['lastMChatID'] = int( messageList[-1].group(1) ) text = web.post( 'http://www.crimbogrotto.com/mchat.php','mode=read&room_id=0&message_last_id={0!s}&sid={1}'.format( bot.memory['lastMChatID'], sid ) ) messageIter = re.finditer( mchatPattern, text ) parser = HTMLParser.HTMLParser() for messageMatch in messageIter: if messageMatch.group(2) != 'CGIRC': sender = messageMatch.group(2) message = messageMatch.group(3) message = re.sub( smiliesPattern, r'\1', message ) #Replace smilies from forum message = re.sub( linkPattern, r'\1', message ) #Replace links with just url message = re.sub( tagPattern, '', message ) #Remove all other tags openBracket = '{' closeBracket = '}' if sender == 'CGBot': nameMatch = re.match( CGBotMessagePattern, message ) sender = nameMatch.group(1) message = nameMatch.group(2) openBracket = '[' closeBracket = ']' if message == '': return bot.msg( '#crimbogrotto', u'{0}{1}{2}: {3}'.format( openBracket, sender, closeBracket, parser.unescape(message) ), 10, False ) bot.memory['lastMChatID'] = int( messageMatch.group(1) ) return
def getFromRelay(bot): #global logger if not "#crimbogrotto" in bot.channels: return sid = bot.getForumSID() if not 'lastMChatID' in bot.memory.keys(): text = web.post('http://www.crimbogrotto.com/mchat.php', 'mode=read&room_id=0&sid={0}'.format(sid)) lastIDSoup = BeautifulSoup(text) bot.memory['lastMChatID'] = int(lastIDSoup.find_all('div', class_='mChatHover')[-1]['id'][4:]) params = 'mode=read&room_id=0&message_last_id={0!s}&sid={1}'.format(bot.memory['lastMChatID'], sid) text = web.post('http://www.crimbogrotto.com/mchat.php', params) mchatSoup = BeautifulSoup(text) # Each message is contained in div with class mChatHover for messageDiv in mchatSoup.find_all('div', class_='mChatHover'): sender = messageDiv.find('a', href=memberlistPattern).string bot.memory['lastMChatID'] = int(messageDiv['id'][4:]) if sender == 'CGIRC': continue message = messageDiv.find('div', class_='mChatMessage') # Replace smilies with text of smilie (images are disallowed, so all images should be smilies) imgs = message.find_all('img') for img in imgs: new_tag = mchatSoup.new_tag('div') new_tag.string = img['alt'] img.replace_with(new_tag) links = message.find_all('a') for link in links: new_tag = mchatSoup.new_tag('div') if link.string != link['href']: new_tag.string = '{} ({})'.format(link['href'], link.string) else: new_tag.string = link.string link.replace_with(new_tag) # Collapse message to only plain text and adjust for correct bracketing based on message source messageText = message.get_text() openBracket = '[' closeBracket = ']' if sender == 'CGBot': KoLMessageMatch = re.match(KoLMessagePattern, messageText) sender = KoLMessageMatch.group(1) messageText = KoLMessageMatch.group(2) openBracket = '{' closeBracket = '}' if message == '': return parser = HTMLParser.HTMLParser() toSend = u'{0}{1}{2}: {3}'.format(openBracket, sender, closeBracket, parser.unescape(messageText)) bot.msg('#crimbogrotto', toSend, 10, False) bot.memory['lastMChatID'] = int(KoLMessageMatch.group(1)) return
def relay(bot, trigger): #global logger sid = bot.getForumSID() message = re.sub(actionPattern, '', trigger.group(0)) #Remove ACTION from /me messages message = re.sub(colorPattern, '', message) # Remove color codes message = re.sub(nonAsciiPattern, '', message) #remove non-ascii characters 'cause forum chat and kol chat are dumb message = re.sub(hiddenPattern, '', message) #messages starting with "irc:" are hidden from kol chat if message == '': return toPost = web.quote(u'[b]{0}:[/b] {1}'.format(trigger.nick, message)) web.post('http://www.crimbogrotto.com/mchat.php', 'room_id=0&mode=add&sid={0}&message={1}'.format(sid, toPost)) return
def issue(bot, trigger): """Create a GitHub issue, also known as a bug report. Syntax: .makeissue Title of the bug report""" # check input if not trigger.group(2): return bot.say('Please title the issue') # Is the Oauth token and repo available? gitAPI = checkConfig(bot) if not gitAPI: return bot.say('Git module not configured, make sure github.oauth_token and github.repo are defined') # parse input now = ' '.join(str(datetime.utcnow()).split(' ')).split('.')[0] + ' UTC' body = 'Submitted by: %s\nFrom channel: %s\nAt %s' % (trigger.nick, trigger.sender, now) data = {"title": trigger.group(2), "body": body} # submit try: raw = web.post('https://api.github.com/repos/' + gitAPI[1] + '/issues?access_token=' + gitAPI[0], json.dumps(data)) except HTTPError: bot.say('The GitHub API returned an error.') return NOLIMIT data = json.loads(raw) bot.say('Issue #%s posted. %s' % (data['number'], data['html_url'])) bot.debug(__file__, 'Issue #%s created in %s' % (data['number'], trigger.sender), 'warning')
def who(bot, trigger): sid = bot.getForumSID() whoText = web.post( 'http://www.crimbogrotto.com/mchat.php','mode=read&room_id=6&sid={0}'.format(sid) ) lastWhoID = 0 messageList = re.findall( whoPattern, whoText ) messageMatch = messageList[-1] bot.reply( messageMatch.group(3) )
def issue(bot, trigger): """Create a GitHub issue, also known as a bug report. Syntax: .makeissue Title of the bug report""" # check input if not trigger.group(2): return bot.say('Please title the issue') # Is the Oauth token and repo available? gitAPI = checkConfig(bot) if gitAPI == False: return bot.say( 'Git module not configured, make sure github.oauth_token and github.repo are defined' ) # parse input now = ' '.join(str(datetime.utcnow()).split(' ')).split('.')[0] + ' UTC' body = 'Submitted by: %s\nFrom channel: %s\nAt %s' % (trigger.nick, trigger.sender, now) data = {"title": trigger.group(2).encode('utf-8'), "body": body} # submit try: raw = web.post( 'https://api.github.com/repos/' + gitAPI[1] + '/issues?access_token=' + gitAPI[0], json.dumps(data)) except HTTPError: return bot.say('The GitHub API returned an error.') data = json.loads(raw) bot.say('Issue #%s posted. %s' % (data['number'], data['html_url'])) bot.debug(__file__, 'Issue #%s created in %s' % (data['number'], trigger.sender), 'warning')
def think(self, thought): self.svars['stimulus'] = thought postdata = web.urlencode(self.svars) postdata += '&icognocheck=' + md5(postdata[9:29]).hexdigest() response = web.post('http://www.cleverbot.com/webservicemin', postdata).read().split('\r') self.svars['sessionid'] = response[1] self.svars['logurl'] = response[2] self.svars['vText8'] = response[3] self.svars['vText7'] = response[4] self.svars['vText6'] = response[5] self.svars['vText5'] = response[6] self.svars['vText4'] = response[7] self.svars['vText3'] = response[8] self.svars['vText2'] = response[9] self.svars['prevref'] = response[10] self.svars['emotionalhistory'] = response[12] self.svars['ttsLocMP3'] = response[13] self.svars['ttsLocTXT'] = response[14] self.svars['ttsLocTXT3'] = response[15] self.svars['ttsText'] = response[16] self.svars['lineRef'] = response[17] self.svars['lineURL'] = response[18] self.svars['linePOST'] = response[19] self.svars['lineChoices'] = response[20] self.svars['lineChoicesAbbrev'] = response[21] self.svars['typingData'] = response[22] self.svars['divert'] = response[23] return self.svars['ttsText']
def shindan(bot, trigger): """ .shindan <id> [name] - Do the shindanmaker thing! Will automatically translate japanese shindans to english. (Waifu id: 215100 | Teh_Colt's Drama Gen id: 490953) """ if not trigger.group(3) or not trigger.group(3).isdigit() or int(trigger.group(3).strip()) < 2000: bot.say('You must specify a shindanmaker ID (Waifu id: 215100 | Teh_Colt\'s Drama Gen id: 490953)') return name = trigger.nick if (trigger.group(4)): name = trigger.group(4) data = web.urlencode({'u': name, 'from': ''}).encode('ascii') url = follow_redirects('http://en.shindanmaker.com/'+trigger.group(3).strip()) try: soup = get_soup(web.post(url, data)) shindan = soup.find(attrs={'class':re.compile("result")}) if 'en' in url: bot.say(shindan.text.strip()) else: msg, in_lang = translate.translate(shindan.text.strip()) if in_lang == 'ja': in_lang = 'Japanese' bot.say('%s (Translated from %s)' % (msg, in_lang)) except Exception as e: bot.say('418 I\'m a teapot')
def shindan(bot, trigger): """ .shindan <id> [name] - Do the shindanmaker thing! Will automatically translate japanese shindans to english. (Waifu id: 215100 | Teh_Colt's Drama Gen id: 490953) """ if not trigger.group(3) or not trigger.group(3).isdigit() or int( trigger.group(3).strip()) < 2000: return bot.say( u'You must specify a shindanmaker ID (Waifu id: 215100 | T\u0081eh_Colt\'s Drama Gen id: 490953)' ) name = trigger.nick if (trigger.group(4)): name = trigger.group(4) data = web.urlencode({'u': name, 'from': ''}).encode('ascii') url = follow_redirects('http://en.shindanmaker.com/' + trigger.group(3).strip()) try: soup = get_soup(web.post(url, data)) shindan = soup.find(class_='result') if shindan is None: bot.say('The shindanmaker ID %s does not exist!' % (trigger.group(3).strip(), )) else: bot.say(shindan.text.strip()) except Exception as e: bot.say('418 I\'m a teapot')
def shorten_url(url): try: res, headers = web.post('http://git.io', 'url=' + web.quote(url), return_headers=True) return headers['location'] except: return url
def add_traceback(bot, trigger): """Add a traceback to a GitHub issue. This pulls the traceback from the exceptions log file. To use, put .addtrace followed by the issue number to add the comment to, then the signature of the error (the message shown to the channel when the error occured). This command will only work for errors from unhandled exceptions.""" # Make sure the API is set up gitAPI = checkConfig(bot) if not gitAPI: return bot.say('Git module not configured, make sure github.oauth_token and github.repo are defined') # Make sure the input is valid args = trigger.group(2).split(None, 1) if len(args) != 2: bot.say('Please give both the issue number and the error message.') return number, trace = args # Make sure the given issue number exists issue_data = web.get('https://api.github.com/repos/%s/issues/%s' % (gitAPI[1], number)) issue_data = json.loads(issue_data) if 'message' in issue_data and issue_data['message'] == 'Not Found': return bot.say("That issue doesn't exist.") # Find the relevant lines from the log file post = '' logfile = os.path.join(bot.config.logdir, 'exceptions.log') with open(logfile) as log: in_trace = False for data in log: if data == 'Signature: ' + trace + '\n': post = data in_trace = True elif data == '----------------------------------------\n': in_trace = False elif in_trace: post += data # Give an error if we didn't find the traceback if not post: return bot.say("I don't remember getting that error. Please post it " "yourself at https://github.com/%s/issues/%s" % (gitAPI[1], number)) # Make the comment try: raw = web.post('https://api.github.com/repos/' + gitAPI[1] + '/issues/' + number + '/comments?access_token=' + gitAPI[0], json.dumps({'body': '``\n' + post + '``'})) except OSError: # HTTPError: bot.say('The GitHub API returned an error.') return NOLIMIT data = json.loads(raw) bot.say('Added traceback to issue #%s. %s' % (number, data['html_url'])) bot.debug(__file__, 'Traceback added to #%s in %s.' % (number, trigger.sender), 'warning')
def paste(text, title="", format='text'): global pastebin_key response = web.post("http://pastebin.com/api/api_post.php", { 'api_option': 'paste', 'api_dev_key': pastebin_key, 'api_paste_code': text.encode('utf-8'), 'api_paste_private': '0', 'api_paste_name': title.encode('utf-8'), 'api_paste_expire_date': '1D', 'api_paste_format': format }) if len(response) > 200: raise IOError("Pastebin is not responding correctly") return response
def latex(bot, trigger): #Request Body # formula=<FORMULA>&fsize=17px&fcolor=000000&mode=0&out=1&remhost=quicklatex.com&preamble=\usepackage{amsmath}\usepackage{amsfonts}\usepackage{amssymb} data = web.urlencode({ 'formula': trigger.group(2), 'fsize': '25px', 'fcolor': '000000', 'mode': '0', 'out': '1', 'remhost': 'quicklatex.com', 'preamble': '\\usepackage{amsmath}\\usepackage{amsfonts}\\usepackage{amssymb}' }).encode('ascii') url = web.post('http://quicklatex.com/latex3.f', data).split()[1] bot.reply(web.get('http://is.gd/create.php?format=simple&url=' + url))
def shindan(bot, trigger): """ .shindan <id> [name] - Do the shindanmaker thing! Will automatically translate japanese shindans to english. (Waifu id: 215100 | Teh_Colt's Drama Gen id: 490953) """ if not trigger.group(3) or not trigger.group(3).isdigit() or int(trigger.group(3).strip()) < 2000: return bot.say(u'You must specify a shindanmaker ID (Waifu id: 215100 | T\u0081eh_Colt\'s Drama Gen id: 490953)') name = trigger.nick if (trigger.group(4)): name = trigger.group(4) data = web.urlencode({'u': name, 'from': ''}).encode('ascii') url = follow_redirects('http://en.shindanmaker.com/' + trigger.group(3).strip()) try: soup = get_soup(web.post(url, data)) shindan = soup.find(class_='result') if shindan is None: bot.say('The shindanmaker ID %s does not exist!' % (trigger.group(3).strip(), )) else: bot.say(shindan.text.strip()) except Exception as e: bot.say('418 I\'m a teapot')
def url_handler(bot, trigger): """ Check for malicious URLs """ check = True # Enable URL checking strict = False # Strict mode: kick on malicious URL positives = 0 # Number of engines saying it's malicious total = 0 # Number of total engines use_vt = True # Use VirusTotal if bot.config.has_section('safety'): check = bot.config.safety.enabled_by_default if check is None: # If not set, assume default check = True else: check = bool(check) # DB overrides config: setting = bot.db.get_channel_value(trigger.sender, 'safety') if setting is not None: if setting == 'off': return # Not checking elif setting in ['on', 'strict', 'local', 'local strict']: check = True if setting == 'strict' or setting == 'local strict': strict = True if setting == 'local' or setting == 'local strict': use_vt = False if not check: return # Not overriden by DB, configured default off netloc = urlparse(trigger).netloc if any(regex.search(netloc) for regex in known_good): return # Whitelisted apikey = bot.config.safety.vt_api_key try: if apikey is not None and use_vt: payload = { 'resource': unicode(trigger), 'apikey': apikey, 'scan': '1' } if trigger not in bot.memory['safety_cache']: result = web.post(vt_base_api_url + 'report', payload) if sys.version_info.major > 2: result = result.decode('utf-8') result = json.loads(result) age = time.time() data = { 'positives': result['positives'], 'total': result['total'], 'age': age } bot.memory['safety_cache'][trigger] = data if len(bot.memory['safety_cache']) > 1024: _clean_cache(bot) else: print('using cache') result = bot.memory['safety_cache'][trigger] positives = result['positives'] total = result['total'] except Exception as e: LOGGER.debug('Error from checking URL with VT.', exc_info=True) pass # Ignoring exceptions with VT so MalwareDomains will always work if unicode(netloc).lower() in malware_domains: # malwaredomains is more trustworthy than some VT engines # therefor it gets a weight of 10 engines when calculating confidence positives += 10 total += 10 if positives > 1: # Possibly malicious URL detected! confidence = '{}%'.format(round((positives / total) * 100)) msg = 'link posted by %s is possibliy malicious ' % bold(trigger.nick) msg += '(confidence %s - %s/%s)' % (confidence, positives, total) bot.say('[' + bold(color('WARNING', 'red')) + '] ' + msg) if strict: bot.write([ 'KICK', trigger.sender, trigger.nick, 'Posted a malicious link' ])
def handle_auth_response(): code = bottle.request.query.code state = bottle.request.query.state repo = state.split(":")[0] channel = state.split(":")[1] data = { "client_id": willie_instance.config.github.client_id, "client_secret": willie_instance.config.github.secret, "code": code, } raw = web.post("https://github.com/login/oauth/access_token", data, headers={"Accept": "application/json"}) try: res = json.loads(raw) if "scope" not in res: raise ValueError("You've already completed authorization on this repo") if "write:repo_hook" not in res["scope"]: raise ValueError("You didn't allow read/write on repo hooks!") access_token = res["access_token"] data = { "name": "web", "active": "true", "events": ["*"], "config": {"url": "http://xpw.us/webhook", "content_type": "json"}, } raw = web.post( "https://api.github.com/repos/{}/hooks?access_token={}".format(repo, access_token), json.dumps(data) ) res = json.loads(raw) if "ping_url" not in res: if "errors" in res: raise ValueError(", ".join([error["message"] for error in res["errors"]])) else: raise ValueError("Webhook creation failed, try again.") raw, headers = web.get(res["ping_url"] + "?access_token={}".format(access_token), return_headers=True) title = "Done!" header = "Webhook setup complete!" body = "That was simple, right?! You should be seeing a completion message in {} any second now".format(channel) flair = "There's no way it was that easy... things are never this easy..." except Exception as e: title = "Error!" header = "Webhook setup failed!" body = "Please try using the link in {} again, something went wrong!".format(channel) flair = str(e) page = """ <!DOCTYPE html> <html> <head> <title>{title}</title> <style> body {{ width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; }} </style> </head> <body> <h1>{header}</h1> <p>{body}</p> <small><em>{flair}</em></small> </body> </html> """ return page.format(title=title, header=header, body=body, flair=flair)
def shorten_url(url): try: res, headers = web.post("http://git.io", "url=" + web.quote(url), return_headers=True) return headers["location"] except: return url
def handle_auth_response(): code = bottle.request.query.code state = bottle.request.query.state repo = state.split(':')[0] channel = state.split(':')[1] data = {'client_id': willie_instance.config.github.client_id, 'client_secret': willie_instance.config.github.secret, 'code': code} raw = web.post('https://github.com/login/oauth/access_token', data, headers={'Accept': 'application/json'}) try: res = json.loads(raw) if 'scope' not in res: raise ValueError('You\'ve already completed authorization on this repo') if 'write:repo_hook' not in res['scope']: raise ValueError('You didn\'t allow read/write on repo hooks!') access_token = res['access_token'] data = { "name": "web", "active": True, "events": ["*"], "config": { "url": "http://xpw.us/webhook", "content_type": "json" } } raw = web.post('https://api.github.com/repos/{}/hooks?access_token={}'.format(repo, access_token), json.dumps(data)) res = json.loads(raw) if 'ping_url' not in res: if 'errors' in res: raise ValueError(', '.join([error['message'] for error in res['errors']])) else: raise ValueError('Webhook creation failed. If you\'re creating a webhook on an organization repo, please ensure you\'ve granted Inumuta IRC Bot access to the organization at https://github.com/settings/applications') raw, headers = web.get(res['ping_url'] + '?access_token={}'.format(access_token), return_headers=True) title = 'Done!' header = 'Webhook setup complete!' body = 'That was simple, right?! You should be seeing a completion message in {} any second now'.format(channel) flair = 'There\'s no way it was that easy... things are never this easy...' except Exception as e: title = 'Error!' header = 'Webhook setup failed!' body = 'Please try using the link in {} again, something went wrong!'.format(channel) flair = str(e) page = ''' <!DOCTYPE html> <html> <head> <title>{title}</title> <style> body {{ width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; }} </style> </head> <body> <h1>{header}</h1> <p>{body}</p> <small><em>{flair}</em></small> </body> </html> ''' return page.format(title=title, header=header, body=body, flair=flair)
def who(bot, trigger): sid = bot.getForumSID() whoText = web.post('http://www.crimbogrotto.com/mchat.php', 'mode=read&room_id=6&sid={0}'.format(sid)) lastIDSoup = BeautifulSoup(whoText) whoMessage = lastIDSoup.find_all('div', class_='mChatHover')[-1].text bot.msg(trigger.nick, whoMessage.decode('utf-8'), relay=False)
def url_handler(bot, trigger): """ Check for malicious URLs """ check = True # Enable URL checking strict = False # Strict mode: kick on malicious URL positives = 0 # Number of engines saying it's malicious total = 0 # Number of total engines use_vt = True # Use VirusTotal if bot.config.has_section('safety'): check = bot.config.safety.enabled_by_default if check is None: # If not set, assume default check = True else: check = bool(check) # DB overrides config: setting = bot.db.get_channel_value(trigger.sender, 'safety') if setting is not None: if setting == 'off': return # Not checking elif setting in ['on', 'strict', 'local', 'local strict']: check = True if setting == 'strict' or setting == 'local strict': strict = True if setting == 'local' or setting == 'local strict': use_vt = False if not check: return # Not overriden by DB, configured default off netloc = urlparse(trigger).netloc if any(regex.search(netloc) for regex in known_good): return # Whitelisted apikey = bot.config.safety.vt_api_key try: if apikey is not None and use_vt: payload = {'resource': unicode(trigger), 'apikey': apikey, 'scan': '1'} if trigger not in bot.memory['safety_cache']: result = web.post(vt_base_api_url + 'report', payload) if sys.version_info.major > 2: result = result.decode('utf-8') result = json.loads(result) age = time.time() data = {'positives': result['positives'], 'total': result['total'], 'age': age} bot.memory['safety_cache'][trigger] = data if len(bot.memory['safety_cache']) > 1024: _clean_cache(bot) else: print('using cache') result = bot.memory['safety_cache'][trigger] positives = result['positives'] total = result['total'] except Exception as e: LOGGER.debug('Error from checking URL with VT.', exc_info=True) pass # Ignoring exceptions with VT so MalwareDomains will always work if unicode(netloc).lower() in malware_domains: # malwaredomains is more trustworthy than some VT engines # therefor it gets a weight of 10 engines when calculating confidence positives += 10 total += 10 if positives > 1: # Possibly malicious URL detected! confidence = '{}%'.format(round((positives / total) * 100)) msg = 'link posted by %s is possibliy malicious ' % bold(trigger.nick) msg += '(confidence %s - %s/%s)' % (confidence, positives, total) bot.say('[' + bold(color('WARNING', 'red')) + '] ' + msg) if strict: bot.write(['KICK', trigger.sender, trigger.nick, 'Posted a malicious link'])
def postIRCWho(bot, trigger=None): sid = bot.getForumSID() users = bot.privileges['#crimbogrotto'].keys() web.post('http://www.crimbogrotto.com/mchat.php', 'room_id=7&mode=add&sid={0}&message={1}'.format(sid, ', '.join(users)))
def latex(bot, trigger): #Request Body # formula=<FORMULA>&fsize=17px&fcolor=000000&mode=0&out=1&remhost=quicklatex.com&preamble=\usepackage{amsmath}\usepackage{amsfonts}\usepackage{amssymb} data = web.urlencode({'formula': trigger.group(2), 'fsize': '25px', 'fcolor': '000000', 'mode': '0', 'out': '1', 'remhost': 'quicklatex.com', 'preamble': '\\usepackage{amsmath}\\usepackage{amsfonts}\\usepackage{amssymb}'}).encode('ascii') url = web.post('http://quicklatex.com/latex3.f', data).split()[1] bot.reply(web.get('http://is.gd/create.php?format=simple&url=' + url))
def msg(self, recipient, text, max_messages=1, relay=True): # We're arbitrarily saying that the max is 400 bytes of text when # messages will be split. Otherwise, we'd have to acocunt for the bot's # hostmask, which is hard. max_text_length = 400 # Encode to bytes, for propper length calculation if isinstance(text, unicode): encoded_text = text.encode('utf-8') else: encoded_text = text excess = '' if max_messages > 1 and len(encoded_text) > max_text_length: last_space = encoded_text.rfind(' ', 0, max_text_length) if last_space == -1: excess = encoded_text[max_text_length:] encoded_text = encoded_text[:max_text_length] else: excess = encoded_text[last_space + 1:] encoded_text = encoded_text[:last_space] # We'll then send the excess at the end # Back to unicode again, so we don't screw things up later. text = encoded_text.decode('utf-8') try: self.sending.acquire() # No messages within the last 3 seconds? Go ahead! # Otherwise, wait so it's been at least 0.8 seconds + penalty recipient_id = Nick(recipient) if recipient_id not in self.stack: self.stack[recipient_id] = [] elif self.stack[recipient_id]: elapsed = time.time() - self.stack[recipient_id][-1][0] if elapsed < 3: penalty = float(max(0, len(text) - 50)) / 70 wait = 0.7 + penalty if elapsed < wait: time.sleep(wait - elapsed) # Loop detection messages = [m[1] for m in self.stack[recipient_id][-8:]] # If what we about to send repeated at least 5 times in the # last 2 minutes, replace with '...' if messages.count(text) >= 5 and elapsed < 120: text = '...' if messages.count('...') >= 3: # If we said '...' 3 times, discard message return self.write(('PRIVMSG', recipient), text) self.stack[recipient_id].append((time.time(), self.safe(text))) self.stack[recipient_id] = self.stack[recipient_id][-10:] finally: self.sending.release() if recipient == "#crimbogrotto" and relay: forumsid = self.getForumSID() mchatmessage = web.quote("[b]CGBot:[/b] "+text) web.post("http://www.crimbogrotto.com/mchat.php","room_id=0&mode=add&sid="+forumsid+"&message="+mchatmessage) # Now that we've sent the first part, we need to send the rest. Doing # this recursively seems easier to me than iteratively if excess: self.msg(recipient, excess, max_messages - 1, relay)
def forumLogin(bot): text = web.post( "http://www.crimbogrotto.com/ucp.php?","mode=login&username=CGIRC&password="******"&redirect=./ucp.php?mode=login&redirect=index.php&login=Login"); SIDMatch = re.search( r'\?sid=([^"]+)"',text ) bot.cachedSID = SIDMatch.group(1) bot.lastSIDUpdate = datetime.now() return bot.cachedSID
def handle_auth_response(): code = bottle.request.query.code state = bottle.request.query.state repo = state.split(':')[0] channel = state.split(':')[1] data = { 'client_id': willie_instance.config.github.client_id, 'client_secret': willie_instance.config.github.secret, 'code': code } raw = web.post('https://github.com/login/oauth/access_token', data, headers={'Accept': 'application/json'}) try: res = json.loads(raw) if 'scope' not in res: raise ValueError( 'You\'ve already completed authorization on this repo') if 'write:repo_hook' not in res['scope']: raise ValueError('You didn\'t allow read/write on repo hooks!') access_token = res['access_token'] data = { "name": "web", "active": "true", "events": ["*"], "config": { "url": "http://xpw.us/webhook", "content_type": "json" } } raw = web.post( 'https://api.github.com/repos/{}/hooks?access_token={}'.format( repo, access_token), json.dumps(data)) res = json.loads(raw) if 'ping_url' not in res: if 'errors' in res: raise ValueError(', '.join( [error['message'] for error in res['errors']])) else: raise ValueError('Webhook creation failed, try again.') raw, headers = web.get(res['ping_url'] + '?access_token={}'.format(access_token), return_headers=True) title = 'Done!' header = 'Webhook setup complete!' body = 'That was simple, right?! You should be seeing a completion message in {} any second now'.format( channel) flair = 'There\'s no way it was that easy... things are never this easy...' except Exception as e: title = 'Error!' header = 'Webhook setup failed!' body = 'Please try using the link in {} again, something went wrong!'.format( channel) flair = str(e) page = ''' <!DOCTYPE html> <html> <head> <title>{title}</title> <style> body {{ width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; }} </style> </head> <body> <h1>{header}</h1> <p>{body}</p> <small><em>{flair}</em></small> </body> </html> ''' return page.format(title=title, header=header, body=body, flair=flair)
def hastebin_it(text): raw = web.post('http://hastebin.com/documents', text) return u'http://hastebin.com/raw/' + json.loads(raw)['key']