def get_episodes_for_series(seriesname): res = {"error": None, "ended": False, "episodes": None, "name": None} # http://thetvdb.com/wiki/index.php/API:GetSeries try: query = http.get_xml(base_url + "GetSeries.php", seriesname=seriesname) except http.URLError: res["error"] = "error contacting thetvdb.com" return res series_id = query.xpath("//seriesid/text()") if not series_id: res["error"] = "unknown tv series (using www.thetvdb.com)" return res series_id = series_id[0] try: series = http.get_xml(base_url + "%s/series/%s/all/en.xml" % (api_key, series_id)) except http.URLError: res["error"] = "error contacting thetvdb.com" return res series_name = series.xpath("//SeriesName/text()")[0] if series.xpath("//Status/text()")[0] == "Ended": res["ended"] = True res["episodes"] = series.xpath("//Episode") res["name"] = series_name return res
def get_episodes_for_series(seriesname): res = {"error": None, "ended": False, "episodes": None, "name": None} # http://thetvdb.com/wiki/index.php/API:GetSeries try: query = http.get_xml(base_url + "GetSeries.php", seriesname=seriesname) except http.URLError: res["error"] = "error contacting thetvdb.com" return res series_id = query.xpath("//seriesid/text()") if not series_id: res["error"] = "unknown tv series (using www.thetvdb.com)" return res series_id = series_id[0] try: series = http.get_xml( base_url + "%s/series/%s/all/en.xml" % (api_key, series_id) ) except http.URLError: res["error"] = "error contacting thetvdb.com" return res series_name = series.xpath("//SeriesName/text()")[0] if series.xpath("//Status/text()")[0] == "Ended": res["ended"] = True res["episodes"] = series.xpath("//Episode") res["name"] = series_name return res
def stock(inp): "stock <symbol> -- Gets information about stock symbol <symbol>." parsed = http.get_xml(url, stock=inp) if len(parsed) != 1: return "error getting stock info" # Stuff the results in a dict for easy string formatting results = dict( (el.tag, el.attrib['data']) for el in parsed.xpath('//finance/*')) # if we dont get a company name back, the symbol doesn't match a company if results['company'] == '': return "error: unknown ticker symbol (%s)" % inp if results['last'] == '0.00': return "%(company)s - last known stock value was 0.00 %(currency)s" \ " as of %(trade_timestamp)s" % (results) if results['change'][0] == '-': results['color'] = "5" else: results['color'] = "3" ret = "%(company)s - %(last)s %(currency)s " \ "\x03%(color)s%(change)s (%(perc_change)s%%)\x03 " \ "as of %(trade_timestamp)s" % results if results['delay'] != '0': ret += " (delayed %s minutes)" % results['delay'] return ret
def twittergrep(inp): ".twittergrep <user> <search> -- gets last tweet by this user which includes the search string" if inp.strip().find(' ') == -1: return 'error: invalid request' name = inp[:inp.find(' ')] search = inp[inp.find(' ') + 1:].lower().strip() try: tweets = http.get_xml( 'http://twitter.com/statuses/user_timeline/%s.xml' % name) except http.HTTPError, e: errors = { 400: 'bad request (ratelimited?)', 401: 'tweet is private', 403: 'tweet is private', 404: 'invalid user/id', 500: 'twitter is broken', 502: 'twitter is down ("getting upgraded")', 503: 'twitter is overloaded (lol, RoR)' } if e.code == 404: return 'error: invalid username' if e.code in errors: return 'error: ' + errors[e.code] return 'error: unknown %s' % e.code
def time_command(inp, bot=None): """time <area> -- Gets the time in <area>""" query = "current time in {}".format(inp) api_key = bot.config.get("api_keys", {}).get("wolframalpha", None) if not api_key: return "error: no wolfram alpha api key set" request = http.get_xml(api_url, input=query, appid=api_key) current_time = " ".join( request.xpath("//pod[@title='Result']/subpod/plaintext/text()")) current_time = current_time.replace(" | ", ", ") if current_time: # nice place name for UNIX time if inp.lower() == "unix": place = "Unix Epoch" else: place = capitalize_first(" ".join( request.xpath( "//pod[@" "title='Input interpretation']/subpod/plaintext/text()")) [16:]) return "{} - \x02{}\x02".format(current_time, place) else: return "Could not get the time for '{}'.".format(inp)
def wiki(inp): """wiki <phrase> -- Gets first sentence of Wikipedia article on <phrase>.""" x = http.get_xml(search_url, search=inp) ns = '{http://opensearch.org/searchsuggest2}' items = x.findall(ns + 'Section/' + ns + 'Item') if not items: if x.find('error') is not None: return 'error: %(code)s: %(info)s' % x.find('error').attrib else: return 'No results found.' def extract(item): return [item.find(ns + x).text for x in ('Text', 'Description', 'Url')] title, desc, url = extract(items[0]) if 'may refer to' in desc: title, desc, url = extract(items[1]) title = paren_re.sub('', title) if title.lower() not in desc.lower(): desc = title + desc desc = re.sub('\s+', ' ', desc).strip() # remove excess spaces desc = text.truncate_str(desc, 200) return '{} :: {}'.format(desc, http.quote(url, ':/'))
def get_episodes_for_series(seriesname, api_key): res = {"error": None, "ended": False, "episodes": None, "name": None} # http://thetvdb.com/wiki/index.php/API:GetSeries try: query = http.get_xml(base_url + 'GetSeries.php', seriesname=seriesname) except URLError: res["error"] = "error contacting thetvdb.com" return res series_id = query.xpath('//seriesid/text()') if not series_id: res["error"] = "unknown tv series (using www.thetvdb.com)" return res series_id = series_id[0] try: series = get_zipped_xml(base_url + '%s/series/%s/all/en.zip' % (api_key, series_id), path="en.xml") except URLError: res["error"] = "error contacting thetvdb.com" return res series_name = series.xpath('//SeriesName/text()')[0] if series.xpath('//Status/text()')[0] == 'Ended': res["ended"] = True res["episodes"] = series.xpath('//Episode') res["name"] = series_name return res
def time_command(inp, bot=None): """.time <area> - Gets the time in <area>.""" if inp.lower() == "butts": return "It's always time for butts." query = "current time in {}".format(inp) api_key = bot.config.get("api_keys", {}).get("wolframalpha", None) if not api_key: return "error: no wolfram alpha api key set" request = http.get_xml(api_url, input=query, appid=api_key) time = " ".join( request.xpath("//pod[@title='Result']/subpod/plaintext/text()")) time = time.replace(" | ", ", ") if time: # nice place name for UNIX time if inp.lower() == "unix": place = "Unix Epoch" else: place = cap_first( " ".join(request.xpath("//pod[@" "title='Input interpretation']/subpod/plaintext/text()")).split('|')[0]) place = place.replace("Current Time In", "").strip() return "\x02{}\x02 - {}".format(place, time) else: return "Could not get the time for '{}'.".format(inp)
def wiki(inp): '''.w/.wiki <phrase> -- gets first sentence of wikipedia ''' \ '''article on <phrase>''' x = http.get_xml(search_url, search=inp) ns = '{http://opensearch.org/searchsuggest2}' items = x.findall(ns + 'Section/' + ns + 'Item') if items == []: if x.find('error') is not None: return 'error: %(code)s: %(info)s' % x.find('error').attrib else: return 'no results found' def extract(item): return [item.find(ns + x).text for x in ('Text', 'Description', 'Url')] title, desc, url = extract(items[0]) if 'may refer to' in desc: title, desc, url = extract(items[1]) title = paren_re.sub('', title) if title.lower() not in desc.lower(): desc = title + desc desc = re.sub('\s+', ' ', desc).strip() # remove excess spaces if len(desc) > 300: desc = desc[:300] + '...' return '%s -- %s' % (desc, http.quote(url, ':/'))
def stock(inp): '''.stock <symbol> -- gets information about a stock symbol''' url = 'http://www.google.com/ig/api?stock=%s' parsed = http.get_xml(url, stock=inp) if len(parsed) != 1: return "error getting stock info" # Stuff the results in a dict for easy string formatting results = dict((el.tag, el.attrib['data']) for el in parsed.xpath('//finance/*')) # if we dont get a company name back, the symbol doesn't match a company if results['company'] == '': return "unknown ticker symbol %s" % inp if results['change'][0] == '-': results['color'] = "5" else: results['color'] = "3" ret = "%(company)s - %(last)s %(currency)s " \ "\x03%(color)s%(change)s (%(perc_change)s%%)\x03 " \ "as of %(trade_timestamp)s" % results if results['delay'] != '0': ret += " (delayed %s minutes)" % results['delay'] return ret
def get_series_info(seriesname): res = {"error": None, "ended": False, "episodes": None, "name": None} # http://thetvdb.com/wiki/index.php/API:GetSeries try: query = http.get_xml(base_url + 'GetSeries.php', seriesname=seriesname) except URLError: res["error"] = "error contacting thetvdb.com" return res series_id = "" try: series_id = query.xpath('//id/text()') except: print "Failed" if not series_id: result = "\x02Could not find show:\x02 %s" % seriesname else: series_name = query.xpath('//SeriesName/text()')[0] overview = query.xpath('//Overview/text()')[0] firstaired = query.xpath('//FirstAired/text()')[0] #imdb_id = query.xpath('//IMDB_ID/text()')[0] #imdb_url = web.isgd("http://www.imdb.com/title/%s" % imdb_id) tvdb_url = web.isgd("http://thetvdb.com/?tab=series&id=%s" % series_id[0]) status = tv_next(seriesname) result = '\x02%s\x02 (%s) \x02-\x02 \x02%s\x02 - [%s] - %s' % ( series_name, firstaired, status, tvdb_url, overview) return result
def wiki(inp): "wiki <phrase> -- Gets first sentence of Wikipedia article on <phrase>." x = http.get_xml(search_url, search=inp) ns = '{http://opensearch.org/searchsuggest2}' items = x.findall(ns + 'Section/' + ns + 'Item') if items == []: if x.find('error') is not None: return 'error: %(code)s: %(info)s' % x.find('error').attrib else: return 'No results found.' def extract(item): return [item.find(ns + x).text for x in ('Text', 'Description', 'Url')] title, desc, url = extract(items[0]) if 'may refer to' in desc: title, desc, url = extract(items[1]) title = paren_re.sub('', title) if title.lower() not in desc.lower(): desc = title + desc desc = re.sub('\s+', ' ', desc).strip() # remove excess spaces desc = text.truncate_str(desc, 250) return '%s -- %s' % (desc, http.quote(url, ':/'))
def wiki(inp): '''.w/.wiki <phrase> -- gets first sentence of wikipedia ''' \ '''article on <phrase>''' x = http.get_xml(search_url, search=inp) ns = '{http://opensearch.org/searchsuggest2}' items = x.findall(ns + 'Section/' + ns + 'Item') if items == []: if x.find('error') is not None: return 'error: %(code)s: %(info)s' % x.find('error').attrib else: return 'no results found' def extract(item): return [item.find(ns + x).text for x in ('Text', 'Description', 'Url')] title, desc, url = extract(items[0]) if 'may refer to' in desc: title, desc, url = extract(items[1]) title = paren_re.sub('', title) if title.lower() not in desc.lower(): desc = title + desc desc = re.sub('\s+', ' ', desc).strip() # remove excess spaces if len(desc) > 300: desc = desc[:300] + '...' return '%s -- %s' % (desc, http.quote(http.unquote(url), ':/'))
def kb(inp): """kb <topic> -- Gets the first article available on <topic>.""" x = http.get_xml(search_url, search=inp) ns = '{http://opensearch.org/searchsuggest2}' items = x.findall(ns + 'Section/' + ns + 'Item') if not items: if x.find('error') is not None: return 'error: %(code)s: %(info)s' % x.find('error').attrib else: return 'No results found.' def extract(item): return [item.find(ns + x).text for x in ('Text', 'Description', 'Url')] title, desc, url = extract(items[0]) if 'may refer to' in desc: title, desc, url = extract(items[1]) title = paren_re.sub('', title) if title.lower() not in desc.lower(): desc = title + desc desc = u' '.join(desc.split()) # remove excess spaces desc = text.truncate_str(desc, 200) return u'{} :: {}'.format(desc, http.quote(url, ':/'))
def get_series_info(seriesname): res = {"error": None, "ended": False, "episodes": None, "name": None} # http://thetvdb.com/wiki/index.php/API:GetSeries try: query = http.get_xml(base_url + 'GetSeries.php', seriesname=seriesname) except URLError: res["error"] = "error contacting thetvdb.com" return res series_id = "" try: series_id = query.xpath('//id/text()') except: print "Failed" if not series_id: result = "\x02Could not find show:\x02 %s" % seriesname else: series_name = query.xpath('//SeriesName/text()')[0] overview = query.xpath('//Overview/text()')[0] firstaired = query.xpath('//FirstAired/text()')[0] #imdb_id = query.xpath('//IMDB_ID/text()')[0] #imdb_url = web.isgd("http://www.imdb.com/title/%s" % imdb_id) tvdb_url = web.isgd("http://thetvdb.com/?tab=series&id=%s" % series_id[0]) status = tv_next(seriesname) result = '\x02%s\x02 (%s) \x02-\x02 \x02%s\x02 - [%s] - %s' % (series_name, firstaired, status, tvdb_url, overview) return result
def stock(inp): ".stock <symbol> -- Gets information about stock symbol <symbol>." url = 'http://www.google.com/ig/api?stock=%s' parsed = http.get_xml(url, stock=inp) if len(parsed) != 1: return "error getting stock info" # Stuff the results in a dict for easy string formatting results = dict((el.tag, el.attrib['data']) for el in parsed.xpath('//finance/*')) # if we dont get a company name back, the symbol doesn't match a company if results['company'] == '': return "unknown ticker symbol %s" % inp if results['change'][0] == '-': results['color'] = "5" else: results['color'] = "3" ret = "%(company)s - %(last)s %(currency)s " \ "\x03%(color)s%(change)s (%(perc_change)s)\x03 " \ "as of %(trade_timestamp)s" % results if results['delay'] != '0': ret += " (delayed %s minutes)" % results['delay'] return ret
def get_episodes_for_series(series_name, api_key): res = {"error": None, "ended": False, "episodes": None, "name": None} # http://thetvdb.com/wiki/index.php/API:GetSeries try: query = http.get_xml(base_url + 'GetSeries.php', seriesname=series_name) except URLError: res["error"] = "error contacting thetvdb.com" return res series_id = query.xpath('//seriesid/text()') if not series_id: res["error"] = "Unknown TV series. (using www.thetvdb.com)" return res series_id = series_id[0] try: series = get_zipped_xml(base_url + '%s/series/%s/all/en.zip' % (api_key, series_id), path="en.xml") except URLError: res["error"] = "Error contacting thetvdb.com." return res series_name = series.xpath('//SeriesName/text()')[0] if series.xpath('//Status/text()')[0] == 'Ended': res["ended"] = True res["episodes"] = series.xpath('//Episode') res["name"] = series_name return res
def get_twitter(inp): try: text = 'status/text' url = 'http://twitter.com/users/show/%s.xml' % inp screen_name = 'screen_name' tweet = http.get_xml(url) text = unescape_xml(tweet.find(text).text.replace('\n', '')) screen_name = tweet.find(screen_name).text except http.HTTPError, e: return 'error: '+str(e.code)
def wolframalpha(inp, bot=None): "wa <query> -- Computes <query> using Wolfram Alpha." api_key = bot.config.get("api_keys", {}).get("wolframalpha", None) if not api_key: return "error: missing api key" url = 'http://api.wolframalpha.com/v2/query?format=plaintext' result = http.get_xml(url, input=inp, appid=api_key) # get the URL for a user to view this query in a browser query_url = "http://www.wolframalpha.com/input/?i=" + \ http.quote_plus(inp.encode('utf-8')) try: short_url = web.isgd(query_url) except (web.ShortenError, http.HTTPError): short_url = query_url pod_texts = [] for pod in result.xpath("//pod[@primary='true']"): title = pod.attrib['title'] if pod.attrib['id'] == 'Input': continue results = [] for subpod in pod.xpath('subpod/plaintext/text()'): subpod = subpod.strip().replace('\\n', '; ') subpod = re.sub(r'\s+', ' ', subpod) if subpod: results.append(subpod) if results: pod_texts.append(title + ': ' + ', '.join(results)) ret = ' - '.join(pod_texts) if not pod_texts: return 'No results.' ret = re.sub(r'\\(.)', r'\1', ret) def unicode_sub(match): return unichr(int(match.group(1), 16)) ret = re.sub(r'\\:([0-9a-z]{4})', unicode_sub, ret) ret = text.truncate_str(ret, 250) if not ret: return 'No results.' return "%s - %s" % (ret, short_url)
def getTwitchStream(user): r = http.get_xml('http://api.justin.tv/api/stream/list.xml?channel=%s' % user) try: viewers = r.xpath('//stream/channel_count/text()')[0] except IndexError: return False if r.xpath('//stream/format/text()')[0] == 'live': if viewers: return True, viewers else: return False else: return False
def getOwnedStream(user): h = http.get_xml('http://api.own3d.tv/liveCheck.php?live_id=' + user) status = h.xpath('//liveEvent/isLive/text()')[0] try: viewers = h.xpath('//liveEvent/liveViewers/text()')[0] except IndexError: return False if status == 'true': if viewers: return True, viewers else: return False else: return False
def wolframalpha(inp, bot=None, input=None): ".wa <query> -- Computes <query> using Wolfram Alpha." api_key = bot.config.get("api_keys", {}).get("wolframalpha", None) if api_key is None: return "error: no api key set" if '^' in input.paraml[1]: inp = str(inp).replace("^", bot.chanseen[input.conn.server][input.chan][0]) url = 'http://api.wolframalpha.com/v2/query?format=plaintext' result = http.get_xml(url, input=inp, appid=api_key) input.say("Please wait.") pod_texts = [] for pod in result.xpath("//pod"): title = pod.attrib['title'] if pod.attrib['id'] == 'Input': continue results = [] for subpod in pod.xpath('subpod/plaintext/text()'): subpod = subpod.strip().replace('\\n', '; ') subpod = re.sub(r'\s+', ' ', subpod) if subpod: results.append(subpod) if results: pod_texts.append(title + ': ' + '|'.join(results)) ret = '. '.join(pod_texts) if not pod_texts: return 'No results.' ret = re.sub(r'\\(.)', r'\1', ret) def unicode_sub(match): return unichr(int(match.group(1), 16)) ret = re.sub(r'\\:([0-9a-z]{4})', unicode_sub, ret) if len(ret) > 430: ret = ret[:ret.rfind(' ', 0, 430)] ret = re.sub(r'\W+$', '', ret) + '...' if not ret: return 'No results..' return ret
def wolframalpha(inp, bot=None): ".wa/.wolframalpha <query> -- computes <query> using Wolfram Alpha" api_key = "22PK5Q-Y7YKV77E4U" #api_key = bot.config.get("api_keys", {}).get("wolframalpha", None) #if api_key is None: # return "error: no api key set" url = 'http://api.wolframalpha.com/v2/query?format=plaintext' result = http.get_xml(url, input=inp, appid=api_key) pod_texts = [] for pod in result.xpath("//pod"): title = pod.attrib['title'] if pod.attrib['id'] == 'Input': continue results = [] for subpod in pod.xpath('subpod/plaintext/text()'): subpod = subpod.strip().replace('\\n', '; ') subpod = re.sub(r'\s+', ' ', subpod) if subpod: results.append(subpod) if results: pod_texts.append(title + ': ' + '|'.join(results)) ret = '. '.join(pod_texts) if not pod_texts: return 'no results' ret = re.sub(r'\\(.)', r'\1', ret) def unicode_sub(match): return unichr(int(match.group(1), 16)) ret = re.sub(r'\\:([0-9a-z]{4})', unicode_sub, ret) if len(ret) > 430: ret = ret[:ret.rfind(' ', 0, 430)] ret = re.sub(r'\W+$', '', ret) + '...' if not ret: return 'no results' return ret
def wolframalpha(inp, bot=None): ".wa <query> -- Computes <query> using Wolfram Alpha." api_key = bot.config.get("api", {}).get("wolframalpha") if api_key is None: return "I have a lazy owner, they won't even bother adding an API key! " + randout.fail() url = 'http://api.wolframalpha.com/v2/query?format=plaintext' result = http.get_xml(url, input=inp, appid=api_key) fail = 'No results. ' + randout.fail() pod_texts = [] for pod in result.xpath("//pod"): title = pod.attrib['title'] if pod.attrib['id'] == 'Input': continue results = [] for subpod in pod.xpath('subpod/plaintext/text()'): subpod = subpod.strip().replace('\\n', '; ') subpod = re.sub(r'\s+', ' ', subpod) if subpod: results.append(subpod) if results: pod_texts.append(title + ': ' + '|'.join(results)) ret = '. '.join(pod_texts) if not pod_texts: return fail ret = re.sub(r'\\(.)', r'\1', ret) def unicode_sub(match): return unichr(int(match.group(1), 16)) ret = re.sub(r'\\:([0-9a-z]{4})', unicode_sub, ret) if len(ret) > 430: ret = ret[:ret.rfind(' ', 0, 430)] ret = re.sub(r'\W+$', '', ret) + '...' if not ret: return fail return ret
def bam(inp): ".bam [basic|magic|pepsi|jprdy] <message> -- creates a big ass message" host = 'http://bigassmessage.com/' path = 'dsx_BAM/boe.php?' params = {'action': 'saveMsg', 'theStyle': 'basic', 'theMessage': inp} if ' ' in inp: style, message = inp.split(None, 1) if style in ['basic', 'magic', 'pepsi', 'jprdy']: params['theStyle'] = style params['theMessage'] = message response = http.get_xml(host + path, params) status = response.xpath('//status/text()')[0] if status == 'ok': return host + response.xpath('//msgid/text()')[0] else: return response.xpath('//message/text()')[0]
def stock(inp): """stock <symbol> -- Gets information about stock symbol <symbol>.""" parsed = http.get_xml(url, stock=inp) if len(parsed) != 1: return "error getting stock info" # Stuff the results in a dict for easy string formatting results = dict( (el.tag, el.attrib['data']) for el in parsed.xpath('//finance/*')) # if we dont get a company name back, the symbol doesn't match a company if not "company" in results: guess_data = json.loads( http.get("http://d.yimg.com/autoc.finance.yahoo.com/autoc", query=inp, callback="YAHOO.Finance.SymbolSuggest.ssCallback")[39:-1]) guess = guess_data['ResultSet']['Result'] if len(guess) > 0: guess = guess[0]["symbol"] return stock(guess) else: return "error: unable to get stock info for '{}'".format(inp) if results['last'] == '0.00': return "%(company)s - last known stock value was 0.00 %(currency)s" \ " as of %(trade_timestamp)s" % results if results['change'][0] == '-': results['color'] = "5" else: results['color'] = "3" ret = "%(company)s - %(last)s %(currency)s " \ "\x03%(color)s%(change)s (%(perc_change)s%%)\x03 " \ "as of %(trade_timestamp)s" % results if results['delay'] != '0': ret += " (delayed %s minutes)" % results['delay'] return ret
def wolframalpha(inp, api_key=None): ".wa/.wolframalpha <query> -- computes <query> using Wolfram Alpha" url = "http://api.wolframalpha.com/v2/query?format=plaintext" result = http.get_xml(url, input=inp, appid=api_key) pod_texts = [] for pod in result.xpath("//pod"): title = "" if pod.attrib["title"] == "Result" else pod.attrib["title"] + ": " if pod.attrib["id"] == "Input": continue results = [] for subpod in pod.xpath("subpod/plaintext/text()"): subpod = subpod.strip().replace("\\n", "; ") subpod = re.sub(r"\s+", " ", subpod) if subpod: results.append(subpod) if results: pod_texts.append(title + "|".join(results)) ret = ". ".join(pod_texts) if not pod_texts: return "no results" ret = re.sub(r"\\(.)", r"\1", ret) def unicode_sub(match): return chr(int(match.group(1), 16)) ret = re.sub(r"\\:([0-9a-z]{4})", unicode_sub, ret) if len(ret) > 430: ret = ret[: ret.rfind(" ", 0, 430)] ret = re.sub(r"\W+$", "", ret) + "..." if not ret: return "no results" return ret
def bam(inp): ".bam [basic|magic|heart|krugr] <message> -- creates a big ass message" host = 'http://bigassmessage.com/' path = 'BAM.php?' params = {'action': 'SAVE', 'theStyle': 'basic', 'theMessage': inp} if ' ' in inp: style, message = inp.split(None, 1) if style in ['basic', 'magic', 'heart', 'krugr']: params['theStyle'] = style params['theMessage'] = message response = http.get_xml(host + path, params) status = response.xpath('//status/text()')[0] if status == 'ok': return host + response.xpath('//msgid/text()')[0] else: return response.xpath('//message/text()')[0]
def wa(inp, api_key=None): """.wa/.calc <query> - Computes <query> using Wolfram Alpha.""" url = 'http://api.wolframalpha.com/v2/query?format=plaintext' try: result = http.get_xml(url, input=inp, appid=api_key) except: return "WolframAlpha query timed out for '%s'" % inp pod_texts = [] for pod in result.xpath("//pod"): title = pod.attrib['title'] if pod.attrib['id'] == 'Input': continue results = [] for subpod in pod.xpath('subpod/plaintext/text()'): subpod = subpod.strip().replace('\\n', '; ') subpod = re.sub(r'\s+', ' ', subpod) if subpod: results.append(subpod) if results: pod_texts.append(title + ': ' + '|'.join(results)) ret = '. '.join(pod_texts) if not pod_texts: return 'No results' ret = re.sub(r'\\(.)', r'\1', ret) def unicode_sub(match): return unichr(int(match.group(1), 16)) ret = re.sub(r'\\:([0-9a-z]{4})', unicode_sub, ret) if not ret: return 'No results' return text.truncate_str(ret.split('. ')[0], 230)
def stock(inp): """stock <symbol> -- Gets information about stock symbol <symbol>.""" parsed = http.get_xml(url, stock=inp) if len(parsed) != 1: return "error getting stock info" # Stuff the results in a dict for easy string formatting results = dict((el.tag, el.attrib['data']) for el in parsed.xpath('//finance/*')) # if we dont get a company name back, the symbol doesn't match a company if not "company" in results: guess_data = json.loads(http.get("http://d.yimg.com/autoc.finance.yahoo.com/autoc", query=inp, callback="YAHOO.Finance.SymbolSuggest.ssCallback")[39:-1]) guess = guess_data['ResultSet']['Result'] if len(guess) > 0: guess = guess[0]["symbol"] return stock(guess) else: return "error: unable to get stock info for '{}'".format(inp) if results['last'] == '0.00': return "%(company)s - last known stock value was 0.00 %(currency)s" \ " as of %(trade_timestamp)s" % results if results['change'][0] == '-': results['color'] = "5" else: results['color'] = "3" ret = "%(company)s - %(last)s %(currency)s " \ "\x03%(color)s%(change)s (%(perc_change)s%%)\x03 " \ "as of %(trade_timestamp)s" % results if results['delay'] != '0': ret += " (delayed %s minutes)" % results['delay'] return ret
def forecast(inp, nick='', server='', reply=None, db=None, notice=None, say=None): ".forecast <location> [dontsave] -- Gets a weather forecast" \ " for <location> from Google." loc = inp dontsave = loc.endswith(" dontsave") if dontsave: loc = loc[:-9].strip().lower() db.execute("create table if not exists weather(nick primary key, loc)") if not loc: loc = db.execute("select loc from weather where nick=lower(?)", (nick,)).fetchone() if not loc: notice(forecast.__doc__) return loc = loc[0] w = http.get_xml('http://www.google.com/ig/api', weather=loc) w = w.find('weather') if w.find('problem_cause') is not None: notice("Couldn't fetch weather data for '%s', try using a zip or " \ "postal code." % inp) return city = w.find('forecast_information/city').get('data') out = "%s: " % city for elem in w.findall('forecast_conditions'): info = dict((e.tag, e.get('data')) for e in elem) info['high'] = elem.find('high').get('data') info['low'] = elem.find('low').get('data') out += '[%(day_of_week)s]: %(condition)s (H:%(high)sF'\ ', L:%(low)sF). ' % info return out
def weather(inp, nick='', server='', reply=None, db=None, notice=None): ".weather <location> [dontsave] -- Gets weather data"\ " for <location> from Google." loc = inp dontsave = loc.endswith(" dontsave") if dontsave: loc = loc[:-9].strip().lower() db.execute("create table if not exists weather(nick primary key, loc)") if not loc: loc = db.execute("select loc from weather where nick=lower(?)", (nick,)).fetchone() if not loc: notice(weather.__doc__) return loc = loc[0] w = http.get_xml('http://www.google.com/ig/api', weather=loc) w = w.find('weather') if w.find('problem_cause') is not None: notice("Couldn't fetch weather data for '%s', try using a zip or " \ "postal code." % inp) return info = dict((e.tag, e.get('data')) for e in w.find('current_conditions')) info['city'] = w.find('forecast_information/city').get('data') info['high'] = w.find('forecast_conditions/high').get('data') info['low'] = w.find('forecast_conditions/low').get('data') reply('%(city)s: %(condition)s, %(temp_f)sF/%(temp_c)sC (H:%(high)sF'\ ', L:%(low)sF), %(humidity)s, %(wind_condition)s.' % info) if inp and not dontsave: db.execute("insert or replace into weather(nick, loc) values (?,?)", (nick.lower(), loc)) db.commit()
def weather(inp, nick='', server='', reply=None, db=None): ".weather <location> [dontsave] -- gets weather data from Google" loc = inp dontsave = loc.endswith(" dontsave") if dontsave: loc = loc[:-9].strip().lower() db.execute("create table if not exists weather(nick primary key, loc)") if not loc: # blank line loc = db.execute("select loc from weather where nick=lower(?)", (nick, )).fetchone() if not loc: return weather.__doc__ loc = loc[0] w = http.get_xml('http://www.google.com/ig/api', weather=loc) w = w.find('weather') if w.find('problem_cause') is not None: return "Couldn't fetch weather data for '%s', try using a zip or " \ "postal code." % inp info = dict((e.tag, e.get('data')) for e in w.find('current_conditions')) info['city'] = w.find('forecast_information/city').get('data') info['high'] = w.find('forecast_conditions/high').get('data') info['low'] = w.find('forecast_conditions/low').get('data') reply('%(city)s: %(condition)s, %(temp_f)sF/%(temp_c)sC (H:%(high)sF'\ ', L:%(low)sF), %(humidity)s, %(wind_condition)s.' % info) if inp and not dontsave: db.execute("insert or replace into weather(nick, loc) values (?,?)", (nick.lower(), loc)) db.commit()
def weather(inp, nick="", server="", reply=None, db=None): ",weather <location> [dontsave] -- gets weather data from Google" loc = inp dontsave = loc.endswith(" dontsave") if dontsave: loc = loc[:-9].strip().lower() db.execute("create table if not exists weather(nick primary key, loc)") if not loc: # blank line loc = db.execute("select loc from weather where nick=lower(?)", (nick,)).fetchone() if not loc: return weather.__doc__ loc = loc[0] w = http.get_xml("http://www.google.com/ig/api", weather=loc) w = w.find("weather") if w.find("problem_cause") is not None: return "Couldn't fetch weather data for '%s', try using a zip or " "postal code." % inp info = dict((e.tag, e.get("data")) for e in w.find("current_conditions")) info["city"] = w.find("forecast_information/city").get("data") info["high"] = w.find("forecast_conditions/high").get("data") info["low"] = w.find("forecast_conditions/low").get("data") reply( "%(city)s: %(condition)s, %(temp_f)sF/%(temp_c)sC (H:%(high)sF" ", L:%(low)sF), %(humidity)s, %(wind_condition)s." % info ) if inp and not dontsave: db.execute("insert or replace into weather(nick, loc) values (?,?)", (nick.lower(), loc)) db.commit()
def twittergrep(inp): ".twittergrep <user> <search> -- gets last tweet by this user which includes the search string" if inp.strip().find(' ') == -1: return 'error: invalid request' name = inp[:inp.find(' ')] search = inp[inp.find(' ') + 1:].lower().strip() try: tweets = http.get_xml('http://twitter.com/statuses/user_timeline/%s.xml' % name) except http.HTTPError, e: errors = {400: 'bad request (ratelimited?)', 401: 'tweet is private', 403: 'tweet is private', 404: 'invalid user/id', 500: 'twitter is broken', 502: 'twitter is down ("getting upgraded")', 503: 'twitter is overloaded (lol, RoR)'} if e.code == 404: return 'error: invalid username' if e.code in errors: return 'error: ' + errors[e.code] return 'error: unknown %s' % e.code
def watime(inp, bot=None): """time <area> -- Gets the time in <area>""" query = "current time in {}".format(inp) api_key = bot.config.get("api_keys", {}).get("wolframalpha", None) if not api_key: return "error: no wolfram alpha api key set" request = http.get_xml(api_url, input=query, appid=api_key) time = " ".join(request.xpath("//pod[@title='Result']/subpod/plaintext/text()")) time = time.replace(" | ", ", ") if time: # nice place name for UNIX time if inp.lower() == "unix": place = "Unix Epoch" else: place = capitalize_first(" ".join(request.xpath("//pod[@" "title='Input interpretation']/subpod/plaintext/text()"))[ 16:]) return "{} - \x02{}\x02".format(time, place) else: return u"Could not get the time for '{}'.".format(inp)
def twitter(inp): ".twitter <user>/<user> <n>/<id>/#<hashtag>/@<user> -- gets last/<n>th " "tweet from <user>/gets tweet <id>/gets random tweet with #<hashtag>/" "gets replied tweet from @<user>" def add_reply(reply_name, reply_id): if len(history) == history_max_size: history.pop() history.insert(0, (reply_name, reply_id)) def find_reply(reply_name): for name, id in history: if name == reply_name: return id if id != -1 else name if inp[0] == "@": reply_inp = find_reply(inp[1:]) if reply_inp == None: return "error: no replies to %s found" % inp inp = reply_inp url = "http://twitter.com" getting_nth = False getting_id = False searching_hashtag = False time = "status/created_at" text = "status/text" reply_name = "status/in_reply_to_screen_name" reply_id = "status/in_reply_to_status_id" reply_user = "******" if re.match(r"^\d+$", inp): getting_id = True url += "/statuses/show/%s.xml" % inp screen_name = "user/screen_name" time = "created_at" text = "text" reply_name = "in_reply_to_screen_name" reply_id = "in_reply_to_status_id" reply_user = "******" elif re.match(r"^\w{1,15}$", inp): url += "/users/show/%s.xml" % inp screen_name = "screen_name" elif re.match(r"^\w{1,15}\s+\d+$", inp): getting_nth = True name, num = inp.split() if int(num) > 3200: return "error: only supports up to the 3200th tweet" url += "/statuses/user_timeline/%s.xml?count=1&page=%s" % (name, num) screen_name = "status/user/screen_name" elif re.match(r"^#\w+$", inp): url = "http://search.twitter.com/search.atom?q=%23" + inp[1:] searching_hashtag = True else: return "error: invalid request" try: tweet = http.get_xml(url) except http.HTTPError, e: errors = { 400: "bad request (ratelimited?)", 401: "tweet is private", 403: "tweet is private", 404: "invalid user/id", 500: "twitter is broken", 502: 'twitter is down ("getting upgraded")', 503: "twitter is overloaded (lol, RoR)", } if e.code == 404: return "error: invalid " + ["username", "tweet id"][getting_id] if e.code in errors: return "error: " + errors[e.code] return "error: unknown %s" % e.code
def tv_next(inp): ".tv_next <series> -- get the next episode of <series> from thetvdb.com" # http://thetvdb.com/wiki/index.php/API:GetSeries try: query = http.get_xml(base_url + 'GetSeries.php', seriesname=inp) except URLError: return "error contacting thetvdb.com" series_id = query.xpath('//seriesid/text()') if not series_id: return "unknown tv series (using www.thetvdb.com)" series_id = series_id[0] try: series = get_zipped_xml(base_url + '%s/series/%s/all/en.zip' % (api_key, series_id), path="en.xml") except URLError: return "error contacting thetvdb.com" series_name = series.xpath('//SeriesName/text()')[0] if series.xpath('//Status/text()')[0] == 'Ended': return '%s has ended.' % series_name next_eps = [] today = datetime.date.today() for episode in reversed(series.xpath('//Episode')): first_aired = episode.findtext("FirstAired") try: airdate = datetime.date(*map(int, first_aired.split('-'))) except (ValueError, TypeError): continue episode_num = "S%02dE%02d" % (int(episode.findtext("SeasonNumber")), int(episode.findtext("EpisodeNumber"))) episode_name = episode.findtext("EpisodeName") # in the event of an unannounced episode title, users either leave the # field out (None) or fill it with TBA if episode_name == "TBA": episode_name = None episode_desc = '%s' % episode_num if episode_name: episode_desc += ' - %s' % episode_name if airdate > today: next_eps = ['%s (%s)' % (first_aired, episode_desc)] elif airdate == today: next_eps = ['Today (%s)' % episode_desc] + next_eps else: #we're iterating in reverse order with newest episodes last #so, as soon as we're past today, break out of loop break if not next_eps: return "there are no new episodes scheduled for %s" % series_name if len(next_eps) == 1: return "the next episode of %s airs %s" % (series_name, next_eps[0]) else: next_eps = ', '.join(next_eps) return "the next episodes of %s: %s" % (series_name, next_eps)
def real(): h = http.get_xml('http://www.vice.com/rss') item = random.choice(h.xpath('//item')) msg = item.xpath('title')[0].text url = item.xpath('link')[0].text return msg, url
def steamcalc(inp, reply=None): """steamcalc <username> [currency] - Gets value of steam account and total hours played. Uses steamcommunity.com/id/<nickname>. """ # check if the user asked us to force reload force_reload = inp.endswith(" forcereload") if force_reload: name = inp[:-12].strip().lower() else: name = inp.strip() if force_reload: try: reply("Collecting data, this may take a while.") refresh_data(name) request = get_data(name) do_refresh = False except (http.HTTPError, http.URLError): return "Could not get data for this user." else: try: request = get_data(name) do_refresh = True except (http.HTTPError, http.URLError): try: reply("Collecting data, this may take a while.") refresh_data(name) request = get_data(name) do_refresh = False except (http.HTTPError, http.URLError): return "Could not get data for this user." csv_data = io.StringIO(request) # we use StringIO because CSV can't read a string reader = unicode_dictreader(csv_data) # put the games in a list games = [] for row in reader: games.append(row) data = {} # basic information steam_profile = http.get_xml(steam_api_url.format(name)) try: data["name"] = steam_profile.find('steamID').text online_state = steam_profile.find('stateMessage').text except AttributeError: return "Could not get data for this user." online_state = online_state.replace("<br/>", ": ") # will make this pretty later data["state"] = text.strip_html(online_state) # work out the average metascore for all games ms = [float(game["metascore"]) for game in games if is_number(game["metascore"])] metascore = float(sum(ms)) / len(ms) if len(ms) > 0 else float('nan') data["average_metascore"] = "{0:.1f}".format(metascore) # work out the totals data["games"] = len(games) total_value = sum([float(game["value"]) for game in games if is_number(game["value"])]) data["value"] = str(int(round(total_value))) # work out the total size total_size = 0.0 for game in games: if not is_number(game["size"]): continue if game["unit"] == "GB": total_size += float(game["size"]) else: total_size += float(game["size"]) / 1024 data["size"] = "{0:.1f}".format(total_size) reply("{name} ({state}) has {games} games with a total value of ${value}" " and a total size of {size}GB! The average metascore for these" " games is {average_metascore}.".format(**data)) if do_refresh: refresh_data(name)
def twitter(inp): ".twitter <user>/<user> <n>/<id>/#<hashtag>/@<user> -- gets last/<n>th "\ "tweet from <user>/gets tweet <id>/gets random tweet with #<hashtag>/"\ "gets replied tweet from @<user>" def add_reply(reply_name, reply_id): if len(history) == history_max_size: history.pop() history.insert(0, (reply_name, reply_id)) def find_reply(reply_name): for name, id in history: if name == reply_name: return id if id != -1 else name if inp[0] == '@': reply_inp = find_reply(inp[1:]) if reply_inp == None: return 'error: no replies to %s found' % inp inp = reply_inp url = 'http://twitter.com' getting_nth = False getting_id = False searching_hashtag = False time = 'status/created_at' text = 'status/text' reply_name = 'status/in_reply_to_screen_name' reply_id = 'status/in_reply_to_status_id' reply_user = '******' if re.match(r'^\d+$', inp): getting_id = True url += '/statuses/show/%s.xml' % inp screen_name = 'user/screen_name' time = 'created_at' text = 'text' reply_name = 'in_reply_to_screen_name' reply_id = 'in_reply_to_status_id' reply_user = '******' elif re.match(r'^\w{1,15}$', inp): url += '/users/show/%s.xml' % inp screen_name = 'screen_name' elif re.match(r'^\w{1,15}\s+\d+$', inp): getting_nth = True name, num = inp.split() if int(num) > 3200: return 'error: only supports up to the 3200th tweet' url += '/statuses/user_timeline/%s.xml?count=1&page=%s' % (name, num) screen_name = 'status/user/screen_name' elif re.match(r'^#\w+$', inp): url = 'http://search.twitter.com/search.atom?q=%23' + inp[1:] searching_hashtag = True else: return 'error: invalid request' try: tweet = http.get_xml(url) except http.HTTPError, e: errors = { 400: 'bad request (ratelimited?)', 401: 'tweet is private', 403: 'tweet is private', 404: 'invalid user/id', 500: 'twitter is broken', 502: 'twitter is down ("getting upgraded")', 503: 'twitter is overloaded (lol, RoR)' } if e.code == 404: return 'error: invalid ' + ['username', 'tweet id'][getting_id] if e.code in errors: return 'error: ' + errors[e.code] return 'error: unknown %s' % e.code
def twitter(inp): "twitter <user>/<user> <n>/<id>/#<hashtag>/@<user> -- Gets last/<n>th " \ "tweet from <user>/gets tweet <id>/Gets random tweet with #<hashtag>/" \ "gets replied tweet from @<user>." def add_reply(reply_name, reply_id): if len(history) == history_max_size: history.pop() history.insert(0, (reply_name, reply_id)) def find_reply(reply_name): for name, id in history: if name == reply_name: return id if id != -1 else name if inp[0] == '@': reply_inp = find_reply(inp[1:]) if reply_inp == None: return 'No replies to %s found.' % inp inp = reply_inp url = 'http://api.twitter.com' getting_nth = False getting_id = False searching_hashtag = False time = 'status/created_at' text = 'status/text' retweeted_text = 'status/retweeted_status/text' retweeted_screen_name = 'status/retweeted_status/user/screen_name' reply_name = 'status/in_reply_to_screen_name' reply_id = 'status/in_reply_to_status_id' reply_user = '******' if re.match(r'^\d+$', inp): getting_id = True url += '/statuses/show/%s.xml' % inp screen_name = 'user/screen_name' time = 'created_at' text = 'text' reply_name = 'in_reply_to_screen_name' reply_id = 'in_reply_to_status_id' reply_user = '******' elif re.match(r'^\w{1,15}$', inp) or re.match(r'^\w{1,15}\s+\d+$', inp): getting_nth = True if inp.find(' ') == -1: name = inp num = 1 else: name, num = inp.split() if int(num) > 3200: return 'error: only supports up to the 3200th tweet' url += ('/1/statuses/user_timeline.xml?include_rts=true&' 'screen_name=%s&count=1&page=%s' % (name, num)) screen_name = 'status/user/screen_name' elif re.match(r'^#\w+$', inp): url = 'http://search.twitter.com/search.atom?q=%23' + inp[1:] searching_hashtag = True else: return 'Error: Invalid request.' try: tweet = http.get_xml(url) except http.HTTPError as e: errors = { 400: 'Bad request (ratelimited?)', 401: 'Tweet is private', 403: 'Tweet is private', 404: 'Invalid user/id', 500: 'Twitter is broken', 502: 'Twitter is down ("getting upgraded")', 503: 'Twitter is overloaded' } if e.code == 404: return 'error: invalid ' + ['username', 'tweet id'][getting_id] if e.code in errors: return 'Error: %s.' % errors[e.code] return 'Unknown Error: %s' % e.code except http.URLError as e: return 'Error: Request timed out.' if searching_hashtag: ns = '{http://www.w3.org/2005/Atom}' tweets = tweet.findall(ns + 'entry/' + ns + 'id') if not tweets: return 'Hashtag not found!' id = random.choice(tweets).text id = id[id.rfind(':') + 1:] return twitter(id) if getting_nth: if tweet.find('status') is None: return "User doesn't have that many tweets!" time = tweet.find(time) if time is None: return "User has no tweets!" reply_name = tweet.find(reply_name).text reply_id = tweet.find(reply_id).text reply_user = tweet.find(reply_user).text if reply_name is not None and (reply_id is not None or reply_user is not None): add_reply(reply_name, reply_id or -1) time_raw = strftime('%Y-%m-%d %H:%M:%S', strptime(time.text, '%a %b %d %H:%M:%S +0000 %Y')) time_nice = timesince(parseDateTime(time_raw), datetime.utcnow()) if tweet.find(retweeted_text) is not None: text = 'RT @%s:' % tweet.find(retweeted_screen_name).text text += unescape_xml(tweet.find(retweeted_text).text.replace('\n', '')) else: text = unescape_xml(tweet.find(text).text.replace('\n', '')) screen_name = tweet.find(screen_name).text return "\x02@%s\x02: %s (%s ago)" % (screen_name, text, time_nice)
def twitter(inp): ".twitter <user>/<user> <n>/<id>/#<hashtag>/@<user> -- Gets last/<n>th "\ "tweet from <user>/gets tweet <id>/Gets random tweet with #<hashtag>/"\ "gets replied tweet from @<user>." def add_reply(reply_name, reply_id): if len(history) == history_max_size: history.pop() history.insert(0, (reply_name, reply_id)) def find_reply(reply_name): for name, id in history: if name == reply_name: return id if id != -1 else name if inp[0] == '@': reply_inp = find_reply(inp[1:]) if reply_inp == None: return 'No replies to %s found.' % inp inp = reply_inp url = 'http://twitter.com' getting_nth = False getting_id = False searching_hashtag = False time = 'status/created_at' text = 'status/text' reply_name = 'status/in_reply_to_screen_name' reply_id = 'status/in_reply_to_status_id' reply_user = '******' if re.match(r'^\d+$', inp): getting_id = True url += '/statuses/show/%s.xml' % inp screen_name = 'user/screen_name' time = 'created_at' text = 'text' reply_name = 'in_reply_to_screen_name' reply_id = 'in_reply_to_status_id' reply_user = '******' elif re.match(r'^\w{1,15}$', inp): url += '/users/show/%s.xml' % inp screen_name = 'screen_name' elif re.match(r'^\w{1,15}\s+\d+$', inp): getting_nth = True name, num = inp.split() if int(num) > 3200: return 'error: only supports up to the 3200th tweet' url += '/statuses/user_timeline/%s.xml?count=1&page=%s' % (name, num) screen_name = 'status/user/screen_name' elif re.match(r'^#\w+$', inp): url = 'http://search.twitter.com/search.atom?q=%23' + inp[1:] searching_hashtag = True else: return 'error: invalid request' try: tweet = http.get_xml(url) except http.HTTPError, e: errors = {400: 'bad request (ratelimited?)', 401: 'tweet is private', 403: 'tweet is private', 404: 'invalid user/id', 500: 'twitter is broken', 502: 'twitter is down ("getting upgraded")', 503: 'twitter is overloaded (lol, RoR)'} if e.code == 404: return 'error: invalid ' + ['username', 'tweet id'][getting_id] if e.code in errors: return 'error: ' + errors[e.code] return 'error: unknown %s' % e.code
def twitter(inp): "twitter <user>/<user> <n>/<id>/#<hashtag>/@<user> -- Gets last/<n>th " \ "tweet from <user>/gets tweet <id>/Gets random tweet with #<hashtag>/" \ "gets replied tweet from @<user>." def add_reply(reply_name, reply_id): if len(history) == history_max_size: history.pop() history.insert(0, (reply_name, reply_id)) def find_reply(reply_name): for name, id in history: if name == reply_name: return id if id != -1 else name if inp[0] == '@': reply_inp = find_reply(inp[1:]) if reply_inp == None: return 'No replies to %s found.' % inp inp = reply_inp url = 'http://api.twitter.com' getting_nth = False getting_id = False searching_hashtag = False time = 'status/created_at' text = 'status/text' retweeted_text = 'status/retweeted_status/text' retweeted_screen_name = 'status/retweeted_status/user/screen_name' reply_name = 'status/in_reply_to_screen_name' reply_id = 'status/in_reply_to_status_id' reply_user = '******' if re.match(r'^\d+$', inp): getting_id = True url += '/statuses/show/%s.xml' % inp screen_name = 'user/screen_name' time = 'created_at' text = 'text' reply_name = 'in_reply_to_screen_name' reply_id = 'in_reply_to_status_id' reply_user = '******' elif re.match(r'^\w{1,15}$', inp) or re.match(r'^\w{1,15}\s+\d+$', inp): getting_nth = True if inp.find(' ') == -1: name = inp num = 1 else: name, num = inp.split() if int(num) > 3200: return 'error: only supports up to the 3200th tweet' url += ('/1/statuses/user_timeline.xml?include_rts=true&' 'screen_name=%s&count=1&page=%s' % (name, num)) screen_name = 'status/user/screen_name' elif re.match(r'^#\w+$', inp): url = 'http://search.twitter.com/search.atom?q=%23' + inp[1:] searching_hashtag = True else: return 'Error: Invalid request.' try: tweet = http.get_xml(url) except http.HTTPError as e: errors = {400: 'Bad request (ratelimited?)', 401: 'Tweet is private', 403: 'Tweet is private', 404: 'Invalid user/id', 500: 'Twitter is broken', 502: 'Twitter is down ("getting upgraded")', 503: 'Twitter is overloaded'} if e.code == 404: return 'error: invalid ' + ['username', 'tweet id'][getting_id] if e.code in errors: return 'Error: %s.' % errors[e.code] return 'Unknown Error: %s' % e.code except http.URLError as e: return 'Error: Request timed out.' if searching_hashtag: ns = '{http://www.w3.org/2005/Atom}' tweets = tweet.findall(ns + 'entry/' + ns + 'id') if not tweets: return 'Hashtag not found!' id = random.choice(tweets).text id = id[id.rfind(':') + 1:] return twitter(id) if getting_nth: if tweet.find('status') is None: return "User doesn't have that many tweets!" time = tweet.find(time) if time is None: return "User has no tweets!" reply_name = tweet.find(reply_name).text reply_id = tweet.find(reply_id).text reply_user = tweet.find(reply_user).text if reply_name is not None and (reply_id is not None or reply_user is not None): add_reply(reply_name, reply_id or -1) time_raw = strftime('%Y-%m-%d %H:%M:%S', strptime(time.text, '%a %b %d %H:%M:%S +0000 %Y')) time_nice = timesince(parseDateTime(time_raw), datetime.utcnow()) if tweet.find(retweeted_text) is not None: text = 'RT @%s:' % tweet.find(retweeted_screen_name).text text += unescape_xml(tweet.find(retweeted_text).text.replace('\n', '')) else: text = unescape_xml(tweet.find(text).text.replace('\n', '')) screen_name = tweet.find(screen_name).text return "\x02@%s\x02: %s (%s ago)" % (screen_name, text, time_nice)
def steamcalc(inp, reply=None): """steamcalc <username> [currency] - Gets value of steam account and total hours played. Uses steamcommunity.com/id/<nickname>. """ # check if the user asked us to force reload force_reload = inp.endswith(" forcereload") if force_reload: name = inp[:-12].strip().lower() else: name = inp.strip() if force_reload: try: reply("Collecting data, this may take a while.") refresh_data(name) request = get_data(name) do_refresh = False except (http.HTTPError, http.URLError): return "Could not get data for this user." else: try: request = get_data(name) do_refresh = True except (http.HTTPError, http.URLError): try: reply("Collecting data, this may take a while.") refresh_data(name) request = get_data(name) do_refresh = False except (http.HTTPError, http.URLError): return "Could not get data for this user." csv_data = io.StringIO( request) # we use StringIO because CSV can't read a string reader = unicode_dictreader(csv_data) # put the games in a list games = [] for row in reader: games.append(row) data = {} # basic information steam_profile = http.get_xml(steam_api_url.format(name)) try: data["name"] = steam_profile.find('steamID').text online_state = steam_profile.find('stateMessage').text except AttributeError: return "Could not get data for this user." online_state = online_state.replace("<br/>", ": ") # will make this pretty later data["state"] = text.strip_html(online_state) # work out the average metascore for all games ms = [ float(game["metascore"]) for game in games if is_number(game["metascore"]) ] metascore = float(sum(ms)) / len(ms) if len(ms) > 0 else float('nan') data["average_metascore"] = "{0:.1f}".format(metascore) # work out the totals data["games"] = len(games) total_value = sum( [float(game["value"]) for game in games if is_number(game["value"])]) data["value"] = str(int(round(total_value))) # work out the total size total_size = 0.0 for game in games: if not is_number(game["size"]): continue if game["unit"] == "GB": total_size += float(game["size"]) else: total_size += float(game["size"]) / 1024 data["size"] = "{0:.1f}".format(total_size) reply("{name} ({state}) has {games} games with a total value of ${value}" " and a total size of {size}GB! The average metascore for these" " games is {average_metascore}.".format(**data)) if do_refresh: refresh_data(name)