def cmd_github(msg): if not len(msg.args): raise IMException("indicate a repository name to search") repos = info_repos(" ".join(msg.args)) res = Response(channel=msg.channel, nomore="No more repository", count=" (%d more repo)") for repo in repos["items"]: homepage = "" if repo["homepage"] is not None: homepage = repo["homepage"] + " - " res.append_message( "Repository %s: %s%s Main language: %s; %d forks; %d stars; %d watchers; %d opened_issues; view it at %s" % ( repo["full_name"], homepage, repo["description"], repo["language"], repo["forks"], repo["stargazers_count"], repo["watchers_count"], repo["open_issues_count"], repo["html_url"], ) ) return res
def cmd_imdb(msg): if not len(msg.args): raise IMException("precise a movie/serie title!") title = ' '.join(msg.args) if re.match("^tt[0-9]{7}$", title) is not None: data = get_movie(imdbid=title) else: rm = re.match(r"^(.+)\s\(([0-9]{4})\)$", title) if rm is not None: data = get_movie(title=rm.group(1), year=rm.group(2)) else: data = get_movie(title=title) res = Response(channel=msg.channel, title="%s (%s)" % (data['Title'], data['Year']), nomore="No more information, more at http://www.imdb.com/title/%s" % data['imdbID']) res.append_message("\x02rating\x0F: %s (%s votes); \x02plot\x0F: %s" % (data['imdbRating'], data['imdbVotes'], data['Plot'])) res.append_message("%s \x02from\x0F %s \x02released on\x0F %s; \x02genre:\x0F %s; \x02directed by:\x0F %s; \x02written by:\x0F %s; \x02main actors:\x0F %s" % (data['Type'], data['Country'], data['Released'], data['Genre'], data['Director'], data['Writer'], data['Actors'])) return res
def cmd_github_user(msg): if not len(msg.args): raise IMException("indicate a user name to search") res = Response(channel=msg.channel, nomore="No more user") user = info_user(" ".join(msg.args)) if "login" in user: if user["repos"]: kf = " Known for: " + ", ".join([repo["name"] for repo in user["repos"]]) else: kf = "" if "name" in user: name = user["name"] else: name = user["login"] res.append_message( "User %s: %d public repositories; %d public gists; %d followers; %d following; view it at %s.%s" % ( name, user["public_repos"], user["public_gists"], user["followers"], user["following"], user["html_url"], kf, ) ) else: raise IMException("User not found") return res
def get_tracking_info(msg): if not len(msg.args): raise IMException("Renseignez un identifiant d'envoi.") res = Response(channel=msg.channel, count=" (%d suivis supplémentaires)") if 'tracker' in msg.kwargs: if msg.kwargs['tracker'] in TRACKING_HANDLERS: trackers = { msg.kwargs['tracker']: TRACKING_HANDLERS[msg.kwargs['tracker']] } else: raise IMException("No tracker named \x02{tracker}\x0F, please use" " one of the following: \x02{trackers}\x0F" .format(tracker=msg.kwargs['tracker'], trackers=', ' .join(TRACKING_HANDLERS.keys()))) else: trackers = TRACKING_HANDLERS for tracknum in msg.args: for name, tracker in trackers.items(): ret = tracker(tracknum) if ret: res.append_message(ret) break if not ret: res.append_message("L'identifiant \x02{id}\x0F semble incorrect," " merci de vérifier son exactitude." .format(id=tracknum)) return res
def cmd_github_commit(msg): if not len(msg.args): raise IMException("indicate a repository to view its commits") commit = None if re.match("^[a-fA-F0-9]+$", msg.args[0]): commit = msg.args[0] del msg.args[0] elif re.match("^[a-fA-F0-9]+$", msg.args[-1]): commit = msg.args[-1] del msg.args[-1] repo = " ".join(msg.args) count = " (%d more commits)" if commit is None else None res = Response(channel=msg.channel, nomore="No more commit", count=count) commits = info_commit(repo, commit) if commits is None: raise IMException("Repository or commit not found") for commit in commits: res.append_message( "Commit %s by %s on %s: %s" % ( commit["sha"][:10], commit["commit"]["author"]["name"], commit["commit"]["author"]["date"], commit["commit"]["message"].replace("\n", " "), ) ) return res
def get_cve_desc(msg): res = Response(channel=msg.channel) for cve_id in msg.args: if cve_id[:3].lower() != 'cve': cve_id = 'cve-' + cve_id res.append_message(get_cve(cve_id)) return res
def cmd_github_user_keys(msg): if not len(msg.args): raise IMException("indicate a user name to search") res = Response(channel=msg.channel, nomore="No more keys") for k in user_keys(" ".join(msg.args)): res.append_message(k) return res
def cmd_srchmediawiki(msg): if len(msg.args) < 2: raise IMException("indicate a domain and a term to search") res = Response(channel=msg.to_response, nomore="No more results", count=" (%d more results)") for r in search(msg.args[0], " ".join(msg.args[1:]), **msg.kwargs): res.append_message("%s: %s" % r) return res
def cmd_alert(msg): loc, coords, specific = treat_coord(msg) wth = get_json_weather(coords) res = Response(channel=msg.channel, nomore="No more weather alert", count=" (%d more alerts)") if "alerts" in wth: for alert in wth["alerts"]: res.append_message("\x03\x02%s\x03\x02 (see %s expire on %s): %s" % (alert["title"], alert["uri"], format_timestamp(int(alert["expires"]), wth["timezone"], wth["offset"]), alert["description"].replace("\n", " "))) return res
def cmd_book(msg): if not len(msg.args): raise IMException("please give me a title to search") book = get_book(" ".join(msg.args)) if book is None: raise IMException("unable to find book named like this") res = Response(channel=msg.channel) res.append_message("%s, written by %s: %s" % (book.getElementsByTagName("title")[0].firstChild.nodeValue, book.getElementsByTagName("author")[0].getElementsByTagName("name")[0].firstChild.nodeValue, web.striphtml(book.getElementsByTagName("description")[0].firstChild.nodeValue if book.getElementsByTagName("description")[0].firstChild else ""))) return res
def cmd_books(msg): if not len(msg.args): raise IMException("please give me a title to search") title = " ".join(msg.args) res = Response(channel=msg.channel, title="%s" % (title), count=" (%d more books)") for book in search_books(title): res.append_message("%s, writed by %s" % (book.getElementsByTagName("best_book")[0].getElementsByTagName("title")[0].firstChild.nodeValue, book.getElementsByTagName("best_book")[0].getElementsByTagName("author")[0].getElementsByTagName("name")[0].firstChild.nodeValue)) return res
def cmd_whois(msg): if len(msg.args) < 1: raise IMException("Provide a name") res = Response(channel=msg.channel, count=" (%d more logins)") for srch in msg.args: l = found_login(srch) if l is not None: pic = l.get_photo() res.append_message("%s is %s (%s %s): %s%s" % (srch, l.cn.capitalize(), l.login, l.uid, l.get_promo(), " and looks like %s" % pic if pic is not None else "")) else: res.append_message("Unknown %s :(" % srch) return res
def udsearch(msg): if not len(msg.args): raise IMException("Indicate a term to search") s = search(msg.args) res = Response(channel=msg.channel, nomore="No more results", count=" (%d more definitions)") for i in s["list"]: res.append_message(i["definition"].replace("\n", " "), title=i["word"]) return res
def get_info_yt(msg): soup = BeautifulSoup(getURLContent(URL)) res = Response(channel=msg.channel, nomore="No more upcoming CTF") for line in soup.body.find_all('tr'): n = line.find_all('td') if len(n) == 5: try: res.append_message("\x02%s:\x0F from %s type %s at %s. %s" % tuple([striphtml(x.text) for x in n])) except: pass return res
def cmd_whatis(msg): args = ["whatis", " ".join(msg.args)] res = Response(channel=msg.channel) with subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc: for line in proc.stdout.read().split(b"\n"): (line, n) = RGXP_s.subn(b'', line) res.append_message(" ".join(line.decode().split())) if len(res.messages) <= 0: res.append_message("There is no man page for %s." % msg.args[0]) return res
def cmd_news(msg): if not len(msg.args): raise IMException("Indicate the URL to visit.") url = " ".join(msg.args) links = [x for x in find_rss_links(url)] if len(links) == 0: links = [ url ] res = Response(channel=msg.channel, nomore="No more news from %s" % url) for n in get_last_news(links[0]): res.append_message("%s published %s: %s %s" % (("\x02" + web.striphtml(n.title) + "\x0F") if n.title else "An article without title", (n.updated.strftime("on %A %d. %B %Y at %H:%M") if n.updated else "someday") if isinstance(n, AtomEntry) else n.pubDate, web.striphtml(n.summary) if n.summary else "", n.link if n.link else "")) return res
def cmd_subreddit(msg): global LAST_SUBS if not len(msg.args): if msg.channel in LAST_SUBS and len(LAST_SUBS[msg.channel]) > 0: subs = [LAST_SUBS[msg.channel].pop()] else: raise IMException("Which subreddit? Need inspiration? " "type !horny or !bored") else: subs = msg.args all_res = list() for osub in subs: sub = re.match(r"^/?(?:(\w)/)?(\w+)/?$", osub) if sub is not None: if sub.group(1) is not None and sub.group(1) != "": where = sub.group(1) else: where = "r" sbr = web.getJSON("http://www.reddit.com/%s/%s/about.json" % (where, sub.group(2))) if sbr is None: raise IMException("subreddit not found") if "title" in sbr["data"]: res = Response(channel=msg.channel, nomore="No more information") res.append_message( ("[NSFW] " if sbr["data"]["over18"] else "") + sbr["data"]["url"] + " " + sbr["data"]["title"] + ": " + sbr["data"]["public_description" if sbr["data"]["public_description"] != "" else "description"].replace("\n", " ") + " %s subscriber(s)" % sbr["data"]["subscribers"]) if sbr["data"]["public_description"] != "": res.append_message( sbr["data"]["description"].replace("\n", " ")) all_res.append(res) else: all_res.append(Response("/%s/%s doesn't exist" % (where, sub.group(2)), channel=msg.channel)) else: all_res.append(Response("%s is not a valid subreddit" % osub, channel=msg.channel, nick=msg.nick)) return all_res
def cmd_man(msg): args = ["man"] num = None if len(msg.args) == 1: args.append(msg.args[0]) elif len(msg.args) >= 2: try: num = int(msg.args[0]) args.append("%d" % num) args.append(msg.args[1]) except ValueError: args.append(msg.args[0]) os.unsetenv("LANG") res = Response(channel=msg.channel) with subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc: for line in proc.stdout.read().split(b"\n"): (line, n) = RGXP_s.subn(b'', line) res.append_message(line.decode()) if len(res.messages) <= 0: if num is not None: res.append_message("There is no entry %s in section %d." % (msg.args[0], num)) else: res.append_message("There is no man page for %s." % msg.args[0]) return res
def cmd_spell(msg): if not len(msg.args): raise IMException("indique une orthographe approximative du mot dont tu veux vérifier l'orthographe.") lang = msg.kwargs["lang"] if "lang" in msg.kwargs else "fr" res = Response(channel=msg.channel) for word in msg.args: try: r = check_spell(word, lang) except AspellError: raise IMException("Je n'ai pas le dictionnaire `%s' :(" % lang) if r == True: add_score(msg.nick, "correct") res.append_message("l'orthographe de `%s' est correcte" % word) elif len(r) > 0: add_score(msg.nick, "bad") res.append_message(r, title="suggestions pour `%s'" % word) else: add_score(msg.nick, "bad") res.append_message("aucune suggestion pour `%s'" % word) return res
def get_info_yt(msg): links = list() if len(msg.args) <= 0: global LAST_URLS if msg.channel in LAST_URLS and len(LAST_URLS[msg.channel]) > 0: links.append(LAST_URLS[msg.channel].pop()) else: raise IMException("I don't have any youtube URL for now, please provide me one to get information!") else: for url in msg.args: links.append(url) data = _get_ytdl(links) res = Response(channel=msg.channel) for msg in data: res.append_message(msg) return res
def cmd_translate(msg): if not len(msg.args): raise IMException("which word would you translate?") langFrom = msg.kwargs["from"] if "from" in msg.kwargs else "en" if "to" in msg.kwargs: langTo = msg.kwargs["to"] else: langTo = "fr" if langFrom == "en" else "en" if langFrom not in LANG or langTo not in LANG: raise IMException("sorry, I can only translate to or from: " + ", ".join(LANG)) if langFrom != "en" and langTo != "en": raise IMException("sorry, I can only translate to or from english") res = Response(channel=msg.channel, count=" (%d more meanings)", nomore="No more translation") for t in translate(" ".join(msg.args), langFrom=langFrom, langTo=langTo): res.append_message(t) return res
def cmd_tcode(msg): if not len(msg.args): raise IMException("indicate a transaction code or " "a keyword to search!") url = ("http://www.tcodesearch.com/tcodes/search?q=%s" % urllib.parse.quote(msg.args[0])) page = web.getURLContent(url) soup = BeautifulSoup(page) res = Response(channel=msg.channel, nomore="No more transaction code", count=" (%d more tcodes)") search_res = soup.find("", {'id':'searchresults'}) for item in search_res.find_all('dd'): res.append_message(item.get_text().split('\n')[1].strip()) return res
def go(msg, what): if not len(msg.args): raise IMException("de quel mot veux-tu connaître la liste des synonymes ?") lang = msg.kwargs["lang"] if "lang" in msg.kwargs else "fr" word = ' '.join(msg.args) try: best, synos, anton = lang_binding[lang](word) except: best, synos, anton = (list(), list(), list()) if what == "synonymes": if len(synos) > 0 or len(best) > 0: res = Response(channel=msg.channel, title="Synonymes de %s" % word) if len(best) > 0: res.append_message(best) if len(synos) > 0: res.append_message(synos) return res else: raise IMException("Aucun synonyme de %s n'a été trouvé" % word) elif what == "antonymes": if len(anton) > 0: res = Response(anton, channel=msg.channel, title="Antonymes de %s" % word) return res else: raise IMException("Aucun antonyme de %s n'a été trouvé" % word) else: raise IMException("WHAT?!")
def cmd_github_issue(msg): if not len(msg.args): raise IMException("indicate a repository to view its issues") issue = None li = re.match("^#?([0-9]+)$", msg.args[0]) ri = re.match("^#?([0-9]+)$", msg.args[-1]) if li is not None: issue = li.group(1) del msg.args[0] elif ri is not None: issue = ri.group(1) del msg.args[-1] repo = " ".join(msg.args) count = " (%d more issues)" if issue is None else None res = Response(channel=msg.channel, nomore="No more issue", count=count) issues = info_issue(repo, issue) if issues is None: raise IMException("Repository not found") for issue in issues: res.append_message( "%s%s issue #%d: \x03\x02%s\x03\x02 opened by %s on %s: %s" % ( issue["state"][0].upper(), issue["state"][1:], issue["number"], issue["title"], issue["user"]["login"], issue["created_at"], issue["body"].replace("\n", " "), ) ) return res
def cmd_flight(msg): if not len(msg.args): raise IMException("please indicate a flight") res = Response(channel=msg.channel, nick=msg.nick, nomore="No more flights", count=" (%s more flights)") for param in msg.args: for flight in virtual_radar(param): if 'Lat' in flight and 'Long' in flight: loc = None for location in mapquest.geocode('{Lat},{Long}'.format(**flight)): loc = location break if loc: res.append_message('\x02{0}\x0F: Position: \x02{1}\x0F, {2}'.format(flight['Call'], \ mapquest.where(loc), \ ', '.join(filter(None, flight_info(flight))))) continue res.append_message('\x02{0}\x0F: {1}'.format(flight['Call'], \ ', '.join(filter(None, flight_info(flight))))) return res
def parseanswer(msg): res = Response(channel=msg.channel) # Avoid message starting by ! which can be interpreted as command by other bots if msg.cmd[0] == "!": res.nick = msg.nick if context.data.index[msg.cmd].name == "strend": if context.data.index[msg.cmd].hasAttribute("end"): res.append_message("%s commencé il y a %s et se terminera dans %s." % (msg.cmd, countdown(msg.date - context.data.index[msg.cmd].getDate("start")), countdown(context.data.index[msg.cmd].getDate("end") - msg.date))) else: res.append_message("%s commencé il y a %s." % (msg.cmd, countdown(msg.date - context.data.index[msg.cmd].getDate("start")))) else: res.append_message(countdown_format(context.data.index[msg.cmd].getDate("start"), context.data.index[msg.cmd]["msg_before"], context.data.index[msg.cmd]["msg_after"])) return res
def cmd_worldcup(msg): res = Response(channel=msg.channel, nomore="No more match to display", count=" (%d more matches)") url = None if len(msg.args) == 1: if msg.args[0] == "today" or msg.args[0] == "aujourd'hui": url = "matches/today?by_date=ASC" elif msg.args[0] == "tomorrow" or msg.args[0] == "demain": url = "matches/tomorrow?by_date=ASC" elif msg.args[0] == "all" or msg.args[0] == "tout" or msg.args[0] == "tous": url = "matches/" elif len(msg.args[0]) == 3: url = "matches/country?fifa_code=%s&by_date=DESC" % msg.args[0] elif is_int(msg.args[0]): url = int(msg.arg[0]) else: raise IMException("unrecognized request; choose between 'today', 'tomorrow', a FIFA country code or a match identifier") if url is None: url = "matches/current?by_date=ASC" res.nomore = "There is no match currently" if isinstance(url, int): matches = get_match(API_URL % "matches/", url) else: matches = [m for m in get_matches(API_URL % url)] for match in matches: if len(matches) == 1: res.count = " (%d more actions)" for m in prettify(match): res.append_message(m) else: res.append_message(prettify(match)[0]) return res
def search(msg): if not len(msg.args): raise IMException("Indicate a term to search") s = do_search(msg.args) res = Response(channel=msg.channel, nomore="No more results", count=" (%d more results)") res.append_message(s.redirect) res.append_message(s.answer) res.append_message(s.abstract) res.append_message([r for r in s.result]) for rt in s.relatedTopics: res.append_message(rt) res.append_message(s.definition) return res
def cmd_weather(msg): loc, coords, specific = treat_coord(msg) wth = get_json_weather(coords) res = Response(channel=msg.channel, nomore="No more weather information") if "alerts" in wth: alert_msgs = list() for alert in wth["alerts"]: alert_msgs.append("\x03\x02%s\x03\x02 expire on %s" % (alert["title"], format_timestamp(int(alert["expires"]), wth["timezone"], wth["offset"]))) res.append_message("\x03\x16\x03\x02/!\\\x03\x02 Alert%s:\x03\x16 " % ("s" if len(alert_msgs) > 1 else "") + ", ".join(alert_msgs)) if specific is not None: gr = re.match(r"^([0-9]*)\s*([a-zA-Z])", specific) if gr is None or gr.group(1) == "": gr1 = 1 else: gr1 = int(gr.group(1)) if gr.group(2).lower() == "h" and gr1 < len(wth["hourly"]["data"]): hour = wth["hourly"]["data"][gr1] res.append_message("\x03\x02At %sh:\x03\x02 %s" % (format_timestamp(int(hour["time"]), wth["timezone"], wth["offset"], '%H'), format_wth(hour))) elif gr.group(2).lower() == "d" and gr1 < len(wth["daily"]["data"]): day = wth["daily"]["data"][gr1] res.append_message("\x03\x02On %s:\x03\x02 %s" % (format_timestamp(int(day["time"]), wth["timezone"], wth["offset"], '%A'), format_forecast_daily(day))) else: res.append_message("I don't understand %s or information is not available" % specific) else: res.append_message("\x03\x02Currently:\x03\x02 " + format_wth(wth["currently"])) nextres = "\x03\x02Today:\x03\x02 %s " % wth["daily"]["data"][0]["summary"] if "minutely" in wth: nextres += "\x03\x02Next hour:\x03\x02 %s " % wth["minutely"]["summary"] nextres += "\x03\x02Next 24 hours:\x03\x02 %s \x03\x02Next week:\x03\x02 %s" % (wth["hourly"]["summary"], wth["daily"]["summary"]) res.append_message(nextres) for hour in wth["hourly"]["data"][1:4]: res.append_message("\x03\x02At %sh:\x03\x02 %s" % (format_timestamp(int(hour["time"]), wth["timezone"], wth["offset"], '%H'), format_wth(hour))) for day in wth["daily"]["data"][1:]: res.append_message("\x03\x02On %s:\x03\x02 %s" % (format_timestamp(int(day["time"]), wth["timezone"], wth["offset"], '%A'), format_forecast_daily(day))) return res
def _help_msg(msg): """Parse and response to help messages""" from more import Response res = Response(channel=msg.to_response) if len(msg.args) >= 1: if msg.args[0] in self.modules: if hasattr(self.modules[msg.args[0]], "help_full"): hlp = self.modules[msg.args[0]].help_full() if isinstance(hlp, Response): return hlp else: res.append_message(hlp) else: res.append_message([str(h) for s,h in self.modules[msg.args[0]].__nemubot_context__.hooks], title="Available commands for module " + msg.args[0]) elif msg.args[0][0] == "!": from nemubot.message.command import Command for h in self.treater._in_hooks(Command(msg.args[0][1:])): if h.help_usage: lp = ["\x03\x02%s%s\x03\x02: %s" % (msg.args[0], (" " + k if k is not None else ""), h.help_usage[k]) for k in h.help_usage] jp = h.keywords.help() return res.append_message(lp + ([". Moreover, you can provides some optional parameters: "] + jp if len(jp) else []), title="Usage for command %s" % msg.args[0]) elif h.help: return res.append_message("Command %s: %s" % (msg.args[0], h.help)) else: return res.append_message("Sorry, there is currently no help for the command %s. Feel free to make a pull request at https://github.com/nemunaire/nemubot/compare" % msg.args[0]) res.append_message("Sorry, there is no command %s" % msg.args[0]) else: res.append_message("Sorry, there is no module named %s" % msg.args[0]) else: res.append_message("Pour me demander quelque chose, commencez " "votre message par mon nom ; je réagis " "également à certaine commandes commençant par" " !. Pour plus d'informations, envoyez le " "message \"!more\".") res.append_message("Mon code source est libre, publié sous " "licence AGPL (http://www.gnu.org/licenses/). " "Vous pouvez le consulter, le dupliquer, " "envoyer des rapports de bogues ou bien " "contribuer au projet sur GitHub : " "http://github.com/nemunaire/nemubot/") res.append_message(title="Pour plus de détails sur un module, " "envoyez \"!help nomdumodule\". Voici la liste" " de tous les modules disponibles localement", message=["\x03\x02%s\x03\x02 (%s)" % (im, self.modules[im].__doc__) for im in self.modules if self.modules[im].__doc__]) return res