def distance(self, event, unit, ignore, src, dst): unit_names = self.unit_names if unit and unit not in self.unit_names: event.addresponse(u"I don't know the unit '%(badunit)s'. I know about: %(knownunits)s", { 'badunit': unit, 'knownunits': human_join(u"%s (%s)" % (unit, self.unit_names[unit]) for unit in self.unit_names), }) return if unit: unit_names = [unit] srcp, dstp = self.get_place(src), self.get_place(dst) if not srcp or not dstp: event.addresponse(u"I don't know of anywhere called %s", (u" or ".join("'%s'" % place[0] for place in ((src, srcp), (dst, dstp)) if not place[1]))) return dist = acos(cos(srcp['lng']) * cos(dstp['lng']) * cos(srcp['lat']) * cos(dstp['lat']) + cos(srcp['lat']) * sin(srcp['lng']) * cos(dstp['lat']) * sin(dstp['lng']) + sin(srcp['lat'])*sin(dstp['lat'])) event.addresponse(u"Approximate distance, as the bot flies, between %(srcname)s and %(dstname)s is: %(distance)s", { 'srcname': srcp['name'], 'dstname': dstp['name'], 'distance': human_join([ u"%.02f %s" % (self.radius_values[unit]*dist, self.unit_names[unit]) for unit in unit_names], conjunction=u'or'), })
def __unicode__(self): msgs = [] if self.definition(): msgs = [u'it means %s' % self.definition()] msgs += self.variant() prons = [] for reading, lang in ((self.pinyin, 'pinyin'), (self.korean, 'Korean'), (self.japanese_on, 'Japanese on'), (self.japanese_kun, 'Japanese kun')): readings = reading() if readings: prons.append(u'%(readings)s (%(lang)s)' % {'readings': human_join(readings, conjunction=u'or'), 'lang': lang}) if prons: msgs.append(u'it is pronounced ' + human_join(prons, conjunction=u'or')) msg = u'; '.join(msgs) if msg: msg = msg[0].upper() + msg[1:] return msg
def define(self, event, word, dictionary): connection = Connection(self.server, self.port) dictionary = dictionary is None and '*' or dictionary.lower() dictionaries = connection.getdbdescs().keys() if dictionary != '*' and dictionary not in dictionaries: event.addresponse( u"I'm afraid I don't have a dictionary of that name. I know about: %s", human_join(sorted(dictionaries))) return definitions = connection.define(dictionary, word.encode('utf-8')) if definitions: event.addresponse(u', '.join(d.getdefstr() for d in definitions)) else: suggestions = connection.match(dictionary, 'lev', word.encode('utf-8')) if suggestions: event.addresponse( u"I don't know about %(word)s. Maybe you meant %(suggestions)s?", { 'word': word, 'suggestions': human_join( self.reduce_suggestions(suggestions), conjunction=u'or'), }) else: event.addresponse(u"I don't have a definition for that. Is it even a word?")
def handle_spell(self, event, word, strategy): connection = Connection(self.server, self.port) word = word.encode('utf-8') strategies = connection.getstratdescs().keys() if connection.match('*', 'exact', word): event.addresponse(choice(( u'That seems correct. Carry on', u'Looks good to me', u"Yup, that's a word all right", u'Yes, you *can* spell', ))) return strategy = strategy is None and 'lev' or strategy.lower() if strategy not in strategies: event.addresponse( u"I'm afraid I don't know about such a strategy. I know about: %s", human_join(sorted(strategies))) suggestions = connection.match('*', strategy, word) if suggestions: event.addresponse(u'Suggestions: %s', human_join( self.reduce_suggestions(suggestions), conjunction=u'or')) else: event.addresponse(u"That doesn't seem correct, but I can't find anything to suggest")
def endgame(self, event): """Check if the game is over. If the game is over, announce the winners and return True. Otherwise return False. """ if 2 * len(self.wolves) >= len(self.roles): # werewolves win event.addresponse(u'The werewolves devour the remaining ' u'villagers and win. OM NOM NOM.\n' u'The winning werewolves were: %s', human_join(self.wolves), conflate=False) elif not self.wolves: # villagers win event.addresponse(u'The villagers have defeated the werewolves. ' u'Vigilantism FTW.\n' u'The surviving villagers were: %s', human_join(self.roles), conflate=False) else: return False self.state = None werewolf_games.remove(self) return True
def display_movie(self, movie): desc = u"%s: %s." % (movie.movieID, movie["long imdb title"]) if len(movie.get("director", ())) > 0: desc += u" Dir: %s." % (human_join(x["name"] for x in movie["director"])) if len(movie.get("cast", ())) > 0: desc += u" Starring: %s." % (human_join(x["name"] for x in movie["cast"][:3])) if movie.has_key("rating"): desc += u" Rated: %.1f " % movie["rating"] desc += human_join(movie.get("genres", ())) desc += u" Plot: %s" % movie.get("plot outline", u"Unknown") return desc
def display_episode(self, episode): desc = u"%s: %s s%02ie%02i %s(%s)." % ( episode.movieID, episode["series title"], episode["season"], episode["episode"], episode["title"], episode["year"]) if len(episode.get("director", ())) > 0: desc += u" Dir: %s." % (human_join(x["name"] for x in episode["director"])) if len(episode.get("cast", ())) > 0: desc += u" Starring: %s." % (human_join(x["name"] for x in episode["cast"][:3])) if episode.has_key("rating"): desc += u" Rated: %.1f " % episode["rating"] desc += human_join(episode.get("genres", ())) desc += u" Plot: %s" % episode.get("plot outline", u"Unknown") return desc
def search(self, event, term): terms = re.split(r'(?u)[\s/?]', term) result = json_webservice( u'http://debtags.debian.net/dde/q/axi/cquery/%s' % u'/'.join(terms), {'t': 'json'}) result = result['r'] if not result['pkgs']: event.addresponse(u"Sorry, I couldn't find anything relevant. " u"Try being less specific?") return event.addresponse(u"Packages: %(packages)s. " u"Not there? Try these terms: %(suggested)s", { 'packages': human_join(pkg[1] for pkg in result['pkgs']), 'suggested': human_join(result['sugg']), })
def playing(self, event, stream): if not event.get('addressed', False): return if len(self.streams) == 0: event.addresponse(u"Sorry, I don't know about any streams") return elif stream is None and len(self.streams) == 1: stream = self.streams.keys()[0] elif stream is not None and stream not in self.streams: for name in self.streams.iterkeys(): if name.lower() == stream.lower(): stream = name break else: stream = None if stream is None: event.addresponse( u'Sorry, I only know about the following streams, ' u'please choose one: %s', human_join(self.streams.keys())) return try: status = self.scrape_status(stream) event.addresponse(u'Currently Playing on %(stream)s: ' u'%(song)s - %(description)s (Listeners: %(listeners)s)', { 'stream': stream, 'song': status['Current Song'], 'description': status['Stream Description'], 'listeners': status['Current Listeners'], }) except HTTPError: event.addresponse(u'The stream must be down, back to the MP3 collection for you')
def search(self, event, term, distro, arch): distro = distro and distro.lower() or self.distro arch = arch and arch.lower() or self.arch distro = distro + u'-' + arch if distro == u'all-all': distro = u'all' result = json_webservice( u'http://dde.debian.net/dde/q/aptfile/byfile/%s/%s' % (distro, quote(term)), {'t': 'json'}) result = result['r'] if result: if isinstance(result[0], list): bypkg = map(lambda x: (x[-1], u'/'.join(x[:-1])), result) numpackages = len(bypkg) packages = defaultdict(list) for p, arch in bypkg: packages[p].append(arch) packages = map(lambda i: u'%s [%s]' % (i[0], u', '.join(i[1])), packages.iteritems()) else: numpackages = len(result) packages = result event.addresponse(u'Found %(num)i packages: %(names)s', { 'num': numpackages, 'names': human_join(packages), }) else: event.addresponse(u'No packages found')
def show(self, event, package, distro): if distro is None or distro.lower() == 'all': distro = 'all' else: if self._release_cache is None: self._release_cache = json_webservice( u'http://dde.debian.net/dde/q/udd/packages', { 'list': '', 't': 'json', })['r'] releases = self._release_cache if distro not in releases: candidates = [x for x in releases if distro in x] if len(candidates) == 1: distro = candidates[0] else: event.addresponse(u"Sorry, I don't know about %(distro)s. " u"How about one of: %(releases)s?", { 'distro': distro, 'releases': human_join( x.startswith('prio-') and x[5:] or x for x in releases ),}) return result = json_webservice( u'http://dde.debian.net/dde/q/udd/packages/%s/%s' % (distro, package), {'t': 'json'}) result = result['r'] if not result: event.addresponse(u"Sorry, I couldn't find anything of that name. " u"Is it a binary package?") return event.addresponse(u'%(package)s %(version)s: %(description)s', result)
def get(self, event, key): if 'password' in key.lower() and not auth_responses(event, u'config'): return option = self.find_option(key) if isinstance(option, dict): config = option key = '' elif option is not None: config = option[0].__get__(option[1], type(option[1])) key = option[2] elif key == 'plugins': # Construct a dictionary since this isn't a list-valued option, # but a list of option keys. config = dict((plugin, None) for plugin in list_plugins()) key = '' elif key == 'sources': config = ibid.sources key = '' else: config = ibid.config if key: for part in key.split('.'): if not isinstance(config, dict) or part not in config: event.addresponse(u'No such option') return config = config[part] if isinstance(config, list): event.addresponse(u', '.join(config)) elif isinstance(config, dict): event.addresponse(u'Keys: ' + human_join(config.keys())) else: event.addresponse(unicode(config))
def query_carrying(self, event): items = Item.carried_items(event.session).all() if items: event.addresponse(u"I'm carrying %s", human_join(map(unicode, items))) else: event.addresponse(u"I'm not carrying anything")
def airport_search(self, event, search_loc, query): search_loc = search_loc is not None if not search_loc and not 3 <= len(query) <= 4: event.addresponse(u'Airport code must be 3 or 4 characters') return ids = self._airport_search(query, search_loc) if len(ids) == 0: event.addresponse(u"Sorry, I don't know that airport") elif len(ids) == 1: id = ids[0] airport = self.airports[id] code = u'unknown code' if airport[3] and airport[4]: code = u'codes %s and %s' % (airport[3], airport[4]) elif airport[3]: code = u'code %s' % airport[3] elif airport[4]: code = u'code %s' % airport[4] event.addresponse(u'%(airport)s in %(city)s, %(country)s has %(code)s', { u'airport': airport[0], u'city': airport[1], u'country': airport[2], u'code': code, }) else: event.addresponse(u'Found the following airports: %s', human_join(self.repr_airport(id) for id in ids)[:480])
def resolve(self, event, record, host, nameserver): ipaddr = re.compile(r"\d+\.\d+\.\d+\.\d+") if not record: if ipaddr.search(host): host = from_address(host) record = "PTR" else: record = "A" resolver = Resolver() if nameserver: if not ipaddr.search(nameserver): nameserver = resolver.query(nameserver, "A")[0].address resolver.nameservers = [nameserver] try: answers = resolver.query(host, str(record)) except NoAnswer: event.addresponse(u"I couldn't find any %(type)s records for %(host)s", {"type": record, "host": host}) return except NXDOMAIN: event.addresponse(u"I couldn't find the domain %s", host) return responses = [] for rdata in answers: responses.append(unicode(rdata)) event.addresponse(u"Records: %s", human_join(responses))
def portfor(self, event, proto): self._load_services() protocol = proto.lower() if protocol in self.protocols: event.addresponse(human_join(self.protocols[protocol])) else: event.addresponse(u"I don't know about that protocol")
def list(self, event): feeds = event.session.query(Feed).all() if feeds: event.addresponse(u'I know about: %s', human_join(sorted([ unicode(feed) for feed in feeds]))) else: event.addresponse(u"I don't know about any feeds")
def remote_tvrage(self, show): info_url = 'http://services.tvrage.com/tools/quickinfo.php?%s' info = urlopen(info_url % urlencode({'show': show.encode('utf-8')})) info = info.read() info = info.decode('utf-8') if info.startswith('No Show Results Were Found'): return info = info[5:].splitlines() show_info = [i.split('@', 1) for i in info] show_dict = dict(show_info) #check if there are actual airdates for Latest and Next Episode. None for Next #Episode does not neccesarily mean it is nor airing, just the date is unconfirmed. show_dict = defaultdict(lambda: 'None', show_info) for field in ('Latest Episode', 'Next Episode'): if field in show_dict: ep, name, date = show_dict[field].split('^', 2) count = date.count('/') format_from = { 0: '%Y', 1: '%b/%Y', 2: '%b/%d/%Y' }[count] format_to = ' '.join(('%d', '%B', '%Y')[-1 - count:]) date = strftime(format_to, strptime(date, format_from)) show_dict[field] = u'%s - "%s" - %s' % (ep, name, date) if 'Genres' in show_dict: show_dict['Genres'] = human_join(show_dict['Genres'].split(' | ')) return show_dict
def currency(self, event, place): if not self.currencies: self._load_currencies() results = defaultdict(list) for code, (c_places, name) in self.currencies.iteritems(): for c_place in c_places: if re.search(place, c_place, re.I): results[c_place].append(u'%s (%s)' % (name, code)) break if results: event.addresponse( human_join(u'%s uses %s' % (place, human_join(currencies)) for place, currencies in results.iteritems())) else: event.addresponse(u'No currencies found')
def handler(self, event): plugins = [] for processor in ibid.processors: if processor.name not in plugins: plugins.append(processor.name) event.addresponse(u'Plugins: %s', human_join(sorted(plugins)) or u'none')
def forecast(self, event, place): try: event.addresponse(u', '.join(self.remote_forecast(place))) except Weather.TooManyPlacesException, e: event.addresponse(u'Too many places match %(place)s: %(exception)s', { 'place': place, 'exception': human_join(e.args[0], separator=u';'), })
def list(self, event): feeds = event.session.query(Feed).all() if feeds: event.addresponse( u'I know about: %s', human_join(sorted([unicode(feed) for feed in feeds]))) else: event.addresponse(u"I don't know about any feeds")
def distance(self, event, unit, ignore, src, dst): unit_names = self.unit_names if unit and unit not in self.unit_names: event.addresponse( u"I don't know the unit '%(badunit)s'. I know about: %(knownunits)s", { 'badunit': unit, 'knownunits': human_join(u"%s (%s)" % (unit, self.unit_names[unit]) for unit in self.unit_names), }) return if unit: unit_names = [unit] srcp, dstp = self.get_place(src), self.get_place(dst) if not srcp or not dstp: event.addresponse( u"I don't know of anywhere called %s", (u" or ".join("'%s'" % place[0] for place in ((src, srcp), (dst, dstp)) if not place[1]))) return dist = acos( cos(srcp['lng']) * cos(dstp['lng']) * cos(srcp['lat']) * cos(dstp['lat']) + cos(srcp['lat']) * sin(srcp['lng']) * cos(dstp['lat']) * sin(dstp['lng']) + sin(srcp['lat']) * sin(dstp['lat'])) event.addresponse( u"Approximate distance, as the bot flies, between %(srcname)s and %(dstname)s is: %(distance)s", { 'srcname': srcp['name'], 'dstname': dstp['name'], 'distance': human_join([ u"%.02f %s" % (self.radius_values[unit] * dist, self.unit_names[unit]) for unit in unit_names ], conjunction=u'or'), })
def weather(self, event, place): try: values = self.remote_weather(place) event.addresponse(u'In %(place)s at %(time)s: %(temp)s; Humidity: %(humidity)s; Wind: %(wind)s; Conditions: %(conditions)s; Sunrise/set: %(sunrise)s/%(sunset)s; Moonrise/set: %(moonrise)s/%(moonset)s', values) except Weather.TooManyPlacesException, e: event.addresponse(u'Too many places match %(place)s: %(exception)s', { 'place': place, 'exception': human_join(e.args[0], separator=u';'), })
def _describe_category(self, event, category): """Respond with the help information for a category""" event.addresponse(u'I use the following features for %(description)s: ' u'%(features)s\n' u'Ask me "how do I use ..." for more details.', { 'description': category['description'].lower(), 'features': human_join(sorted(category['features'])), }, conflate=False)
def _parse_travelocity(self, etree): flights = [] table = [ t for t in etree.getiterator(u'table') if t.get(u'id') == u'tfGrid' ][0] trs = [t for t in table.getiterator(u'tr')] tr_index = 1 while tr_index < len(trs): tds = [] while True: new_tds = [t for t in trs[tr_index].getiterator(u'td')] tds.extend(new_tds) tr_index += 1 if len( filter( lambda t: t.get(u'class').strip() == u'tfAirlineSeatsMR', new_tds)): break flight = Flight() for td in tds: if td.get(u'class').strip() == u'tfAirline': anchor = td.find(u'a') if anchor is not None: airline = anchor.text.strip() else: airline = td.text.split(u'\n')[0].strip() flight.flight.append( u'%s %s' % (airline, td.findtext(u'div').strip())) if td.get(u'class').strip() == u'tfDepart' and td.text: flight.depart_time = td.text.split(u'\n')[0].strip() flight.depart_ap = u'%s %s' % (td.findtext( u'div').strip(), td.findtext(u'div/span').strip()) if td.get(u'class').strip() == u'tfArrive' and td.text: flight.arrive_time = td.text.split(u'\n')[0].strip() span = td.find(u'span') if span is not None and span.get( u'class').strip() == u'tfNextDayDate': flight.arrive_time = u'%s %s' % (flight.arrive_time, span.text.strip()[2:]) span = [ s for s in td.find(u'div').getiterator(u'span') ][1] flight.arrive_ap = u'%s %s' % ( td.findtext(u'div').strip(), span.text.strip()) else: flight.arrive_ap = u'%s %s' % (td.findtext( u'div').strip(), td.findtext(u'div/span').strip()) if td.get(u'class').strip() == u'tfTime' and td.text: flight.duration = td.text.strip() flight.stops = td.findtext(u'span/a').strip() if td.get(u'class').strip() in [u'tfPrice', u'tfPriceOr' ] and td.text: flight.price = td.text.strip() flight.flight = human_join(flight.flight) flights.append(flight) return flights
def placesearch(self, event, place): js = self.get_place_data(place, 10) if js['totalResultsCount'] == 0: event.addresponse(u"I don't know of anywhere even remotely like '%s'", place) else: event.addresponse(u"I can find: %s", (human_join([u"%s, %s, %s" % (p['name'], p['adminName1'], p['countryName']) for p in js['geonames'][:10]], separator=u';')))
def twitchList(self, event): twitch_names = [] for broadcaster in self.twitchlist.iterate(): twitch_names.append(broadcaster.name) message = u'The following people are being watched: %s' % \ (human_join(twitch_names)) event.addresponse(message, address=False, processed=True)
def currency(self, event, place): if not self.currencies: self._load_currencies() results = defaultdict(list) for code, (c_places, name) in self.currencies.iteritems(): for c_place in c_places: if re.search(place, c_place, re.I): results[c_place].append(u'%s (%s)' % (name, code)) break if results: event.addresponse(human_join( u'%s uses %s' % (place, human_join(currencies)) for place, currencies in results.iteritems() )) else: event.addresponse(u'No currencies found')
def variant(self): msgs = [] for name in ('simplified', 'traditional'): variants = self.data['k' + name.title() + 'Variant'].split()[1::2] if variants: msgs.append(u'the %(name)s form is %(var)s' % {'name': name, 'var': human_join(variants, conjunction='or')}) return msgs
def display_character(self, character): desc = u"%s: %s." % (character.characterID, character["long imdb name"]) filmography = character.get("filmography", ()) if len(filmography): more = (u"", u" etc")[len(filmography) > 5] desc += u" Appeared in %s%s." % (human_join(x["long imdb title"] for x in filmography[:5]), more) if character.has_key("introduction"): desc += u" Bio: %s" % character["introduction"] return desc
def intro(self, event): categories, features = self._get_features() categories = filter(lambda c: c['weight'] is not None, categories.itervalues()) categories = sorted(categories, key=lambda c: c['weight']) event.addresponse( u'I can help you with: %s.\n' u'Ask me "help me with ..." for more details.', human_join(c['description'].lower() for c in categories), conflate=False)
def variant(self): msgs = [] for name in ('simplified', 'traditional'): variants = self.data['k' + name.title() + 'Variant'].split()[1::2] if variants: msgs.append(u'the %(name)s form is %(var)s' % { 'name': name, 'var': human_join(variants, conjunction='or') }) return msgs
def _describe_category(self, event, category): """Respond with the help information for a category""" event.addresponse( u'I use the following features for %(description)s: ' u'%(features)s\n' u'Ask me "how do I use ..." for more details.', { 'description': category['description'].lower(), 'features': human_join(sorted(category['features'])), }, conflate=False)
def display_company(self, company): desc = "%s: %s" % (company.companyID, company["long imdb name"]) for key, title in ( (u"production companies", u"Produced"), (u"distributors", u"Distributed"), (u"miscellaneous companies", u"Was involved in")): if len(company.get(key, ())) > 0: more = (u"", u" etc.")[len(company[key]) > 3] desc += u" %s %s%s" % (title, human_join(x["long imdb title"] for x in company[key][:3]), more) return desc
def display_character(self, character): desc = u"%s: %s." % (character.characterID, character["long imdb name"]) filmography = character.get("filmography", ()) if len(filmography): more = (u"", u" etc")[len(filmography) > 5] desc += u" Appeared in %s%s." % (human_join( x["long imdb title"] for x in filmography[:5]), more) if character.has_key("introduction"): desc += u" Bio: %s" % character["introduction"] return desc
def ipcalc_deggregate(self, event, frm, to): code, output, error = self.call_ipcalc([frm, "-", to]) if code == 0: if output.startswith(u"INVALID ADDRESS"): event.addresponse(u"That's an invalid address. " u"Try something like 192.168.1.0") else: event.addresponse(u"Deaggregates to: %s", human_join(output.splitlines()[1:])) else: error = unicode_output(error.strip()) event.addresponse(error.replace(u"\n", u" "))
def intro(self, event): categories, features = self._get_features() categories = categories.itervalues() if not ibid.auth.authorise(event, 'admin'): categories = filter(lambda c: c['weight'] is not None, categories) categories = sorted(categories, key=lambda c: c['weight']) event.addresponse(u'I can help you with: %s.\n' u'Ask me "help me with ..." for more details.', human_join(c['description'].lower() for c in categories), conflate=False)
def country_to_tld(self, event, location): if not self.country_codes: self.country_codes = get_country_codes() output = [] for tld, country in self.country_codes.iteritems(): if location.lower() in country.lower(): output.append(u"%(tld)s is the ccTLD for %(country)s" % {"tld": tld, "country": country}) if output: event.addresponse(human_join(output)) else: event.addresponse(u"ISO doesn't know about any TLD for %s", location)
def display_company(self, company): desc = "%s: %s" % (company.companyID, company["long imdb name"]) for key, title in ((u"production companies", u"Produced"), (u"distributors", u"Distributed"), (u"miscellaneous companies", u"Was involved in")): if len(company.get(key, ())) > 0: more = (u"", u" etc.")[len(company[key]) > 3] desc += u" %s %s%s" % (title, human_join( x["long imdb title"] for x in company[key][:3]), more) return desc
def port(self, event, transport, number): self._load_services() results = [] if transport: results.extend(self.ports.get('%s/%s' % (number, transport.lower()), [])) else: for transport in ('tcp', 'udp', 'sctp'): results.extend('%s (%s)' % (protocol, transport.upper()) for protocol in self.ports.get('%s/%s' % (number, transport.lower()), [])) if results: event.addresponse(human_join(results)) else: event.addresponse(u"I don't know about any protocols using that port")
def list_permissions(self, event): permissions = [] for processor in ibid.processors: if hasattr(processor, 'permission') and getattr( processor, 'permission') not in permissions: permissions.append(getattr(processor, 'permission')) if hasattr(processor, 'permissions'): for permission in getattr(processor, 'permissions'): if permission not in permissions: permissions.append(permission) event.addresponse(u'Permissions: %s', human_join(sorted(permissions)) or u'none')
def ipcalc_deggregate(self, event, frm, to): code, output, error = self.call_ipcalc([frm, '-', to]) if code == 0: if output.startswith(u'INVALID ADDRESS'): event.addresponse(u"That's an invalid address. " u"Try something like 192.168.1.0") else: event.addresponse(u'Deaggregates to: %s', human_join(output.splitlines()[1:])) else: error = unicode_output(error.strip()) event.addresponse(error.replace(u'\n', u' '))
def weather(self, event, place): # The regex also matches "weather forecast..." which forecast should # process. So ignore it when this happens if place.lower().startswith('forecast'): return try: values = self.remote_weather(place) event.addresponse(u'In %(place)s at %(time)s: %(temp)s; Humidity: %(humidity)s; Wind: %(wind)s; Conditions: %(conditions)s; Sunrise/set: %(sunrise)s/%(sunset)s; Moonrise/set: %(moonrise)s/%(moonset)s', values) except Weather.TooManyPlacesException, e: event.addresponse(u'Too many places match %(place)s: %(exception)s', { 'place': place, 'exception': human_join(e.args[0], separator=u';'), })
class Nmap(Processor): usage = u"""port scan <hostname> net scan <network>/<prefix>""" feature = ('nmap', ) permission = 'nmap' min_prefix = IntOption('min_prefix', 'Minimum network prefix that may be scanned', 24) def setup(self): if not file_in_path('nmap'): raise Exception("Cannot locate nmap executable") @match(r'^(?:port\s+scan|nmap)\s+([0-9a-z.-]+)$') @authorise() def host_scan(self, event, host): try: ip = gethostbyname(host) except gaierror, e: event.addresponse(unicode(e.args[1])) return if ip.startswith('127.'): event.addresponse( u"I'm not allowed to inspect my host's internal interface.") return output, error, code = get_process_output( ['nmap', '--open', '-n', host]) ports = [] gotports = False for line in output.splitlines(): if gotports: if not line.split(): break port, state, service = line.split() ports.append('%s (%s)' % (port, service)) else: if line.startswith('Note: Host seems down.'): event.addresponse(u'That host seems to be down') return if line.startswith('PORT'): gotports = True if ports: event.addresponse(human_join(ports)) else: event.addresponse(u'No open ports detected')
def cs_players(self, event): server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.sendto('\xFF\xFF\xFF\xFFdetails', (self.cs_host, self.cs_port)) server.settimeout(5) data = server.recv(16384) assert data.startswith('\xFF\xFF\xFF\xFFm') data = data[5:] address, hostname, map, mod, modname, details = data.split('\x00', 5) details = details[:5] # We don't care about the rest clientcount, clientmax, protocol, type, os = struct.unpack( '<3Bcc', details) if clientcount == 0: event.addresponse(u'Nobody. Everyone must have lives...') return server.sendto('\xFF\xFF\xFF\xFFplayers', (self.cs_host, self.cs_port)) data = server.recv(16384) assert data.startswith('\xFF\xFF\xFF\xFF') data = data[6:] players = [] while data: player = {} data = data[1:] player['nickname'], data = data.split('\x00', 1) player['fragtotal'] = struct.unpack('<i', data[:4])[0] data = data[8:] players.append(player) players.sort(key=lambda x: x['fragtotal'], reverse=True) event.addresponse( u'There are %(clients)i/%(clientmax)s players playing %(map)s: %(players)s', { 'clients': clientcount, 'clientmax': clientmax, 'map': map, 'players': human_join(u'%s (%i)' % (p['nickname'], p['fragtotal']) for p in players), })
def query_giver(self, event, determiner, object): if determiner is None: determiner = '' who = event.sender['nick'] if determiner.lower() == 'our': if who[-1] in 'sS': determiner = who + "'" else: determiner = who + "'s" yours = True elif determiner.lower() == 'my': determiner = who + "'s" yours = True else: yours = False kind, items = self.find_items(event.session, determiner, object) if items: explanation = u'' if kind == 'unowned': explanation = plural(len(items), u". I didn't realise it was ", u". I didn't realise they were ") if yours: explanation += u"yours" else: explanation += determiner explanation += u"." yours = False event.addresponse(u'I got ' + human_join(u'%(item)s from %(giver)s' % {'item': [item, u'your ' + item.description][yours], 'giver': identity_name(event, item.giver)} for item in items) + explanation) return else: if yours: object = u'your ' + object elif determiner: object = determiner + u' ' + object event.addresponse(choice(( u"There's nothing like that in my bucket.", u"I don't have %s" % object)))
def currency(self, event, place): if not self.currencies: self._load_currencies() search = re.compile(place, re.I) results = [] for code, (places, name) in self.currencies.iteritems(): for place in places: if search.search(place): results.append(u'%s uses %s (%s)' % (place, name, code)) break if results: event.addresponse(human_join(results)) else: event.addresponse(u'No currencies found')
def country_to_tld(self, event, location): if not self.country_codes: self.country_codes = get_country_codes() output = [] for tld, country in self.country_codes.iteritems(): if location.lower() in country.lower(): output.append(u'%(tld)s is the ccTLD for %(country)s' % { 'tld': tld, 'country': country, }) if output: event.addresponse(human_join(output)) else: event.addresponse(u"ISO doesn't know about any TLD for %s", location)
def net_scan(self, event, network, prefix): if int(prefix) < self.min_prefix: event.addresponse(u"Sorry, I can't scan networks with a prefix less than %s", self.min_prefix) return output, error, code = get_process_output(['nmap', '-sP', '-n', '%s/%s' % (network, prefix)]) hosts = [] for line in output.splitlines(): if line.startswith('Host '): hosts.append(line.split()[1]) if hosts: event.addresponse(human_join(hosts)) else: event.addresponse(u'No hosts responded to pings')
def get(self, event, key): if 'password' in key.lower() and not auth_responses(event, u'config'): return config = ibid.config for part in key.split('.'): if not isinstance(config, dict) or part not in config: event.addresponse(u'No such option') return config = config[part] if isinstance(config, list): event.addresponse(u', '.join(config)) elif isinstance(config, dict): event.addresponse(u'Keys: ' + human_join(config.keys())) else: event.addresponse(unicode(config))
def _find_timezone(self, string): for name, zonename in self.custom_zones.items(): if string.lower() == name.lower(): return gettz(zonename) zone = gettz(string) if zone: return zone zone = gettz(string.upper()) if zone: return zone if string.lower() in self.lowerzones: return gettz(self.lowerzones[string.lower()]) ccode = None for code, name in self.countries.items(): if name.lower() == string.lower(): ccode = code if not ccode: if string.replace('.', '').upper() in self.timezones: ccode = string.replace('.', '').upper() if ccode: if len(self.timezones[ccode]) == 1: return gettz(self.timezones[ccode][0]) else: raise TimezoneException(u'%s has multiple timezones: %s' % (self.countries[ccode], human_join(self.timezones[ccode]))) possibles = [] for zones in self.timezones.values(): for name in zones: if string.replace(' ', '_').lower() in [part.lower() for part in name.split('/')]: possibles.append(name) if len(possibles) == 1: return gettz(possibles[0]) elif len(possibles) > 1: raise TimezoneException(u'Multiple timezones found: %s' % (human_join(possibles))) zone = self._geonames_lookup(string) if zone: return zone raise TimezoneException(u"I don't know about the %s timezone" % (string,))
def list(self, event, username): if not username: if not event.account: event.addresponse(u"I don't know who you are") return account = event.session.query(Account).get(event.account) else: if not auth_responses(event, u'accounts'): return account = event.session.query(Account) \ .filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return permissions = sorted(u'%s%s' % (permission_values[perm.value], perm.name) for perm in account.permissions) event.addresponse(u'Permissions: %s', human_join(permissions) or u'none')
def _usage_search(self, event, terms, features): terms = frozenset(self.stemmer.stemWord(term) for term in terms) results = set() for name, feat in features.iteritems(): if terms.issubset(feat['usage_keywords']): results.add(name) results = sorted(results) if len(results) == 1: self._describe_feature(event, features[results[0]]) elif len(results) > 1: event.addresponse( u"Please be more specific. I don't know if you mean %s", human_join((features[result]['name'] for result in results), conjunction=u'or')) else: event.addresponse( u"I'm afraid I don't know what you are asking about. " u'Ask "what can you do" to browse my features.')
def describe(self, event, username): if username.lower() == 'my': if not event.account: identity = event.session.query(Identity).get(event.identity) event.addresponse(u"%(name)s on %(source)s", { 'name': identity.identity, 'source': identity.source, }) return account = event.session.query(Account).get(event.account) else: account = event.session.query(Account).filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return event.addresponse(u'%(accountname)s is %(identities)s', { 'accountname': account.username, 'identities': human_join(u'%s on %s' % (identity.identity, identity.source) for identity in account.identities), })
def display_person(self, person): desc = u"%s: %s. %s." % ( person.personID, person["name"], human_join(role.title() for role in ( u"actor", u"animation department", u"art department", u"art director", u"assistant director", u"camera department", u"casting department", u"casting director", u"cinematographer", u"composer", u"costume department", u"costume designer", u"director", u"editorial department", u"editor", u"make up department", u"music department", u"producer", u"production designer", u"set decorator", u"sound department", u"speccial effects department", u"stunts", u"transport department", u"visual effects department", u"writer", u"miscellaneous crew") if person.has_key(role))) if person.has_key("mini biography"): desc += u" " + u" ".join(person["mini biography"]) else: if person.has_key("birth name") or person.has_key("birth date"): desc += u" Born %s." % u", ".join(person[attr] for attr in ( "birth name", "birth date") if person.has_key(attr)) return desc
def describe_category(self, event, terms): categories, features = self._get_features() termset = frozenset( self.stemmer.stemWord(term) for term in terms.lower().split()) if len(termset) == 1: term = list(termset)[0] exact = [c for c in categories.itervalues() if c['name'] == term] if exact: self._describe_category(event, exact[0]) return results = [] for name, cat in categories.iteritems(): if termset.issubset(cat['description_keywords']): results.append(name) if len(results) == 0: for name, cat in categories.iteritems(): if terms.lower() in cat['description'].lower(): results.append(name) results.sort() if len(results) == 1: self._describe_category(event, categories[results[0]]) return elif len(results) > 1: event.addresponse( u"Please be more specific, I don't know if you mean %s.", human_join( ('%s (%s)' % (categories[r]['description'].lower(), r) for r in results), conjunction=u'or')) return event.addresponse( u"I'm afraid I don't know what you are asking about. " u'Ask "what can you do" to browse my features.')