def on_gitlab_note(self, data): repo_name = data["project"]["name"] attribs = data["object_attributes"] noteable_type = attribs["noteable_type"] if noteable_type == "Commit": id = attribs["commit_id"] title = data["commit"]["message"].split("\n")[0] if len(title) > 100: title = title[:100] + "..." elif noteable_type == "MergeRequest": id = data["merge_request"]["iid"] title = data["merge_request"]["title"] noteable_type = "Merge Request" elif noteable_type == "Issue": id = data["issue"]["iid"] title = data["issue"]["title"] elif noteable_type == "Snippet": id = data["snippet"]["id"] title = data["snippet"]["title"] else: return msg = ("[{repo_name}] {user} commented on {noteable_type} {number} " "{title} {url}".format(repo_name=colored(repo_name, "blue"), user=colored(data["user"]["name"], "dark_cyan"), noteable_type=noteable_type, number=colored(str(id), "dark_yellow"), title=unidecode(title), url=attribs["url"])) self.report_to_irc(repo_name, msg)
def on_gitlab_merge_request(self, data): attribs = data["object_attributes"] repo_name = attribs["target"]["name"] action = attribs["action"] if action == "open": action = colored("opened", "dark_green") elif action == "reopen": action = colored("reopened", "dark_green") elif action == "close": action = colored("closed", "red") elif action == "merge": action = colored("merged", "dark_green") elif action == "update": action = "updated" elif action == "approved": action = colored("approved", "dark_green") msg = ("[{repo_name}] {user} {action} Merge Request #{number} " "{title} ({source} -> {target}): {url}".format( repo_name=colored(repo_name, "blue"), user=colored(data["user"]["name"], "dark_cyan"), action=action, number=colored(str(attribs["iid"]), "dark_yellow"), title=unidecode(attribs["title"]), source=colored(attribs["source_branch"], "dark_blue"), target=colored(attribs["target_branch"], "dark_red"), url=attribs["url"])) self.report_to_irc(repo_name, msg)
def on_gitlab_note(self, data): repo_name = data["project"]["name"] attribs = data["object_attributes"] noteable_type = attribs["noteable_type"] if noteable_type == "Commit": id = attribs["commit_id"] title = data["commit"]["message"].split("\n")[0] if len(title) > 100: title = title[:100] + "..." elif noteable_type == "MergeRequest": id = data["merge_request"]["iid"] title = data["merge_request"]["title"] noteable_type = "Merge Request" elif noteable_type == "Issue": id = data["issue"]["iid"] title = data["issue"]["title"] elif noteable_type == "Snippet": id = data["snippet"]["id"] title = data["snippet"]["title"] else: return msg = ("[{repo_name}] {user} commented on {noteable_type} {number} " "{title} {url}".format( repo_name=colored(repo_name, "blue"), user=colored(data["user"]["name"], "dark_cyan"), noteable_type=noteable_type, number=colored(str(id), "dark_yellow"), title=unidecode(title), url=attribs["url"])) self.report_to_irc(repo_name, msg)
def on_github_push(self, data): action = "pushed" if data["deleted"]: action = colored("deleted", "red") elif data["forced"]: action = colored("force pushed", "red") url = yield shorten_github_url(data["compare"]) repo_name = data["repository"]["name"] branch = data["ref"].split("/", 2)[-1] msg = ("[{repo_name}] {pusher} {action} {num_commits} commit(s) to " "{branch}: {compare}".format( repo_name=colored(repo_name, "blue"), pusher=colored(unidecode(data["pusher"]["name"]), "dark_cyan"), action=action, num_commits=len(data["commits"]), branch=colored(branch, "dark_green"), compare=url)) self.report_to_irc(repo_name, msg) self.commits_to_irc(repo_name, data["commits"], github=True) # subset of information that is common for both GitHUb and GitLab # only a few useful pieces of information subset = {"commits": data["commits"], "branch": branch, "project": {"name": data["repository"]["name"], "namespace": data["repository"]["full_name"].split( "/")[0], "description": data["repository"]["description"], "url": data["repository"]["html_url"], "homepage": data["repository"]["homepage"]}, "pusher": {"name": data["pusher"]["name"], "username": data["sender"]["login"], "id": data["sender"]["id"]}} self.push_hooks(subset)
def on_gitlab_push(self, data): repo_name = data["project"]["name"] branch = data["ref"].split("/", 2)[-1] msg = ("[{repo_name}] {pusher} pushed {num_commits} commit(s) to " "{branch}".format(repo_name=colored(repo_name, "blue"), pusher=colored(data["user_name"], "dark_cyan"), num_commits=len(data["commits"]), branch=colored(branch, "dark_green"))) self.report_to_irc(repo_name, msg) self.commits_to_irc(repo_name, data["commits"]) # subset of information that is common for both GitHUb and GitLab # only a few useful pieces of information subset = { "commits": data["commits"], "branch": branch, "project": { "name": data["project"]["name"], "namespace": data["project"]["namespace"], "description": data["project"]["description"], "url": data["project"]["http_url"], "homepage": data["project"]["homepage"] }, "pusher": { "name": data["user_name"], "username": data["user_username"], "id": data["user_id"] } } self.push_hooks(subset)
def on_github_commit_comment(self, data): repo_name = data["repository"]["name"] url = yield shorten_github_url(data["comment"]["html_url"]) msg = "[{repo_name}] {user} commented on commit {url}".format( repo_name=colored(repo_name, "blue"), user=colored(data["comment"]["user"]["login"], "dark_cyan"), url=url) self.report_to_irc(repo_name, msg)
def on_github_fork(self, data): repo_name = data["repository"]["name"] url = yield shorten_github_url(data["forkee"]["html_url"]) msg = "[{repo_name}] {user} created fork {url}".format( repo_name=colored(repo_name, "blue"), user=colored(data["forkee"]["owner"]["login"], "dark_cyan"), url=url) self.report_to_irc(repo_name, msg)
def on_github_delete(self, data): repo_name = data["repository"]["name"] msg = "[{repo_name}] {user} deleted {ref_type} {ref}".format( repo_name=colored(repo_name, "blue"), user=colored(data["sender"]["login"], "dark_cyan"), ref_type=data["ref_type"], ref=colored(data["ref"], "dark_magenta")) self.report_to_irc(repo_name, msg)
def on_gitlab_tag_push(self, data): repo_name = data["project"]["name"] msg = ("[{repo_name}] {pusher} added tag {tag}".format( repo_name=colored(repo_name, "blue"), pusher=colored(data["user_name"], "dark_cyan"), tag=colored(data["ref"].split("/", 2)[-1], "dark_green"))) self.report_to_irc(repo_name, msg) self.commits_to_irc(repo_name, data["commits"])
def report_hook_success_msg(self, success, actionname): """ Send a success or fail message to the 'hook_report_users' """ if isinstance(success, Failure): message = "Hook {} failed: {}".format(colored(actionname, "blue"), success.getErrorMessage()) else: message = "Hook {} finished without errors".format( colored(actionname, "blue")) for user in self.hook_report_users: self.bot.msg(user, message)
def on_github_issue_comment(self, data): url = yield shorten_github_url(data["comment"]["html_url"]) repo_name = data["repository"]["name"] msg = ("[{repo_name}] {user} {action} comment on Issue #{number} " "{title} {url}".format( repo_name=colored(repo_name, "blue"), user=colored(data["comment"]["user"]["login"], "dark_cyan"), action=data["action"], number=colored(str(data["issue"]["number"]), "dark_yellow"), title=unidecode(data["issue"]["title"]), url=url)) self.report_to_irc(repo_name, msg)
def on_github_pull_request(self, data): action = data["action"] payload = None repo_name = data["repository"]["name"] user = data["sender"]["login"] if action == "assigned" or action == "unassigned": payload = data["pull_request"]["assignee"]["login"] elif action == "labeled" or action == "unlabeled": url = yield shorten_github_url(data["pull_request"]["html_url"]) fg, bg = self.github_label_colors(data["label"]) payload = "{} ({})".format(colored(data["label"]["name"], fg, bg), url) elif action == "milestoned": payload = data["pull_request"]["milestone"]["title"] elif action == "review_requested": action = "requested review for" payload = data["requested_reviewer"]["login"] elif action == "review_request_removed": action = "removed review request for" payload = data["requested_reviewer"]["login"] elif action == "opened": action = colored(action, "dark_green") elif action == "reopened": action = colored(action, "dark_green") elif action == "closed": if data["pull_request"]["merged"]: action = colored("merged", "dark_green") user = data["pull_request"]["merged_by"]["login"] else: action = colored(action, "red") elif action == "synchronize": action = "synchronized" elif action == "ready_for_review": action = "marked ready for review:" if not payload: payload = yield shorten_github_url( data["pull_request"]["html_url"]) msg = ("[{repo_name}] {user} {action} Pull Request #{number} {title} " "({head} -> {base}): {payload}".format( repo_name=colored(repo_name, "blue"), user=colored(user, "dark_cyan"), action=action, number=colored(str(data["pull_request"]["number"]), "dark_yellow"), title=unidecode(data["pull_request"]["title"]), head=colored(data["pull_request"]["head"]["ref"], "dark_blue"), base=colored(data["pull_request"]["base"]["ref"], "dark_red"), payload=payload)) self.report_to_irc(repo_name, msg)
def on_github_pull_request(self, data): action = data["action"] payload = None repo_name = data["repository"]["name"] user = data["pull_request"]["user"]["login"] if action == "assigned" or action == "unassigned": payload = data["pull_request"]["assignee"]["login"] elif action == "labeled" or action == "unlabeled": url = yield shorten_github_url(data["pull_request"]["html_url"]) fg, bg = self.github_label_colors(data["label"]) payload = "{} ({})".format(colored(data["label"]["name"], fg, bg), url) elif action == "milestoned": payload = data["pull_request"]["milestone"]["title"] elif action == "review_requested": action = "requested review for" payload = data["requested_reviewer"]["login"] elif action == "review_request_removeded": action = "removed review request for" payload = data["requested_reviewer"]["login"] elif action == "opened": action = colored(action, "dark_green") elif action == "reopened": action = colored(action, "dark_green") elif action == "closed": if data["pull_request"]["merged"]: action = colored("merged", "dark_green") user = data["pull_request"]["merged_by"]["login"] else: action = colored(action, "red") user = data["sender"]["login"] elif action == "synchronize": action = "synchronized" if not payload: payload = yield shorten_github_url( data["pull_request"]["html_url"]) msg = ("[{repo_name}] {user} {action} Pull Request #{number} {title} " "({head} -> {base}): {payload}".format( repo_name=colored(repo_name, "blue"), user=colored(user, "dark_cyan"), action=action, number=colored(str(data["pull_request"]["number"]), "dark_yellow"), title=unidecode(data["pull_request"]["title"]), head=colored(data["pull_request"]["head"]["ref"], "dark_blue"), base=colored(data["pull_request"]["base"]["ref"], "dark_red"), payload=payload)) self.report_to_irc(repo_name, msg)
def _github_PR_review_send_msg(self, is_comment, repo_name, user, pr_number, title, action, head, base, urls): type_ = "Review Comment" if is_comment else "Review" msg = ("[{repo_name}] {user} {action} {type_} for Pull Request " "#{number} {title} ({head} -> {base}): {url}".format( repo_name=colored(repo_name, "blue"), user=colored(user, "dark_cyan"), action=action, type_=type_, number=colored(pr_number, "dark_yellow"), title=unidecode(title), head=colored(head, "dark_blue"), base=colored(base, "dark_red"), url=", ".join(urls))) self.report_to_irc(repo_name, msg)
def on_github_release(self, data): repo_name = data["repository"]["name"] url = yield shorten_github_url(data["release"]["html_url"]) msg = "[{repo_name}] New release {url}".format(repo_name=colored( data["repository"]["name"], "blue"), url=url) self.report_to_irc(repo_name, msg)
def on_github_pull_request_review_comment(self, data): repo_name = data["repository"]["name"] url = yield shorten_github_url(data["comment"]["html_url"]) msg = ("[{repo_name}] {user} commented on Pull Request #{number} " "{title} ({head} -> {base}): {url}".format( repo_name=colored(repo_name, "blue"), user=colored(data["comment"]["user"]["login"], "dark_cyan"), number=colored(str(data["pull_request"]["number"]), "dark_yellow"), title=unidecode(data["pull_request"]["title"]), head=colored(data["pull_request"]["head"]["ref"], "dark_blue"), base=colored(data["pull_request"]["base"]["ref"], "dark_red"), url=url)) self.report_to_irc(repo_name, msg)
def on_github_release(self, data): repo_name = data["repository"]["name"] url = yield shorten_github_url(data["release"]["html_url"]) msg = "[{repo_name}] New release {url}".format( repo_name=colored(data["repository"]["name"], "blue"), url=url) self.report_to_irc(repo_name, msg)
def on_github_issues(self, data): action = data["action"] payload = None repo_name = data["repository"]["name"] if action == "assigned" or action == "unassigned": payload = data["issue"]["assignee"]["login"] elif action == "labeled" or action == "unlabeled": url = yield shorten_github_url(data["issue"]["html_url"]) fg, bg = self.github_label_colors(data["label"]) payload = "{} ({})".format(colored(data["label"]["name"], fg, bg), url) elif action == "milestoned": payload = data["issue"]["milestone"]["title"] elif action == "opened": action = colored(action, "red") elif action == "reopened": action = colored(action, "red") elif action == "closed": action = colored(action, "dark_green") if not payload: payload = yield shorten_github_url(data["issue"]["html_url"]) msg = ("[{repo_name}] {user} {action} Issue #{number} {title}: " "{payload}".format(repo_name=colored(repo_name, "blue"), user=colored(data["sender"]["login"], "dark_cyan"), action=action, number=colored(str(data["issue"]["number"]), "dark_yellow"), title=unidecode(data["issue"]["title"]), payload=payload)) self.report_to_irc(repo_name, msg)
def on_github_push(self, data): action = "pushed" if data["deleted"]: action = colored("deleted", "red") elif data["forced"]: action = colored("force pushed", "red") url = yield shorten_github_url(data["compare"]) repo_name = data["repository"]["name"] branch = data["ref"].split("/", 2)[-1] msg = ("[{repo_name}] {pusher} {action} {num_commits} commit(s) to " "{branch}: {compare}".format( repo_name=colored(repo_name, "blue"), pusher=colored(unidecode(data["pusher"]["name"]), "dark_cyan"), action=action, num_commits=len(data["commits"]), branch=colored(branch, "dark_green"), compare=url)) self.report_to_irc(repo_name, msg) self.commits_to_irc(repo_name, data["commits"], github=True) # subset of information that is common for both GitHUb and GitLab # only a few useful pieces of information subset = { "commits": data["commits"], "branch": branch, "project": { "name": data["repository"]["name"], "namespace": data["repository"]["full_name"].split("/")[0], "description": data["repository"]["description"], "url": data["repository"]["html_url"], "homepage": data["repository"]["homepage"] }, "pusher": { "name": data["pusher"]["name"], "username": data["sender"]["login"], "id": data["sender"]["id"] } } self.push_hooks(subset)
def search_pypi(bot): """Search for python packages from PyPI - usage: (search|info) packages""" _baseurl = "https://pypi.python.org/pypi/{}/json" _maxlen = 400 _client = xmlrpclib.ServerProxy("https://pypi.python.org/pypi") def _handle_search_results(results, channel): packagenames = [item['name'] for item in results] num_packages = len(packagenames) if num_packages < 10: show_result = ", ".join(packagenames) else: show_result = ", ".join(packagenames[:10]) + " ..." bot.msg(channel, str(num_packages) + " packages found: " + show_result) @defer.inlineCallbacks def _handle_info_results(results, channel): data = yield results.json() name = data["info"]["name"].encode("utf-8") author = data["info"]["author"].encode("utf-8") description = data["info"]["description"].encode("utf-8") description = description.replace("\n", " ") if len(description) > _maxlen: description = description[:_maxlen] + "..." bot.msg(channel, "{} by {}: {}".format(formatting.bold(name, True), formatting.bold(author, True), description), length=510) bot.msg(channel, data["info"]["package_url"].encode("utf-8")) def _handle_error(error, arg, channel): bot.msg(channel, "No such package: {}".format(arg)) while True: args, sender, senderhost, channel = yield if len(args) < 2 or not args[0] in ["search", "info"]: bot.msg(channel, formatting.colored("Invalid call - check the help", "red")) continue if args[0] == "search": for package in args[1:]: d = threads.deferToThread(_client.search, ({'name': package})) d.addCallback(_handle_search_results, channel) elif args[0] == "info": for package in args[1:]: url = _baseurl.format(package) d = get(url) d.addCallback(_handle_info_results, channel) d.addErrback(_handle_error, package, channel)
def on_gitlab_push(self, data): repo_name = data["project"]["name"] branch = data["ref"].split("/", 2)[-1] msg = ("[{repo_name}] {pusher} pushed {num_commits} commit(s) to " "{branch}".format(repo_name=colored(repo_name, "blue"), pusher=colored(data["user_name"], "dark_cyan"), num_commits=len(data["commits"]), branch=colored(branch, "dark_green"))) self.report_to_irc(repo_name, msg) self.commits_to_irc(repo_name, data["commits"]) # subset of information that is common for both GitHUb and GitLab # only a few useful pieces of information subset = {"commits": data["commits"], "branch": branch, "project": {"name": data["project"]["name"], "namespace": data["project"]["namespace"], "description": data["project"]["description"], "url": data["project"]["http_url"], "homepage": data["project"]["homepage"]}, "pusher": {"name": data["user_name"], "username": data["user_username"], "id": data["user_id"]}} self.push_hooks(subset)
def bot_help(bot): """Guess what this function does""" thismodule = sys.modules[__name__] while True: args, sender, senderhost, channel = yield commands = {name: gen.__name__ for name, gen in bot.commands.items()} doc = [] if args: for arg in args: if arg: try: _gen = getattr(thismodule, commands[arg]) doc.append(formatting.colored(arg + ": ", "red") + formatting.colored(_gen.__doc__, "dark_blue")) except (AttributeError, KeyError): doc.append(formatting.colored("No command called ", "red") + formatting.colored(arg, "dark_green")) else: doc = [", ".join(commands)] for d in doc: bot.msg(channel, d, length=510)
def rand(bot): """Randomizer, opt args: 'range int1 int2', 'frange float1 float2' or \ list of choices""" while True: args, sender, senderhost, channel = yield try: if not args: result = random.choice(["Heads", "Tails"]) elif args[0].lower() == "range": result = str(random.randint(int(args[1]), int(args[2]))) elif args[0].lower() == "frange": result = str(random.uniform(float(args[1]), float(args[2]))) else: result = random.choice(args) except (IndexError, ValueError): result = formatting.colored("Invalid call - check the help", "red") bot.msg(channel, result)
def commits_to_irc(self, repo_name, commits, github=False): for i, commit in enumerate(commits): if i == 3: self.report_to_irc(repo_name, "+{} more commits".format( len(commits) - 3)) break if github: url = yield shorten_github_url(commit["url"]) else: url = commit["url"] message = unidecode(commit["message"].split("\n")[0]) if len(message) > 100: message = message[:100] + "..." self.report_to_irc(repo_name, "{author}: {message} ({url})".format( author=colored(unidecode(commit["author"]["name"]), "dark_cyan"), message=message, url=url))
def commits_to_irc(self, repo_name, commits, github=False): for i, commit in enumerate(commits): if i == 3: self.report_to_irc(repo_name, "+{} more commits".format(len(commits) - 3)) break if github: url = yield shorten_github_url(commit["url"]) else: url = commit["url"] message = unidecode(commit["message"].split("\n")[0]) if len(message) > 100: message = message[:100] + "..." self.report_to_irc( repo_name, "{author}: {message} ({url})".format(author=colored( unidecode(commit["author"]["name"]), "dark_cyan"), message=message, url=url))
def _do_ignore(is_admin, sender, args): if is_admin: if len(args) == 1 and args[0].lower() in ("ls", "list"): ignorelist = bot.get_ignorelist() if ignorelist: bot.notice(sender, ", ".join(ignorelist)) else: bot.notice(sender, "Ignorelist is empty") elif len(args) < 2: bot.notice(sender, "Too few arguments") else: task = args[0] nicks = args[1:] if task.lower() in ("+", "add"): for nick in nicks: # don't add to short nicks # may ignore everything otherwise(regex) if len(nick) > 3: bot.add_to_ignorelist(nick) bot.notice(sender, "Added {} to the ignore " "list".format(nick)) else: bot.notice(sender, "Pattern {} too short, must " "have at least 3 chars".format(nick)) elif task.lower() in ("-", "remove"): for nick in nicks: if bot.ignore_user(nick): bot.remove_from_ignorelist(nick) bot.notice(sender, "Removed {} from the ignore " "ignore list".format(nick)) else: bot.notice(sender, "{} was not found in the " "ignore list".format(nick)) else: bot.notice(sender, formatting.colored("Invalid call - check the" " help", "red"))
def on_gitlab_issue(self, data): repo_name = data["project"]["name"] attribs = data["object_attributes"] action = attribs["action"] if action == "open": action = colored("opened", "red") elif action == "reopen": action = colored("reopened", "red") elif action == "close": action = colored("closed", "dark_green") elif action == "update": action = "updated" msg = ("[{repo_name}] {user} {action} Issue #{number} {title} " "{url}".format(repo_name=colored(repo_name, "blue"), user=colored(data["user"]["name"], "dark_cyan"), action=action, number=colored(str(attribs["iid"]), "dark_yellow"), title=unidecode(attribs["title"]), url=attribs["url"])) self.report_to_irc(repo_name, msg)
def bot_help(bot): """Guess what this function does""" thismodule = sys.modules[__name__] while True: args, sender, senderhost, channel = yield commands = {name: gen.__name__ for name, gen in bot.commands.items()} aliases = [] for name, alias in bot.aliases.items(): aliases.append("{name} ({body})".format( name=name, body=" ".join([alias.command] + alias.arguments))) doc = [] if args: for arg in args: if arg: try: _gen = getattr(thismodule, commands[arg]) doc.append( formatting.colored(arg + ": ", "red") + formatting.colored( _gen.__doc__ or "No help available", "dark_blue")) except (AttributeError, KeyError): doc.append( formatting.colored("No command called ", "red") + formatting.colored(arg, "dark_green")) else: doc = [ formatting.colored("Commands: ", "dark_yellow") + ", ".join(commands) ] if aliases: doc.append( formatting.colored("Aliases: ", "dark_green") + ", ".join(aliases)) for d in doc: bot.msg(channel, d, length=510)
def fortune(bot): """Unix fortune: fortune --list for available fortunes, -l to \ allow long fortunes, -o to allow offensive fortunes""" paths = [r"/usr/share/fortune/", r"/usr/share/games/fortune/", r"/usr/share/fortunes/", r"/usr/share/games/fortunes/", fs.get_abs_path("fortunes")] num_lines_short = 3 parser = argparse.ArgumentParser() parser.add_argument("-l", action='store_true') parser.add_argument("-o", action='store_true') parser.add_argument("--list", action='store_true') parser.add_argument("files", nargs='*') def _display_filename(filename): """ Strip the fortune base path """ for path in paths: if filename.startswith(path): return filename.replace(path, "", 1).lstrip("/") def _find_files(offensive=False): """ Find all fortune files in the system """ fortune_files = [] # only one should be used, but check both anyways for path in paths: if not os.path.isdir(path): continue for root, dirs, files in os.walk(path): for f in files: if "." in f: continue if offensive or not _display_filename(root) == 'off': fortune_files.append(os.path.join(root, f)) return fortune_files def _get_random_fortune(filename, onlyshort=True): """ Get a random fortune out of the file <filename> """ with open(filename) as f: data = f.read() fortunes = data.split("\n%\n") # remove empty strings while "" in fortunes: fortunes.remove("") if onlyshort: for fortune in fortunes[:]: # last line has no "\n" if fortune.count("\n") >= num_lines_short: fortunes.remove(fortune) if not fortunes: return "No fortunes found" fortune = random.choice(fortunes) if _display_filename(filename).startswith("off/"): fortune = fortune.encode("rot13") return fortune while True: args, sender, senderhost, channel = yield options, unknown_options = parser.parse_known_args(args) if unknown_options: log.warn("Fortune: Unknown options: {options}", options=unknown_options) bot.msg(channel, formatting.colored("Invalid input for fortune", "red")) continue if options.list: fortunes = [] for f in _find_files(offensive=options.o): fortunes.append(_display_filename(f)) bot.msg(channel, "Available fortunes: {}".format( ", ".join(fortunes))) else: considered_files = [] only_short = not options.l if not options.files: # Don't use offensive fortunes by default considered_files = _find_files(offensive=options.o) else: for arg in options.files: for f in _find_files(offensive=True): if arg == _display_filename(f): considered_files.append(f) break # nothing found? if not considered_files: bot.msg(channel, "No fortunes found") else: result = _get_random_fortune(random.choice(considered_files), only_short) bot.msg(channel, result)
def fortune(bot): """Unix fortune: fortune --list for available fortunes, -l to \ allow long fortunes, -o to allow offensive fortunes""" paths = [ r"/usr/share/fortune/", r"/usr/share/games/fortune/", r"/usr/share/fortunes/", r"/usr/share/games/fortunes/", fs.get_abs_path("fortunes") ] num_lines_short = 3 parser = ArgParser(exit_on_error=False) parser.add_argument("-l", action='store_true') parser.add_argument("-o", action='store_true') parser.add_argument("--list", action='store_true') parser.add_argument("files", nargs='*') def _display_filename(filename): """ Strip the fortune base path """ for path in paths: if filename.startswith(path): return filename.replace(path, "", 1).lstrip("/") def _find_files(offensive=False): """ Find all fortune files in the system """ fortune_files = [] # only one should be used, but check both anyways for path in paths: if not os.path.isdir(path): continue for root, dirs, files in os.walk(path): for f in files: if "." in f: continue if offensive or not _display_filename(root) == 'off': fortune_files.append(os.path.join(root, f)) return fortune_files def _get_random_fortune(filename, onlyshort=True): """ Get a random fortune out of the file <filename> """ with open(filename) as f: data = f.read() fortunes = data.split("\n%\n") # remove empty strings while "" in fortunes: fortunes.remove("") if onlyshort: for fortune in fortunes[:]: # last line has no "\n" if fortune.count("\n") >= num_lines_short: fortunes.remove(fortune) if not fortunes: return "No fortunes found" fortune = random.choice(fortunes) if _display_filename(filename).startswith("off/"): fortune = fortune.encode("rot13") return fortune while True: args, sender, senderhost, channel = yield try: options, unknown_options = parser.parse_known_args(args) except Exception as e: log.warn("Error parsing fortune arguments: {e}", e=e) bot.msg(channel, formatting.colored("Invalid input for fortune", "red")) continue if unknown_options: log.warn("Fortune: Unknown options: {options}", options=unknown_options) bot.msg(channel, formatting.colored("Invalid input for fortune", "red")) continue if options.list: fortunes = [] for f in _find_files(offensive=options.o): fortunes.append(_display_filename(f)) bot.msg(channel, "Available fortunes: {}".format(", ".join(fortunes))) else: considered_files = [] only_short = not options.l if not options.files: # Don't use offensive fortunes by default considered_files = _find_files(offensive=options.o) else: for arg in options.files: for f in _find_files(offensive=True): if arg == _display_filename(f): considered_files.append(f) break # nothing found? if not considered_files: bot.msg(channel, "No fortunes found") else: result = _get_random_fortune(random.choice(considered_files), only_short) bot.msg(channel, result)