def load_db(): """ load lines from find.txt to search_dict """ if not os.path.isfile("find.txt"): f = open("find.txt", "w") f.write("#test,yano,foobar\n") f.close() search_file = open("find.txt", "r") lines = search_file.readlines() search_file.close() search_dict = dict() for line in lines: line = uc.decode(line) line = uc.encode(line) a = line.replace(r'\n', '') new = a.split(r',') if len(new) < 3: continue channel = new[0] nick = new[1] if len(new) < 2: continue if channel not in search_dict: search_dict[channel] = dict() if nick not in search_dict[channel]: search_dict[channel][nick] = list() if len(new) > 3: result = ",".join(new[2:]) result = result.replace('\n', '') elif len(new) == 3: result = new[-1] if len(result) > 0: result = result[:-1] if result: search_dict[channel][nick].append(uc.decode(result)) return search_dict
def c(jenni, input): """.c -- Google calculator.""" if not input.group(2): return jenni.reply('Nothing to calculate.') q = input.group(2).encode('utf-8') q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5 q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0 uri = 'https://www.google.com/ig/calculator?q=' bytes = web.get(uri + web.urllib.quote(q)) parts = bytes.split('",') equation = [p for p in parts if p.startswith('{lhs: "')][0][7:] answer = [p for p in parts if p.startswith('rhs: "')][0][6:] if answer and equation: answer = answer.decode('unicode-escape') answer = ''.join(chr(ord(c)) for c in answer) answer = uc.decode(answer) answer = answer.replace(u'\xc2\xa0', ',') answer = answer.replace('<sup>', '^(') answer = answer.replace('</sup>', ')') answer = web.decode(answer) answer = answer.strip() equation = uc.decode(equation) equation = equation.strip() max_len = 450 - len(answer) - 6 new_eq = equation if len(new_eq) > max_len: end = max_len - 10 new_eq = new_eq[:end] new_eq += '[..]' output = '\x02' + answer + '\x02' + ' == ' + new_eq jenni.say(output) else: jenni.say('Sorry, no result.')
def ten(channel, ranking): channel = channel.lower() if channel not in self.scores_dict: return self.STRINGS["nochan"].format(channel) q = 0 top_scores = list() if ranking == 'b': tob = 'Bottom' elif ranking == 't': tob= 'Top' str_say = "\x02%s 10 (for %s):\x02" % (tob, channel) sort = True if ranking == 'b': sort = False scores = sorted(self.scores_dict[channel].iteritems(), key=lambda (k, v): (v[0] - v[1]), reverse=sort) for key, value in scores: top_scores.append(self.str_score(key, channel)) if len(scores) == q + 1: str_say += ' %s' % (uc.decode(top_scores[q])) else: str_say += ' %s |' % (uc.decode(top_scores[q])) q += 1 if q > 9: break return str_say
def cs(kenni, input): '''.cs <callsign> -- queries qth.com for call sign information''' cs = input.group(2).upper() try: link = "http://www.qth.com/callsign.php?cs=" + uc.decode(web.quote(cs)) except Exception as e: print(e) return kenni.say('Failed to obtain data from qth.com') page = web.get(link) info = re_look.findall(page) more_info = re_more.findall(page) if info and more_info: info = info[0] name = info[0] name = re_tag.sub(' ', info[0]).strip() address = info[1].split('<br>') address = ', '.join(address[1:]) address = address.strip() extra = dict() for each in more_info: extra[each[0].strip()] = re_tag.sub('', each[1].strip()).strip() response = '(%s) ' % (web.quote(cs)) response += 'Name: %s, Address: %s. ' # More information is available at: %s' response = response % (uc.decode(name), uc.decode(address)) for each in more_info: temp = re_tag.sub('', each[1].strip()) if not temp: temp = 'N/A' response += '%s: %s. ' % (each[0].strip(), temp) response += 'More information is available at: %s' % (link) else: response = 'No matches found.' kenni.say(response)
def load_db(): """ load lines from find.txt to search_dict """ if not os.path.isfile("find.txt"): f = open("find.txt", "w") f.write("#test,yano,foobar\n") f.close() search_file = open("find.txt", "r") lines = search_file.readlines() search_file.close() search_dict = dict() for line in lines: line = uc.decode(line) line = uc.encode(line) a = line.replace(r'\n', '') new = a.split(r',') if len(new) < 3: continue channel = new[0] nick = new[1] if len(new) < 2: continue if channel not in search_dict: search_dict[channel] = dict() if nick not in search_dict[channel]: search_dict[channel][nick] = list() if len(new) > 3: result = ",".join(new[2:]) result = result.replace('\n','') elif len(new) == 3: result = new[-1] if len(result) > 0: result = result[:-1] if result: search_dict[channel][nick].append(uc.decode(result)) return search_dict
def ten(channel, ranking): channel = channel.lower() if channel not in self.scores_dict: return self.STRINGS["nochan"].format(channel) q = 0 top_scores = list() if ranking == 'b': tob = 'Bottom' elif ranking == 't': tob = 'Top' str_say = "\x02%s 10 (for %s):\x02" % (tob, channel) sort = True if ranking == 'b': sort = False scores = sorted(self.scores_dict[channel].iteritems(), key=lambda (k, v): (v[0] - v[1]), reverse=sort) for key, value in scores: top_scores.append(self.str_score(key, channel)) if len(scores) == q + 1: str_say += ' %s' % (uc.decode(top_scores[q])) else: str_say += ' %s |' % (uc.decode(top_scores[q])) q += 1 if q > 9: break return str_say
def e(m): entity = m.group() if entity.startswith('&#x'): cp = int(entity[3:-1], 16) meep = unichr(cp) elif entity.startswith('&#'): cp = int(entity[2:-1]) meep = unichr(cp) else: char = name2codepoint[entity[1:-1]] meep = unichr(char) try: return uc.decode(meep) except: return uc.decode(uc.encode(meep))
def e(m): entity = m.group() if entity.startswith("&#x"): cp = int(entity[3:-1], 16) meep = unichr(cp) elif entity.startswith("&#"): cp = int(entity[2:-1]) meep = unichr(cp) else: char = name2codepoint[entity[1:-1]] meep = unichr(char) try: return uc.decode(meep) except: return uc.decode(uc.encode(meep))
def get_results(text): if not text: return list() a = re.findall(url_finder, text) k = len(a) i = 0 display = list() passs = False while i < k: url = uc.encode(a[i][0]) url = uc.decode(url) url = uc.iriToUri(url) url = remove_nonprint(url) domain = getTLD(url) if '//' in domain: domain = domain.split('//')[1] if not url.startswith(EXCLUSION_CHAR): passs, page_title = find_title(url) if bitly_loaded: bitly = short(url) bitly = bitly[0][1] else: bitly = url display.append([page_title, url, bitly]) i += 1 return passs, display
def short(text): """ This function creates a bitly url for each url in the provided string. The return type is a list. """ if not bitly_loaded: return list() if not text: return list() bitlys = list() try: a = re.findall(url_finder, text) k = len(a) i = 0 while i < k: b = uc.decode(a[i][0]) if not b.startswith('http://bit.ly') and \ not b.startswith('http://j.mp/'): longer = urllib2.quote(b) url = 'http://api.j.mp/v3/shorten?login=%s' % (bitly_user) url += '&apiKey=%s&longUrl=%s&format=txt' % (bitly_api_key, longer) shorter = web.get(url) shorter.strip() bitlys.append([b, shorter]) else: bitlys.append([b, b]) i += 1 return bitlys except: return
def show_title_auto(jenni, input): '''No command - Automatically displays titles for URLs''' for each in BLOCKED_MODULES: if input.startswith('.%s ' % (each)): ## Don't want it to show duplicate titles return if len(re.findall('\([\d]+\sfiles\sin\s[\d]+\sdirs\)', input)) == 1: ## Directory Listing of files return status, results = get_results(input) k = 1 output_shorts = str() results_len = len(results) for r in results: returned_title = r[0] orig = r[1] bitly_link = r[2] link_pass = r[3] if orig and bitly_link and bitly_link != orig and ( 'bit.ly' in bitly_link or 'j.mp' in bitly_link): bitly_link = bitly_link.replace('http:', 'https:') if returned_title == 'imgur: the simple image sharer': return if k > 3: break k += 1 useBitLy = doUseBitLy(returned_title, orig) reg_format = '[ %s ] - %s' special_format = '[ %s ]' response = str() if status and link_pass: if useBitLy and input.sender not in simple_channels and bitly_link: response = reg_format % (uc.decode(returned_title), bitly_link) else: if input.sender in simple_channels: response = special_format % (returned_title) else: response = reg_format % (returned_title, orig) elif len(orig) > BITLY_TRIGGER_LEN_NOTITLE: if useBitLy and bitly_link != orig: #response = '%s' % (bitly_link) output_shorts += bitly_link + ' ' else: ## Fail silently, link can't be bitly'ed and no title was found pass if response: jenni.say(response) if output_shorts: jenni.say((output_shorts).strip())
def delquote(jenni, input): '''.rmquote <number> -- removes a given quote from the database. Can only be done by the owner of the bot.''' if not input.owner: return text = input.group(2) number = int() try: fn = open('quotes.txt', 'r') except: return jenni.reply('No quotes to delete.') lines = fn.readlines() MAX = len(lines) fn.close() try: number = int(text) except: jenni.reply('Please enter the quote number you would like to delete.') return newlines = lines[:number-1] + lines[number:] fn = open('quotes.txt', 'w') for line in newlines: txt = uc.decode(line) if txt: fn.write(txt) if txt[-1] != '\n': fn.write('\n') fn.close() jenni.reply('Successfully deleted quote %s.' % (number))
def collectlines(jenni, input): """Creates a temporary storage of most recent lines for s///""" #channel = (input.sender).encode("utf-8") channel = uc.decode(input.sender) channel = uc.encode(channel) nick = (input.nick).encode("utf-8") search_dict = load_db() if channel not in search_dict: search_dict[channel] = dict() if 'last_said' not in search_dict[channel]: search_dict[channel]['last_said'] = list() if nick not in search_dict[channel]: search_dict[channel][nick] = list() templist = search_dict[channel][nick] last_said_templist = search_dict[channel]['last_said'] line = input.group() try: line = (line).encode("utf-8") except Exception: return if line.startswith("s/") or line.startswith('!'): return elif line.startswith("\x01ACTION"): line = line[:-1] templist.append(line) last_said_templist.append("{}: {}".format(input.nick, line)) del templist[:-50] del last_said_templist[:-50] search_dict[channel][nick] = templist search_dict[channel]['last_said'] = last_said_templist save_db(search_dict)
def collectlines(jenni, input): """Creates a temporary storage of most recent lines for s///""" # don't log things in PM #channel = (input.sender).encode("utf-8") channel = uc.decode(input.sender) channel = uc.encode(channel) nick = (input.nick).encode("utf-8") if not channel.startswith('#'): return search_dict = load_db() if channel not in search_dict: search_dict[channel] = dict() if nick not in search_dict[channel]: search_dict[channel][nick] = list() templist = search_dict[channel][nick] line = input.group() if line.startswith("s/"): return elif line.startswith("\x01ACTION"): line = line[:-1] templist.append(line) else: templist.append(line) del templist[:-10] search_dict[channel][nick] = templist save_db(search_dict)
def short(text): """ This function creates a bitly url for each url in the provided string. The return type is a list. """ if not bitly_loaded: return list() if not text: return list() bitlys = list() try: a = re.findall(url_finder, text) k = len(a) i = 0 while i < k: b = uc.decode(a[i][0]) ## make sure that it is not already a bitly shortened link if not is_bitly(b): longer = urllib2.quote(b) url = 'https://api-ssl.bitly.com/v3/shorten?login=%s' % (bitly_user) url += '&apiKey=%s&longUrl=%s&format=txt' % (bitly_api_key, longer) #shorter = proxy.get(url) shorter = web.get(url) shorter.strip() bitlys.append([b, shorter]) else: bitlys.append([b, str()]) i += 1 return bitlys except: return return bitlys
def short(text): """ This function creates a bitly url for each url in the provided string. The return type is a list. """ if not bitly_loaded: return list() if not text: return list() bitlys = list() try: a = re.findall(url_finder, text) k = len(a) i = 0 while i < k: b = uc.decode(a[i][0]) ## make sure that it is not already a bitly shortened link if not is_bitly(b): longer = urllib2.quote(b) url = 'https://api-ssl.bitly.com/v3/shorten?login=%s' % ( bitly_user) url += '&apiKey=%s&longUrl=%s&format=txt' % (bitly_api_key, longer) #shorter = proxy.get(url) shorter = web.get(url) shorter.strip() bitlys.append([b, shorter]) else: bitlys.append([b, str()]) i += 1 return bitlys except: return return bitlys
def show_title_auto(jenni, input): '''No command - Automatically displays titles for URLs''' for each in BLOCKED_MODULES: if input.startswith('.%s ' % (each)): ## Don't want it to show duplicate titles return if len(re.findall('\([\d]+\sfiles\sin\s[\d]+\sdirs\)', input)) == 1: ## Directory Listing of files return status, results = get_results(input) k = 1 output_shorts = str() results_len = len(results) for r in results: returned_title = r[0] orig = r[1] bitly_link = r[2] link_pass = r[3] if orig and bitly_link and bitly_link != orig and ('bit.ly' in bitly_link or 'j.mp' in bitly_link): bitly_link = bitly_link.replace('http:', 'https:') if returned_title == 'imgur: the simple image sharer': return if k > 3: break k += 1 useBitLy = doUseBitLy(returned_title, orig) reg_format = '[ %s ] - %s' special_format = '[ %s ]' response = str() if status and link_pass: if useBitLy and input.sender not in simple_channels and bitly_link: response = reg_format % (uc.decode(returned_title), bitly_link) else: if input.sender in simple_channels: response = special_format % (returned_title) else: response = reg_format % (returned_title, orig) elif len(orig) > BITLY_TRIGGER_LEN_NOTITLE: if useBitLy and bitly_link != orig: #response = '%s' % (bitly_link) output_shorts += bitly_link + ' ' else: ## Fail silently, link can't be bitly'ed and no title was found pass if response: jenni.say(response) if output_shorts: jenni.say((output_shorts).strip())
def cs(jenni, input): '''.cs <callsign> -- queries qth.com for call sign information''' cs = input.group(2).upper() try: link = "http://www.qth.com/callsign.php?cs=" + uc.decode(web.quote(cs)) except Exception, e: print e return jenni.say('Failed to obtain data from qth.com')
def find_title(url): """ This finds the title when provided with a string of a URL. """ uri = url for item in IGNORE: if item in uri: return False, 'ignored' if not re.search('^((https?)|(ftp))://', uri): uri = 'http://' + uri if '/#!' in uri: uri = uri.replace('/#!', '/?_escaped_fragment_=') if 'i.imgur' in uri: a = uri.split('.') uri = a[0][:-1] + '.'.join(a[1:-1]) if 'zerobin.net' in uri: return True, 'ZeroBin' uri = uc.decode(uri) ## proxy the lookup of the headers through .py def remote_call(): pyurl = u'https://tumbolia.appspot.com/py/' code = 'import simplejson;' code += 'opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(),' code += 'urllib2.BaseHandler(), urllib2.HTTPHandler(),' code += 'urllib2.HTTPRedirectHandler(), urllib2.HTTPErrorProcessor(),' code += 'urllib2.UnknownHandler());' code += 'urllib2.install_opener(opener);' code += "req=urllib2.Request(%s, headers={'Accept':'*/*'});" code += "req.add_header('User-Agent', %s);" code += "u=urllib2.urlopen(req);" code += "rtn=dict();" code += "rtn['headers'] = u.headers.dict;" code += "contents = u.read(32768);" code += "con = str();" code += r'''exec "try: con=(contents).decode('utf-8')\n''' code += '''except: con=(contents).decode('iso-8859-1')";''' code += "rtn['read'] = con;" code += "rtn['url'] = u.url;" code += "rtn['geturl'] = u.geturl();" code += "print simplejson.dumps(rtn)" query = code % (repr(uri), repr(USER_AGENT)) temp = web.quote(query) u = web.get(pyurl + temp) try: useful = json.loads(u) return True, useful except Exception, e: #print "%s -- Failed to parse json from web resource. -- %s" % (time.time(), str(e)) return False, str(u)
def save(self): """ Save to file in comma seperated values """ os.rename(self.scores_filename, '%s-%s' % (self.scores_filename, str(time.time()))) scores_file = codecs.open(self.scores_filename, 'w', encoding='utf-8') for each_chan in self.scores_dict: for each_nick in self.scores_dict[each_chan]: line = '{0},{1},{2},{3}\n'.format(each_chan, each_nick, self.scores_dict[each_chan][each_nick][0], self.scores_dict[each_chan][each_nick][1]) scores_file.write(uc.decode(line)) scores_file.close()
def ep(m): entity = m.group() if entity.startswith('&#x'): cp = int(entity[3:-1], 16) meep = unichr(cp) elif entity.startswith('&#'): cp = int(entity[2:-1]) meep = unichr(cp) else: entity_stripped = entity[1:-1] try: char = name2codepoint[entity_stripped] meep = unichr(char) except: meep = str() try: return uc.decode(meep) except: return uc.decode(uc.encode(meep))
def ip_lookup(jenni, input): txt = input.group(2) if not txt: return jenni.reply("No search term!") txt = uc.encode(txt) query = uc.decode(txt) response = "[IP/Host Lookup] " try: page = web.get(base + txt) except IOError, err: return jenni.say('Could not access given address. (Detailed error: %s)' % (err))
def clean_up_answer(answer): answer = answer.encode('utf-8') answer = answer.decode('utf-8') answer = ''.join(chr(ord(c)) for c in answer) answer = uc.decode(answer) answer = answer.replace('<sup>', '^(') answer = answer.replace('</sup>', ')') answer = web.decode(answer) answer = answer.strip() answer += ' [GC]' return answer
def ip_lookup(jenni, input): txt = input.group(2) if not txt: return jenni.reply("No search term!") txt = uc.encode(txt) query = uc.decode(txt) response = "[IP/Host Lookup] " try: page = web.get(base + txt) except IOError, err: return jenni.say( 'Could not access given address. (Detailed error: %s)' % (err))
def quote(s, safe='/'): # quote('abc def') -> 'abc%20def' s = uc.encode(s) s = uc.decode(s) safe += always_safe safe_map = dict() for i in range(256): c = chr(i) safe_map[c] = (c in safe) and c or ('%%%02X' % i) try: res = map(safe_map.__getitem__, s) except: return '' return ''.join(res)
def e(m): entity = m.group() if entity.startswith("&#x"): cp = int(entity[3:-1], 16) meep = unichr(cp) elif entity.startswith("&#"): cp = int(entity[2:-1]) meep = unichr(cp) else: entity_stripped = entity[1:-1] try: char = name2codepoint[entity_stripped] meep = unichr(char) except: if entity_stripped in HTML_ENTITIES: meep = HTML_ENTITIES[entity_stripped] else: meep = str() try: return uc.decode(meep) except: return uc.decode(uc.encode(meep))
def e(m): entity = m.group() if entity.startswith('&#x'): cp = int(entity[3:-1], 16) meep = unichr(cp) elif entity.startswith('&#'): cp = int(entity[2:-1]) meep = unichr(cp) else: entity_stripped = entity[1:-1] try: char = name2codepoint[entity_stripped] meep = unichr(char) except: if entity_stripped in HTML_ENTITIES: meep = HTML_ENTITIES[entity_stripped] else: meep = str() try: return uc.decode(meep) except: return uc.decode(uc.encode(meep))
def save(self): """ Save to file in comma seperated values """ os.rename(self.scores_filename, '%s-%s' % (self.scores_filename, str(time.time()))) scores_file = codecs.open(self.scores_filename, 'w', encoding='utf-8') for each_chan in self.scores_dict: for each_nick in self.scores_dict[each_chan]: line = '{0},{1},{2},{3}\n'.format( each_chan, each_nick, self.scores_dict[each_chan][each_nick][0], self.scores_dict[each_chan][each_nick][1]) scores_file.write(uc.decode(line)) scores_file.close()
def find_title(url): """ This finds the title when provided with a string of a URL. """ uri = url for item in IGNORE: if item in uri: return False, 'ignored' if not re.search('^((https?)|(ftp))://', uri): uri = 'http://' + uri if 'twitter.com' in uri: uri = uri.replace('#!', '?_escaped_fragment_=') if 'i.imgur' in uri: a = uri.split('.') uri = a[0][:-1] + '.'.join(a[1:-1]) uri = uc.decode(uri) ## proxy the lookup of the headers through .py def remote_call(): pyurl = u'https://tumbolia.appspot.com/py/' code = 'import simplejson;' code += 'import time; unique = str(time.time());' code += "req=urllib2.Request(u'%s', headers={'Accept':'text/html'});" code += "req.add_header('User-Agent', 'Mozilla/5.0" code += "');" code += "u=urllib2.urlopen(req);" code += "rtn=dict();" code += "rtn['headers'] = u.headers.dict;" code += "contents = u.read();" code += "con = str();" code += r'''exec "try: con=(contents).decode('utf-8')\n''' code += '''except: con=(contents).decode('iso-8859-1')";''' code += "rtn['read'] = con;" code += "rtn['url'] = u.url;" code += "rtn['geturl'] = u.geturl();" code += r"print simplejson.dumps(rtn)" query = code % uri temp = web.quote(query) u = web.get(pyurl + temp) try: useful = json.loads(u) return True, useful except Exception, e: #print "%s -- Failed to parse json from web resource. -- %s" % (time.time(), str(e)) return False, str(u)
def get_results(text, manual=False): if not text: return False, list() a = re.findall(url_finder, text) k = len(a) i = 0 display = list() passs = False channel = str() if hasattr(text, 'sender'): channel = text.sender while i < k: url = uc.encode(a[i][0]) url = uc.decode(url) url = uc.iriToUri(url) url = remove_nonprint(url) domain = getTLD(url) if '//' in domain: domain = domain.split('//')[1] if 'i.imgur.com' in url and url.startswith('http://'): url = url.replace('http:', 'https:') bitly = url if not url.startswith(EXCLUSION_CHAR): passs, page_title = find_title(url) if not manual: if bitly_loaded: if channel and channel not in simple_channels: bitly = short(url) if bitly: bitly = bitly[0][1] display.append([page_title, url, bitly, passs]) else: ## has exclusion character if manual: ## only process excluded URLs if .title is used url = url[1:] passs, page_title = find_title(url) display.append([page_title, url, bitly, passs]) i += 1 ## check to make sure at least 1 URL worked correctly overall_pass = False for x in display: if x[-1] == True: overall_pass = True return overall_pass, display
def read_tweet(url): bytes = web.get(url) shim = '<div class="content clearfix">' if shim in bytes: bytes = bytes.split(shim, 1).pop() for text in r_p.findall(bytes): text = expand(text) text = r_tag.sub('', text) text = text.strip() text = r_entity.sub(e, uc.decode(text)) text = r_whiteline.sub(' ', text) text = r_breaks.sub(' ', text) return decode(text) return "Sorry, couldn't get a tweet from %s" % url
def read_tweet(url): bytes = web.get(url) shim = '<div class="content clearfix">' if shim in bytes: bytes = bytes.split(shim, 1).pop() for text in r_p.findall(bytes): text = expand(text) text = r_tag.sub("", text) text = text.strip() text = r_entity.sub(e, uc.decode(text)) text = r_whiteline.sub(" ", text) text = r_breaks.sub(" ", text) return decode(text) return "Sorry, couldn't get a tweet from %s" % url
def ip_lookup(code, input): txt = input.group(2) if not txt: return code.reply(code.color('red', 'No search term!')) elif txt.find('192.168.0.') > -1 or txt.find('127.0.0.') > -1: return code.reply(code.color('red', 'That IP is blacklisted!')) elif not txt.find('.') > -1 or not txt.find(':') > -1: return code.reply(code.color('red','Incorrect input!')) txt = uc.encode(txt) query = uc.decode(txt) response = '' #response = '[' + code.color('blue', 'IP/Host Lookup ') + '] ' page = web.get(base + txt) try: results = json.loads(page) except: print str(page) return code.color('red', code.reply('Couldn\'t receive information for %s' % code.bold(txt))) if results: print 'query', str(query) print 'matches', re_ip.findall(query) if re_ip.findall(query): ## IP Address try: hostname = socket.gethostbyaddr(query)[0] except: hostname = code.bold(code.color('red', 'Unknown Host')) response += code.color('blue', 'Hostname: ') + str(hostname) else: ## Host name response += code.bold(code.color('blue','IP: ')) + results['ip'] spacing = ' ' + code.bold('|') for param in results: if not results[param]: results[param] = code.bold(code.color('red', 'N/A')) if 'city' in results: response += '%s %s %s' % (spacing, code.bold(code.color('blue', 'City:')), results['city']) if 'region_name' in results: response += '%s %s %s' % (spacing, code.bold(code.color('blue', 'State:')), results['region_name']) if 'country_name' in results: response += '%s %s %s' % (spacing, code.bold(code.color('blue', 'Country:')), results['country_name']) if 'zip' in results: response += '%s %s %s' % (spacing, code.bold(code.color('blue', 'ZIP:')), results['zip']) response += '%s %s %s' % (spacing, code.bold(code.color('blue', 'Latitude:')), results['latitude']) response += '%s %s %s' % (spacing, code.bold(code.color('blue', 'Longitude:')), results['longitude']) code.reply(response)
def get_results(text, manual=False): if not text: return list() a = re.findall(url_finder, text) k = len(a) i = 0 display = list() passs = False while i < k: url = uc.encode(a[i][0]) url = uc.decode(url) url = uc.iriToUri(url) url = remove_nonprint(url) domain = getTLD(url) if '//' in domain: domain = domain.split('//')[1] bitly = url if not url.startswith(EXCLUSION_CHAR): if not manual: if bitly_loaded: bitly = short(url) if bitly: bitly = bitly[0][1] passs, page_title = find_title(url) if not passs: passs, page_title = find_title(url) display.append([page_title, url, bitly, passs]) else: ## has exclusion character if manual: ## only process excluded URLs if .title is used url = url[1:] passs, page_title = find_title(url) display.append([page_title, url, bitly, passs]) i += 1 ## check to make sure at least 1 URL worked correctly overall_pass = False for x in display: if x[-1] == True: overall_pass = True return overall_pass, display
def show_title_auto(jenni, input): '''No command - Automatically displays titles for URLs''' for each in BLOCKED_MODULES: if input.startswith('.%s ' % (each)): ## Don't want it to show duplicate titles return if len(re.findall('\([\d]+\sfiles\sin\s[\d]+\sdirs\)', input)) == 1: ## Directory Listing of files return status, results = get_results(input) k = 1 for r in results: returned_title = r[0] orig = r[1] bitly_link = r[2] link_pass = r[3] if k > 3: break k += 1 useBitLy = doUseBitLy(returned_title, orig) reg_format = '[ %s ] - %s' special_format = '[ %s ]' response = str() if status and link_pass: if useBitLy and input.sender not in simple_channels: response = reg_format % (uc.decode(returned_title), bitly_link) else: if input.sender in simple_channels: response = special_format % (returned_title) else: response = reg_format % (returned_title, getTLD(orig)) elif len(orig) > BITLY_TRIGGER_LEN_NOTITLE: if useBitLy: response = '%s' % (bitly_link) else: ## Fail silently, link can't be bitly'ed and no title was found pass if response: jenni.say(response)
def find_title(url): """ This finds the title when provided with a string of a URL. """ uri = url for item in IGNORE: if item in uri: return False, 'ignored' if not re.search('^((https?)|(ftp))://', uri): uri = 'http://' + uri if 'twitter.com' in uri: uri = uri.replace('#!', '?_escaped_fragment_=') if 'i.imgur' in uri: a = uri.split('.') uri = a[0][:-1] + '.'.join(a[1:-1]) uri = uc.decode(uri) ## proxy the lookup of the headers through .py pyurl = u'https://tumbolia.appspot.com/py/' code = 'import simplejson;' code += "req=urllib2.Request(u'%s', headers={'Accept':'text/html'});" code += "req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1 " code += "rv:17.0) Gecko/20100101 Firefox/17.0'); u=urllib2.urlopen(req);" code += "rtn=dict();" code += "rtn['headers'] = u.headers.dict;" code += "contents = u.read();" code += "con = str();" code += r'''exec "try: con=(contents).decode('utf-8')\n''' code += '''except: con=(contents).decode('iso-8859-1')";''' code += "rtn['read'] = con;" code += "rtn['url'] = u.url;" code += "rtn['geturl'] = u.geturl();" code += r"print simplejson.dumps(rtn)" query = code % uri try: temp = web.quote(query) u = web.get(pyurl + temp) except Exception, e: return False, e
def save_db(search_dict): """ save search_dict to find.txt """ search_file = open("find.txt", "w") for channel in search_dict: if channel is not "": for nick in search_dict[channel]: for line in search_dict[channel][nick]: channel = uc.decode(channel) channel_utf = uc.encode(channel) search_file.write(channel_utf) search_file.write(",") nick = uc.encode(nick) search_file.write(nick) search_file.write(",") line_utf = line if not type(str()) == type(line): line_utf = uc.encode(line) search_file.write(line_utf) search_file.write("\n") search_file.close()
def show_title_auto(jenni, input): '''No command - Automatically displays titles for URLs''' for each in BLOCKED_MODULES: if input.startswith('.%s ' % (each)): ## Don't want it to show duplicate titles return if len(re.findall('\([\d]+\sfiles\sin\s[\d]+\sdirs\)', input)) == 1: ## Directory Listing of files return status, results = get_results(input) k = 1 for r in results: returned_title = r[0] orig = r[1] bitly_link = r[2] link_pass = r[3] if k > 3: break k += 1 useBitLy = doUseBitLy(returned_title, orig) reg_format = '[ %s ] - %s' response = str() if status and link_pass: if useBitLy: response = reg_format % (uc.decode(returned_title), bitly_link) else: response = reg_format % (returned_title, getTLD(orig)) elif len(orig) > BITLY_TRIGGER_LEN_NOTITLE: if useBitLy: response = '%s' % (bitly_link) else: ## Fail silently, link can't be bitly'ed and no title was found pass if response: jenni.say(response)
def ip_lookup(jenni, input): txt = input.group(2) if not txt: return jenni.reply("No search term!") txt = uc.encode(txt) query = uc.decode(txt) response = "[IP/Host Lookup] " page = web.get(base + txt) try: results = json.loads(page) except: print str(page) return jenni.reply('Did not receive proper JSON from %s' % (base)) if results: print 'query', str(query) print 'matches', re_ip.findall(query) if re_ip.findall(query): ## IP Address try: hostname = socket.gethostbyaddr(query)[0] except: hostname = 'Unknown Host' response += 'Hostname: ' + str(hostname) else: ## Host name response += 'IP: ' + results['ip'] spacing = ' |' for param in results: if not results[param]: results[param] = 'N/A' if 'city' in results: response += '%s City: %s' % (spacing, results['city']) if 'region_name' in results: response += '%s State: %s' % (spacing, results['region_name']) if 'country_name' in results: response += '%s Country: %s' % (spacing, results['country_name']) if 'zip' in results: response += '%s ZIP: %s' % (spacing, results['zip']) response += '%s Latitude: %s' % (spacing, results['latitude']) response += '%s Longitutde: %s' % (spacing, results['longitude']) jenni.reply(response)
def insult(kenni, input): """ insults <target> with configured language insult """ try: insultFilename = os.path.expanduser('~/Kenni/config/insult.'+ kenni.config.insult_lang +'.txt') except: kenni.say("You need to configure the default language!") return target = input.group(2) if not target: return kenni.say('.i <target>!') target.encode('utf-8') target = (target).strip() try: fn = open(insultFilename, "r") except IOError as e: generateDatabase(kenni, insultFilename) fn = open(insultFilename, "r") lines = fn.readlines() fn.close() random.seed() kenni.say(target + ': ' + uc.decode(random.choice(lines)))
def insult(jenni, input): """ insults <target> with configured language insult """ try: insultFilename = os.path.expanduser('~/.jenni/insult.'+ jenni.config.insult_lang +'.txt') except: jenni.say("You need to configure the default language!") return target = input.group(2) if not target: return jenni.reply('.i <target>!') target.encode('utf-8') target = (target).strip() try: fn = open(insultFilename, "r") except IOError as e: generateDatabase(jenni, insultFilename) fn = open(insultFilename, "r") lines = fn.readlines() fn.close() random.seed() jenni.say(target + ': ' + uc.decode(random.choice(lines)))
def ip_lookup(jenni, input): txt = input.group(2) if not txt: return jenni.reply("No search term!") txt = uc.encode(txt) query = uc.decode(txt) response = "[IP/Host Lookup] " page = web.get(base + txt) try: results = json.loads(page) except: return jenni.reply('Did not receive proper JSON from %s' % (base)) if results: if re_ip.findall(query): ## IP Address try: hostname = socket.gethostbyaddr(query)[0] except: hostname = 'Unknown Host' response += 'Hostname: ' + str(hostname) else: ## Host name response += 'IP: ' + results['ip'] spacing = ' |' for param in results: if not results[param]: results[param] = 'N/A' if 'city' in results: response += '%s City: %s' % (spacing, results['city']) if 'region_name' in results: response += '%s State: %s' % (spacing, results['region_name']) if 'country_name' in results: response += '%s Country: %s' % (spacing, results['country_name']) if 'zip' in results: response += '%s ZIP: %s' % (spacing, results['zip']) response += '%s Latitude: %s' % (spacing, results['latitude']) response += '%s Longitude: %s' % (spacing, results['longitude']) jenni.reply(response)
def update_backlog(jenni, input): """Write every received line to a backlog file""" channel = uc.encode(uc.decode(input.sender)) nick = (input.nick).encode("utf-8") line = input.group() if type(line) != type(str()): line = uc.encode(line) # Rules for lines that should be excluded if not channel.startswith("#"): return elif line.startswith("."): return elif line.startswith("s/"): return jenni.backlog_lock.acquire() try: backlog_file = open(jenni.backlog_filename, "a") backlog_file.write("{},{},{}\n".format(channel, nick, line)) backlog_file.close() #TODO: Check backlog size and clear oldest entries if needed finally: jenni.backlog_lock.release()
def find_title(url): """ This finds the title when provided with a string of a URL. """ for item in IGNORE: if item in url: return False, 'ignored' if not re.search('^((https?)|(ftp))://', url): url = 'http://' + url if '/#!' in url: url = url.replace('/#!', '/?_escaped_fragment_=') if 'i.imgur' in url: a = url.split('.') url = a[0][:-1] + '.'.join(a[1:-1]) if 'zerobin.net' in url: return True, 'ZeroBin' url = uc.decode(url) msg = str() k = 0 status = False while not status: k += 1 if k > 3: break msg = dict() try: status, msg = proxy.get_more(url) except: try: status, msg = get_page_backup(url) except: continue if type(msg) == type(dict()) and 'code' in msg: status = msg['code'] else: continue time.sleep(0.5) if not status: return False, msg useful = msg info = useful['headers'] page = useful['read'] try: mtype = info['content-type'] except: print 'failed mtype:', str(info) return False, 'mtype failed' if not (('/html' in mtype) or ('/xhtml' in mtype)): return False, str(mtype) content = page regex = re.compile('<(/?)title( [^>]+)?>', re.IGNORECASE) content = regex.sub(r'<\1title>', content) regex = re.compile('[\'"]<title>[\'"]', re.IGNORECASE) content = regex.sub('', content) start = content.find('<title>') if start == -1: return False, 'NO <title> found' end = content.find('</title>', start) if end == -1: return False, 'NO </title> found' content = content[start + 7:end] content = content.strip('\n').rstrip().lstrip() title = content if len(title) > 200: title = title[:200] + '[...]' def e(m): entity = m.group() if entity.startswith('&#x'): cp = int(entity[3:-1], 16) meep = unichr(cp) elif entity.startswith('&#'): cp = int(entity[2:-1]) meep = unichr(cp) else: entity_stripped = entity[1:-1] try: char = name2codepoint[entity_stripped] meep = unichr(char) except: if entity_stripped in HTML_ENTITIES: meep = HTML_ENTITIES[entity_stripped] else: meep = str() try: return uc.decode(meep) except: return uc.decode(uc.encode(meep)) title = r_entity.sub(e, title) title = title.replace('\n', '') title = title.replace('\r', '') def remove_spaces(x): if ' ' in x: x = x.replace(' ', ' ') return remove_spaces(x) else: return x title = remove_spaces(title) new_title = str() for char in title: unichar = uc.encode(char) if len(list(uc.encode(char))) <= 3: new_title += uc.encode(char) title = new_title title = re.sub(r'(?i)dcc\ssend', '', title) title += '\x0F' if title: return True, title else: return False, 'No Title'
page = web.get(link) info = re_look.findall(page) more_info = re_more.findall(page) if info and more_info: info = info[0] name = info[0] name = re_tag.sub(' ', info[0]).strip() address = info[1].split('<br>') address = ', '.join(address[1:]) address = address.strip() extra = dict() for each in more_info: extra[each[0].strip()] = re_tag.sub('', each[1].strip()).strip() response = '(%s) ' % (web.quote(cs)) response += 'Name: %s, Address: %s. ' # More information is available at: %s' response = response % (uc.decode(name), uc.decode(address)) for each in more_info: temp = re_tag.sub('', each[1].strip()) if not temp: temp = 'N/A' response += '%s: %s. ' % (each[0].strip(), temp) response += 'More information is available at: %s' % (link) else: response = 'No matches found.' jenni.say(response) cs.commands = ['cs', 'callsign'] cs.example = '.cs W8LT' def cw(jenni, input): re_cw = re.compile("[/\.\- ]+") re_noncw = re.compile("[^/\.\- ]+")
def c(jenni, input): '''.c -- Google calculator.''' ## let's not bother if someone doesn't give us input if not input.group(2): return jenni.reply('Nothing to calculate.') ## handle some unicode conversions q = input.group(2).encode('utf-8') q = q.replace('\xcf\x95', 'phi') # utf-8 U+03D5 q = q.replace('\xcf\x80', 'pi') # utf-8 U+03C0 ## Attempt #1 (Google) uri = 'https://www.google.com/search?gbv=1&q=' uri += web.urllib.quote(q) ## To the webs! try: page = web.get(uri) except: ## if we can't access Google for calculating ## let us move on to Attempt #2 page = None answer = None if page: ## if we get a response from Google ## let us parse out an equation from Google Search results answer = c_answer.findall(page) if answer: ## if the regex finding found a match we want the first result answer = answer[0] #answer = answer.replace(u'\xc2\xa0', ',') answer = answer.decode('unicode-escape') answer = ''.join(chr(ord(c)) for c in answer) answer = uc.decode(answer) answer = answer.replace('<sup>', '^(') answer = answer.replace('</sup>', ')') answer = web.decode(answer) answer = answer.strip() jenni.say(answer) else: #### Attempt #2 (DuckDuckGo's API) ddg_uri = 'https://api.duckduckgo.com/?format=json&q=' ddg_uri += urllib.quote(q) ## Try to grab page (results) ## If page can't be accessed, we shall fail! try: page = web.get(ddg_uri) except: page = None ## Try to take page source and json-ify it! try: json_response = json.loads(page) except: ## if it can't be json-ified, then we shall fail! json_response = None ## Check for 'AnswerType' (stolen from search.py) ## Also 'fail' to None so we can move on to Attempt #3 if (not json_response) or (hasattr(json_response, 'AnswerType') and json_response['AnswerType'] != 'calc'): answer = None else: ## If the json contains an Answer that is the result of 'calc' ## then continue answer = re.sub(r'\<.*?\>', '', json_response['Answer']).strip() if answer: ## If we have found answer with Attempt #2 ## go ahead and display it jenni.say(answer) else: #### Attempt #3 (DuckDuckGo's HTML) ## This relies on BeautifulSoup; if it can't be found, don't even bother try: from BeautifulSoup import BeautifulSoup except: return jenni.say('No results. (Please install BeautifulSoup for additional checking.)') ddg_html_page = web.get('https://duckduckgo.com/html/?q=%s&kl=us-en&kp=-1' % (web.urllib.quote(q))) soup = BeautifulSoup(ddg_html_page) ## use BeautifulSoup to parse HTML for an answer zero_click = str() if soup('div', {'class': 'zero-click-result'}): zero_click = str(soup('div', {'class': 'zero-click-result'})[0]) ## remove some excess text output = r_tag.sub('', zero_click).strip() output = output.replace('\n', '').replace('\t', '') ## test to see if the search module has 'remove_spaces' ## otherwise, let us fail try: output = search.remove_spaces(output) except: output = str() if output: ## If Attempt #3 worked, display the answer jenni.say(output) else: ## If we made it this far, we have tried all available resources jenni.say('Absolutely no results!')