def etymology(word): # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc # entries? - http://swhack.com/logs/2006-07-19#T15-05-29 if len(word) > 25: raise ValueError("Word too long: %s[...]" % word[:10]) word = {'axe': 'ax/axe'}.get(word, word) bytes = web.get(etyuri % web.urllib.quote(word)) definitions = r_definition.findall(bytes) if not definitions: return None defn = text(definitions[0]) m = r_sentence.match(defn) if not m: return None sentence = m.group(0) try: sentence = unicode(sentence, 'iso-8859-1') sentence = sentence.encode('utf-8') except: pass maxlength = 275 if len(sentence) > maxlength: sentence = sentence[:maxlength] words = sentence[:-5].split(' ') words.pop() sentence = ' '.join(words) + ' [...]' sentence = '"' + sentence.replace('"', "'") + '"' return sentence + ' - ' + (etyuri % word)
def dict(ircbot, input): if not input.group(2): return ircbot.reply("Nothing to define.") word = input.group(2) word = urllib.quote(word.encode('utf-8')) def trim(thing): if thing.endswith(' '): thing = thing[:-6] return thing.strip(' :.') bytes = web.get(uri % word) results = {} wordkind = None for kind, sense in r_info.findall(bytes): kind, sense = trim(kind), trim(sense) if kind: wordkind = kind elif sense: results.setdefault(wordkind, []).append(sense) result = input.group(2).encode('utf-8') + ' - ' for key in sorted(results.keys()): if results[key]: result += (key or '') + ' 1. ' + results[key][0] if len(results[key]) > 1: result += ', 2. ' + results[key][1] result += '; ' result = result.rstrip('; ') if result.endswith('-') and (len(result) < 30): ircbot.reply('Sorry, no definition found.') else: ircbot.say(result)
def py(ircbot, input): query = input.group(2).encode('utf-8') uri = 'http://tumbolia.appspot.com/py/' answer = web.get(uri + web.urllib.quote(query)) if answer: ircbot.say(answer) else: ircbot.reply('Sorry, no result.')
def search(query): """Search using AjaxSearch, and return its JSON.""" uri = 'http://ajax.googleapis.com/ajax/services/search/web' args = '?v=1.0&safe=off&q=' + web.urllib.quote(query.encode('utf-8')) handler = web.urllib._urlopener web.urllib._urlopener = Grab() bytes = web.get(uri + args) web.urllib._urlopener = handler return web.json(bytes)
def detect(text): uri = 'http://ajax.googleapis.com/ajax/services/language/detect' q = urllib.quote(text) bytes = web.get(uri + '?q=' + q + '&v=1.0') result = web.json(bytes) try: return result['responseData']['language'] except Exception: return None
def wa(ircbot, input): if not input.group(2): return ircbot.reply("No search term.") query = input.group(2).encode('utf-8') uri = 'http://tumbolia.appspot.com/wa/' answer = web.get(uri + web.urllib.quote(query)) if answer: ircbot.say(answer) else: ircbot.reply('Sorry, no result.')
def translate(text, input, output): uri = 'http://ajax.googleapis.com/ajax/services/language/translate' q = urllib.quote(text) pair = input + '%7C' + output bytes = web.get(uri + '?q=' + q + '&v=1.0&langpair=' + pair) result = web.json(bytes) try: return result['responseData']['translatedText'].encode('cp1252') except Exception: return None
def mappings(uri): result = {} bytes = web.get(uri) for item in r_item.findall(bytes): item = r_tag.sub('', item).strip(' \t\r\n') if not ' ' in item: continue command, template = item.split(' ', 1) if not command.isalnum(): continue if not template.startswith('http://'): continue result[command] = template.replace('&', '&') return result
def service(ircbot, input, command, args): t = o.services[command] template = t.replace('${args}', urllib.quote(args.encode('utf-8'), '')) template = template.replace('${nick}', urllib.quote(input.nick, '')) uri = template.replace('${sender}', urllib.quote(input.sender, '')) info = web.head(uri) if isinstance(info, list): info = info[0] if not 'text/plain' in info.get('content-type', '').lower(): return ircbot.reply("Sorry, the service didn't respond in plain text.") bytes = web.get(uri) lines = bytes.splitlines() if not lines: return ircbot.reply("Sorry, the service didn't respond any output.") ircbot.say(lines[0][:350])
def local(icao, hour, minute): uri = ('http://www.flightstats.com/' + 'go/Airport/airportDetails.do?airportCode=%s') try: bytes = web.get(uri % icao) except AttributeError: raise GrumbleError('A WEBSITE HAS GONE DOWN WTF STUPID WEB') m = re.compile(r'(?i)([+-]\d+):00 from').search(bytes) if m: offset = m.group(1) lhour = int(hour) + int(offset) lhour = lhour % 24 return (str(lhour) + ':' + str(minute) + ', ' + str(hour) + str(minute) + 'Z') # return (str(lhour) + ':' + str(minute) + ' (' + str(hour) + # ':' + str(minute) + 'Z)') return str(hour) + ':' + str(minute) + 'Z'
def calc(ircbot, input): """Use the Frink online calculator.""" q = input.group(2) if not q: return ircbot.say('0?') query = q[:] for a, b in subs: query = re.sub(a, b, query) query = query.rstrip(' \t') precision = 5 if query[-3:] in ('GBP', 'USD', 'EUR', 'NOK'): precision = 2 query = web.urllib.quote(query.encode('utf-8')) uri = 'http://futureboy.us/fsp/frink.fsp?fromVal=' bytes = web.get(uri + query) m = r_result.search(bytes) if m: result = m.group(1) result = r_tag.sub('', result) # strip span.warning tags result = result.replace('>', '>') result = result.replace('(undefined symbol)', '(?) ') if '.' in result: try: result = str(round(float(result), precision)) except ValueError: pass if not result.strip(): result = '?' elif ' in ' in q: result += ' ' + q.split(' in ', 1)[1] ircbot.say(q + ' = ' + result[:350]) else: ircbot.reply("Sorry, can't calculate that.") ircbot.say('Note that .calc is deprecated, consider using .c')
def c(ircbot, input): """Google calculator.""" if not input.group(2): return ircbot.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 = 'http://www.google.com/ig/calculator?q=' bytes = web.get(uri + web.urllib.quote(q)) parts = bytes.split('",') answer = [p for p in parts if p.startswith('rhs: "')][0][6:] if answer: answer = answer.decode('unicode-escape') answer = ''.join(chr(ord(c)) for c in answer) answer = answer.decode('utf-8') answer = answer.replace(u'\xc2\xa0', ',') answer = answer.replace('<sup>', '^(') answer = answer.replace('</sup>', ')') answer = web.decode(answer) ircbot.say(answer) else: ircbot.say('Sorry, no result.')
def bing(ircbot, input): """Queries Bing for the specified input.""" query = input.group(2) if query.startswith(':'): lang, query = query.split(' ', 1) lang = lang[1:] else: lang = 'en-GB' if not query: return ircbot.reply('.bing what?') query = web.urllib.quote(query.encode('utf-8')) base = 'http://www.bing.com/search?mkt=%s&q=' % lang bytes = web.get(base + query) m = r_bing.search(bytes) if m: uri = m.group(1) ircbot.reply(uri) if not hasattr(ircbot.bot, 'last_seen_uri'): ircbot.bot.last_seen_uri = {} ircbot.bot.last_seen_uri[input.sender] = uri else: ircbot.reply("No results found for '%s'." % query)
def wiktionary(word): uri = 'http://en.wiktionary.org/w/index.php?title=%s&printable=yes' bytes = web.get(uri % web.urllib.quote(word.encode('utf-8'))) bytes = re.compile(r'(?ims)<ul>.*?</ul>').sub('', bytes) mode = None etymology = None definitions = {} for line in bytes.splitlines(): if 'id="Etymology"' in line: mode = 'etymology' elif 'id="Noun"' in line: mode = 'noun' elif 'id="Verb"' in line: mode = 'verb' elif 'id="Adjective"' in line: mode = 'adjective' elif 'id="Adverb"' in line: mode = 'adverb' elif 'id="Interjection"' in line: mode = 'interjection' elif 'id="Particle"' in line: mode = 'particle' elif 'id="Preposition"' in line: mode = 'preposition' elif 'id="' in line: mode = None elif (mode == 'etmyology') and ('<p>' in line): etymology = text(line) elif (mode is not None) and ('<li>' in line): definitions.setdefault(mode, []).append(text(line)) if '<hr' in line: break return etymology, definitions
def wikipedia(term, language='en', last=False): global wikiuri if not '%' in term: if isinstance(term, unicode): t = term.encode('utf-8') else: t = term q = urllib.quote(t) u = wikiuri % (language, q) bytes = web.get(u) else: bytes = web.get(wikiuri % (language, term)) bytes = r_tr.sub('', bytes) if not last: r = r_redirect.search(bytes[:4096]) if r: term = urllib.unquote(r.group(1)) return wikipedia(term, language=language, last=True) paragraphs = r_paragraph.findall(bytes) if not paragraphs: if not last: term = search(term) return wikipedia(term, language=language, last=True) return None # Pre-process paragraphs = [ para for para in paragraphs if (para and 'technical limitations' not in para and 'window.showTocToggle' not in para and 'Deletion_policy' not in para and 'Template:AfD_footer' not in para and not (para.startswith('<p><i>') and para.endswith('</i></p>')) and not 'disambiguation)"' in para) and not '(images and media)' in para and not 'This article contains a' in para and not 'id="coordinates"' in para and not 'class="thumb' in para ] # and not 'style="display:none"' in para] for i, para in enumerate(paragraphs): para = para.replace('<sup>', '|') para = para.replace('</sup>', '|') paragraphs[i] = text(para).strip() # Post-process paragraphs = [ para for para in paragraphs if (para and not (para.endswith(':') and len(para) < 150)) ] para = text(paragraphs[0]) m = r_sentence.match(para) if not m: if not last: term = search(term) return wikipedia(term, language=language, last=True) return None sentence = m.group(0) maxlength = 275 if len(sentence) > maxlength: sentence = sentence[:maxlength] words = sentence[:-5].split(' ') words.pop() sentence = ' '.join(words) + ' [...]' if (('using the Article Wizard if you wish' in sentence) or ('or add a request for it' in sentence) or ('in existing articles' in sentence)): if not last: term = search(term) return wikipedia(term, language=language, last=True) return None sentence = '"' + sentence.replace('"', "'") + '"' sentence = sentence.decode('utf-8').encode('utf-8') wikiuri = wikiuri.decode('utf-8').encode('utf-8') term = term.decode('utf-8').encode('utf-8') return sentence + ' - ' + (wikiuri % (language, term))
def f_weather(self, origin, match, args): """.weather <ICAO> - Show the weather at airport with the code <ICAO>.""" if origin.sender == '#talis': if args[0].startswith('.weather '): return icao_code = match.group(2) if not icao_code: return self.msg(origin.sender, 'Try .weather London, for example?') icao_code = code(self, icao_code) if not icao_code: self.msg(origin.sender, 'No ICAO code found, sorry') return uri = 'http://weather.noaa.gov/pub/data/observations/metar/stations/%s.TXT' try: bytes = web.get(uri % icao_code) except AttributeError: raise GrumbleError('OH CRAP NOAA HAS GONE DOWN THE WEB IS BROKEN') if 'Not Found' in bytes: self.msg(origin.sender, icao_code+': no such ICAO code, or no NOAA data') return metar = bytes.splitlines().pop() metar = metar.split(' ') if len(metar[0]) == 4: metar = metar[1:] if metar[0].endswith('Z'): time = metar[0] metar = metar[1:] else: time = None if metar[0] == 'AUTO': metar = metar[1:] if metar[0] == 'VCU': self.msg(origin.sender, icao_code + ': no data provided') return if metar[0].endswith('KT'): wind = metar[0] metar = metar[1:] else: wind = None if ('V' in metar[0]) and (metar[0] != 'CAVOK'): metar = metar[1:] if ((len(metar[0]) == 4) or metar[0].endswith('SM')): visibility = metar[0] metar = metar[1:] else: visibility = None while metar[0].startswith('R') and (metar[0].endswith('L') or 'L/' in metar[0]): metar = metar[1:] if len(metar[0]) == 6 and (metar[0].endswith('N') or metar[0].endswith('E') or metar[0].endswith('S') or metar[0].endswith('W')): metar = metar[1:] # 7000SE? cond = [] while (((len(metar[0]) < 5) or metar[0].startswith('+') or metar[0].startswith('-')) and (not (metar[0].startswith('VV') or metar[0].startswith('SKC') or metar[0].startswith('CLR') or metar[0].startswith('FEW') or metar[0].startswith('SCT') or metar[0].startswith('BKN') or metar[0].startswith('OVC')))): cond.append(metar[0]) metar = metar[1:] while '/P' in metar[0]: metar = metar[1:] if not metar: self.msg(origin.sender, icao_code + ': no data provided') return cover = [] while (metar[0].startswith('VV') or metar[0].startswith('SKC') or metar[0].startswith('CLR') or metar[0].startswith('FEW') or metar[0].startswith('SCT') or metar[0].startswith('BKN') or metar[0].startswith('OVC')): cover.append(metar[0]) metar = metar[1:] if not metar: self.msg(origin.sender, icao_code + ': no data provided') return if metar[0] == 'CAVOK': cover.append('CLR') metar = metar[1:] if metar[0] == 'PRFG': cover.append('CLR') # @@? metar = metar[1:] if metar[0] == 'NSC': cover.append('CLR') metar = metar[1:] if ('/' in metar[0]) or (len(metar[0]) == 5 and metar[0][2] == '.'): temp = metar[0] metar = metar[1:] else: temp = None if metar[0].startswith('QFE'): metar = metar[1:] if metar[0].startswith('Q') or metar[0].startswith('A'): pressure = metar[0] metar = metar[1:] else: pressure = None if time: hour = time[2:4] minute = time[4:6] time = local(icao_code, hour, minute) else: time = '(time unknown)' if wind: speed = int(wind[3:5]) if speed < 1: description = 'Calm' elif speed < 4: description = 'Light air' elif speed < 7: description = 'Light breeze' elif speed < 11: description = 'Gentle breeze' elif speed < 16: description = 'Moderate breeze' elif speed < 22: description = 'Fresh breeze' elif speed < 28: description = 'Strong breeze' elif speed < 34: description = 'Near gale' elif speed < 41: description = 'Gale' elif speed < 48: description = 'Strong gale' elif speed < 56: description = 'Storm' elif speed < 64: description = 'Violent storm' else: description = 'Hurricane' degrees = wind[0:3] if degrees == 'VRB': degrees = u'\u21BB'.encode('utf-8') elif (degrees <= 22.5) or (degrees > 337.5): degrees = u'\u2191'.encode('utf-8') elif (degrees > 22.5) and (degrees <= 67.5): degrees = u'\u2197'.encode('utf-8') elif (degrees > 67.5) and (degrees <= 112.5): degrees = u'\u2192'.encode('utf-8') elif (degrees > 112.5) and (degrees <= 157.5): degrees = u'\u2198'.encode('utf-8') elif (degrees > 157.5) and (degrees <= 202.5): degrees = u'\u2193'.encode('utf-8') elif (degrees > 202.5) and (degrees <= 247.5): degrees = u'\u2199'.encode('utf-8') elif (degrees > 247.5) and (degrees <= 292.5): degrees = u'\u2190'.encode('utf-8') elif (degrees > 292.5) and (degrees <= 337.5): degrees = u'\u2196'.encode('utf-8') if not icao_code.startswith('EN') and not icao_code.startswith('ED'): wind = '%s %skt (%s)' % (description, speed, degrees) elif icao_code.startswith('ED'): kmh = int(round(speed * 1.852, 0)) wind = '%s %skm/h (%skt) (%s)' % (description, kmh, speed, degrees) elif icao_code.startswith('EN'): ms = int(round(speed * 0.514444444, 0)) wind = '%s %sm/s (%skt) (%s)' % (description, ms, speed, degrees) else: wind = '(wind unknown)' if visibility: visibility = visibility + 'm' else: visibility = '(visibility unknown)' if cover: level = None for c in cover: if c.startswith('OVC') or c.startswith('VV'): if (level is None) or (level < 8): level = 8 elif c.startswith('BKN'): if (level is None) or (level < 5): level = 5 elif c.startswith('SCT'): if (level is None) or (level < 3): level = 3 elif c.startswith('FEW'): if (level is None) or (level < 1): level = 1 elif c.startswith('SKC') or c.startswith('CLR'): if level is None: level = 0 if level == 8: cover = u'Overcast \u2601'.encode('utf-8') elif level == 5: cover = 'Cloudy' elif level == 3: cover = 'Scattered' elif (level == 1) or (level == 0): cover = u'Clear \u263C'.encode('utf-8') else: cover = 'Cover Unknown' else: cover = 'Cover Unknown' if temp: if '/' in temp: temp = temp.split('/')[0] else: temp = temp.split('.')[0] if temp.startswith('M'): temp = '-' + temp[1:] try: temp = int(temp) except ValueError: temp = '?' else: temp = '?' if pressure: if pressure.startswith('Q'): pressure = pressure.lstrip('Q') if pressure != 'NIL': pressure = str(int(pressure)) + 'mb' else: pressure = '?mb' elif pressure.startswith('A'): pressure = pressure.lstrip('A') if pressure != 'NIL': inches = pressure[:2] + '.' + pressure[2:] mb = int(float(inches) * 33.7685) pressure = '%sin (%smb)' % (inches, mb) else: pressure = '?mb' if isinstance(temp, int): f = round((temp * 1.8) + 32, 2) temp = u'%s\u2109 (%s\u2103)'.encode('utf-8') % (f, temp) else: pressure = '?mb' if isinstance(temp, int): temp = u'%s\u2103'.encode('utf-8') % temp if cond: conds = cond cond = '' intensities = { '-': 'Light', '+': 'Heavy' } descriptors = { 'MI': 'Shallow', 'PR': 'Partial', 'BC': 'Patches', 'DR': 'Drifting', 'BL': 'Blowing', 'SH': 'Showers of', 'TS': 'Thundery', 'FZ': 'Freezing', 'VC': 'In the vicinity:' } phenomena = { 'DZ': 'Drizzle', 'RA': 'Rain', 'SN': 'Snow', 'SG': 'Snow Grains', 'IC': 'Ice Crystals', 'PL': 'Ice Pellets', 'GR': 'Hail', 'GS': 'Small Hail', 'UP': 'Unknown Precipitation', 'BR': 'Mist', 'FG': 'Fog', 'FU': 'Smoke', 'VA': 'Volcanic Ash', 'DU': 'Dust', 'SA': 'Sand', 'HZ': 'Haze', 'PY': 'Spray', 'PO': 'Whirls', 'SQ': 'Squalls', 'FC': 'Tornado', 'SS': 'Sandstorm', 'DS': 'Duststorm', # ? Cf. http://swhack.com/logs/2007-10-05#T07-58-56 'TS': 'Thunderstorm', 'SH': 'Showers' } for c in conds: if c.endswith('//'): if cond: cond += ', ' cond += 'Some Precipitation' elif len(c) == 5: intensity = intensities[c[0]] descriptor = descriptors[c[1:3]] phenomenon = phenomena.get(c[3:], c[3:]) if cond: cond += ', ' cond += intensity + ' ' + descriptor + ' ' + phenomenon elif len(c) == 4: descriptor = descriptors.get(c[:2], c[:2]) phenomenon = phenomena.get(c[2:], c[2:]) if cond: cond += ', ' cond += descriptor + ' ' + phenomenon elif len(c) == 3: intensity = intensities.get(c[0], c[0]) phenomenon = phenomena.get(c[1:], c[1:]) if cond: cond += ', ' cond += intensity + ' ' + phenomenon elif len(c) == 2: phenomenon = phenomena.get(c, c) if cond: cond += ', ' cond += phenomenon if not cond: format = u'%s, %s, %s, %s - %s %s' args = (cover, temp, pressure, wind, str(icao_code), time) else: format = u'%s, %s, %s, %s, %s - %s, %s' args = (cover, temp, pressure, cond, wind, str(icao_code), time) self.msg(origin.sender, format.encode('utf-8') % args)
def f_weather(self, origin, match, args): """.weather <ICAO> - Show the weather at airport with the code <ICAO>.""" if origin.sender == '#talis': if args[0].startswith('.weather '): return icao_code = match.group(2) if not icao_code: return self.msg(origin.sender, 'Try .weather London, for example?') icao_code = code(self, icao_code) if not icao_code: self.msg(origin.sender, 'No ICAO code found, sorry') return uri = 'http://weather.noaa.gov/pub/data/observations/metar/stations/%s.TXT' try: bytes = web.get(uri % icao_code) except AttributeError: raise GrumbleError('OH CRAP NOAA HAS GONE DOWN THE WEB IS BROKEN') if 'Not Found' in bytes: self.msg(origin.sender, icao_code + ': no such ICAO code, or no NOAA data') return metar = bytes.splitlines().pop() metar = metar.split(' ') if len(metar[0]) == 4: metar = metar[1:] if metar[0].endswith('Z'): time = metar[0] metar = metar[1:] else: time = None if metar[0] == 'AUTO': metar = metar[1:] if metar[0] == 'VCU': self.msg(origin.sender, icao_code + ': no data provided') return if metar[0].endswith('KT'): wind = metar[0] metar = metar[1:] else: wind = None if ('V' in metar[0]) and (metar[0] != 'CAVOK'): metar = metar[1:] if ((len(metar[0]) == 4) or metar[0].endswith('SM')): visibility = metar[0] metar = metar[1:] else: visibility = None while metar[0].startswith('R') and (metar[0].endswith('L') or 'L/' in metar[0]): metar = metar[1:] if len(metar[0]) == 6 and (metar[0].endswith('N') or metar[0].endswith('E') or metar[0].endswith('S') or metar[0].endswith('W')): metar = metar[1:] # 7000SE? cond = [] while (((len(metar[0]) < 5) or metar[0].startswith('+') or metar[0].startswith('-')) and (not (metar[0].startswith('VV') or metar[0].startswith('SKC') or metar[0].startswith('CLR') or metar[0].startswith('FEW') or metar[0].startswith('SCT') or metar[0].startswith('BKN') or metar[0].startswith('OVC')))): cond.append(metar[0]) metar = metar[1:] while '/P' in metar[0]: metar = metar[1:] if not metar: self.msg(origin.sender, icao_code + ': no data provided') return cover = [] while (metar[0].startswith('VV') or metar[0].startswith('SKC') or metar[0].startswith('CLR') or metar[0].startswith('FEW') or metar[0].startswith('SCT') or metar[0].startswith('BKN') or metar[0].startswith('OVC')): cover.append(metar[0]) metar = metar[1:] if not metar: self.msg(origin.sender, icao_code + ': no data provided') return if metar[0] == 'CAVOK': cover.append('CLR') metar = metar[1:] if metar[0] == 'PRFG': cover.append('CLR') # @@? metar = metar[1:] if metar[0] == 'NSC': cover.append('CLR') metar = metar[1:] if ('/' in metar[0]) or (len(metar[0]) == 5 and metar[0][2] == '.'): temp = metar[0] metar = metar[1:] else: temp = None if metar[0].startswith('QFE'): metar = metar[1:] if metar[0].startswith('Q') or metar[0].startswith('A'): pressure = metar[0] metar = metar[1:] else: pressure = None if time: hour = time[2:4] minute = time[4:6] time = local(icao_code, hour, minute) else: time = '(time unknown)' if wind: speed = int(wind[3:5]) if speed < 1: description = 'Calm' elif speed < 4: description = 'Light air' elif speed < 7: description = 'Light breeze' elif speed < 11: description = 'Gentle breeze' elif speed < 16: description = 'Moderate breeze' elif speed < 22: description = 'Fresh breeze' elif speed < 28: description = 'Strong breeze' elif speed < 34: description = 'Near gale' elif speed < 41: description = 'Gale' elif speed < 48: description = 'Strong gale' elif speed < 56: description = 'Storm' elif speed < 64: description = 'Violent storm' else: description = 'Hurricane' degrees = wind[0:3] if degrees == 'VRB': degrees = u'\u21BB'.encode('utf-8') elif (degrees <= 22.5) or (degrees > 337.5): degrees = u'\u2191'.encode('utf-8') elif (degrees > 22.5) and (degrees <= 67.5): degrees = u'\u2197'.encode('utf-8') elif (degrees > 67.5) and (degrees <= 112.5): degrees = u'\u2192'.encode('utf-8') elif (degrees > 112.5) and (degrees <= 157.5): degrees = u'\u2198'.encode('utf-8') elif (degrees > 157.5) and (degrees <= 202.5): degrees = u'\u2193'.encode('utf-8') elif (degrees > 202.5) and (degrees <= 247.5): degrees = u'\u2199'.encode('utf-8') elif (degrees > 247.5) and (degrees <= 292.5): degrees = u'\u2190'.encode('utf-8') elif (degrees > 292.5) and (degrees <= 337.5): degrees = u'\u2196'.encode('utf-8') if not icao_code.startswith('EN') and not icao_code.startswith('ED'): wind = '%s %skt (%s)' % (description, speed, degrees) elif icao_code.startswith('ED'): kmh = int(round(speed * 1.852, 0)) wind = '%s %skm/h (%skt) (%s)' % (description, kmh, speed, degrees) elif icao_code.startswith('EN'): ms = int(round(speed * 0.514444444, 0)) wind = '%s %sm/s (%skt) (%s)' % (description, ms, speed, degrees) else: wind = '(wind unknown)' if visibility: visibility = visibility + 'm' else: visibility = '(visibility unknown)' if cover: level = None for c in cover: if c.startswith('OVC') or c.startswith('VV'): if (level is None) or (level < 8): level = 8 elif c.startswith('BKN'): if (level is None) or (level < 5): level = 5 elif c.startswith('SCT'): if (level is None) or (level < 3): level = 3 elif c.startswith('FEW'): if (level is None) or (level < 1): level = 1 elif c.startswith('SKC') or c.startswith('CLR'): if level is None: level = 0 if level == 8: cover = u'Overcast \u2601'.encode('utf-8') elif level == 5: cover = 'Cloudy' elif level == 3: cover = 'Scattered' elif (level == 1) or (level == 0): cover = u'Clear \u263C'.encode('utf-8') else: cover = 'Cover Unknown' else: cover = 'Cover Unknown' if temp: if '/' in temp: temp = temp.split('/')[0] else: temp = temp.split('.')[0] if temp.startswith('M'): temp = '-' + temp[1:] try: temp = int(temp) except ValueError: temp = '?' else: temp = '?' if pressure: if pressure.startswith('Q'): pressure = pressure.lstrip('Q') if pressure != 'NIL': pressure = str(int(pressure)) + 'mb' else: pressure = '?mb' elif pressure.startswith('A'): pressure = pressure.lstrip('A') if pressure != 'NIL': inches = pressure[:2] + '.' + pressure[2:] mb = int(float(inches) * 33.7685) pressure = '%sin (%smb)' % (inches, mb) else: pressure = '?mb' if isinstance(temp, int): f = round((temp * 1.8) + 32, 2) temp = u'%s\u2109 (%s\u2103)'.encode('utf-8') % (f, temp) else: pressure = '?mb' if isinstance(temp, int): temp = u'%s\u2103'.encode('utf-8') % temp if cond: conds = cond cond = '' intensities = {'-': 'Light', '+': 'Heavy'} descriptors = { 'MI': 'Shallow', 'PR': 'Partial', 'BC': 'Patches', 'DR': 'Drifting', 'BL': 'Blowing', 'SH': 'Showers of', 'TS': 'Thundery', 'FZ': 'Freezing', 'VC': 'In the vicinity:' } phenomena = { 'DZ': 'Drizzle', 'RA': 'Rain', 'SN': 'Snow', 'SG': 'Snow Grains', 'IC': 'Ice Crystals', 'PL': 'Ice Pellets', 'GR': 'Hail', 'GS': 'Small Hail', 'UP': 'Unknown Precipitation', 'BR': 'Mist', 'FG': 'Fog', 'FU': 'Smoke', 'VA': 'Volcanic Ash', 'DU': 'Dust', 'SA': 'Sand', 'HZ': 'Haze', 'PY': 'Spray', 'PO': 'Whirls', 'SQ': 'Squalls', 'FC': 'Tornado', 'SS': 'Sandstorm', 'DS': 'Duststorm', # ? Cf. http://swhack.com/logs/2007-10-05#T07-58-56 'TS': 'Thunderstorm', 'SH': 'Showers' } for c in conds: if c.endswith('//'): if cond: cond += ', ' cond += 'Some Precipitation' elif len(c) == 5: intensity = intensities[c[0]] descriptor = descriptors[c[1:3]] phenomenon = phenomena.get(c[3:], c[3:]) if cond: cond += ', ' cond += intensity + ' ' + descriptor + ' ' + phenomenon elif len(c) == 4: descriptor = descriptors.get(c[:2], c[:2]) phenomenon = phenomena.get(c[2:], c[2:]) if cond: cond += ', ' cond += descriptor + ' ' + phenomenon elif len(c) == 3: intensity = intensities.get(c[0], c[0]) phenomenon = phenomena.get(c[1:], c[1:]) if cond: cond += ', ' cond += intensity + ' ' + phenomenon elif len(c) == 2: phenomenon = phenomena.get(c, c) if cond: cond += ', ' cond += phenomenon if not cond: format = u'%s, %s, %s, %s - %s %s' args = (cover, temp, pressure, wind, str(icao_code), time) else: format = u'%s, %s, %s, %s, %s - %s, %s' args = (cover, temp, pressure, cond, wind, str(icao_code), time) self.msg(origin.sender, format.encode('utf-8') % args)
def wikipedia(term, language='en', last=False): global wikiuri if not '%' in term: if isinstance(term, unicode): t = term.encode('utf-8') else: t = term q = urllib.quote(t) u = wikiuri % (language, q) bytes = web.get(u) else: bytes = web.get(wikiuri % (language, term)) bytes = r_tr.sub('', bytes) if not last: r = r_redirect.search(bytes[:4096]) if r: term = urllib.unquote(r.group(1)) return wikipedia(term, language=language, last=True) paragraphs = r_paragraph.findall(bytes) if not paragraphs: if not last: term = search(term) return wikipedia(term, language=language, last=True) return None # Pre-process paragraphs = [para for para in paragraphs if (para and 'technical limitations' not in para and 'window.showTocToggle' not in para and 'Deletion_policy' not in para and 'Template:AfD_footer' not in para and not (para.startswith('<p><i>') and para.endswith('</i></p>')) and not 'disambiguation)"' in para) and not '(images and media)' in para and not 'This article contains a' in para and not 'id="coordinates"' in para and not 'class="thumb' in para] # and not 'style="display:none"' in para] for i, para in enumerate(paragraphs): para = para.replace('<sup>', '|') para = para.replace('</sup>', '|') paragraphs[i] = text(para).strip() # Post-process paragraphs = [para for para in paragraphs if (para and not (para.endswith(':') and len(para) < 150))] para = text(paragraphs[0]) m = r_sentence.match(para) if not m: if not last: term = search(term) return wikipedia(term, language=language, last=True) return None sentence = m.group(0) maxlength = 275 if len(sentence) > maxlength: sentence = sentence[:maxlength] words = sentence[:-5].split(' ') words.pop() sentence = ' '.join(words) + ' [...]' if (('using the Article Wizard if you wish' in sentence) or ('or add a request for it' in sentence) or ('in existing articles' in sentence)): if not last: term = search(term) return wikipedia(term, language=language, last=True) return None sentence = '"' + sentence.replace('"', "'") + '"' sentence = sentence.decode('utf-8').encode('utf-8') wikiuri = wikiuri.decode('utf-8').encode('utf-8') term = term.decode('utf-8').encode('utf-8') return sentence + ' - ' + (wikiuri % (language, term))