diff --git a/earwigbot/config/script.py b/earwigbot/config/script.py index 40e8ff2..f4b912a 100644 --- a/earwigbot/config/script.py +++ b/earwigbot/config/script.py @@ -22,7 +22,9 @@ from collections import OrderedDict from getpass import getpass +from os import chmod import re +import stat from textwrap import fill, wrap try: @@ -56,14 +58,18 @@ class ConfigScript(object): ("schedule", []) ) - def _print(self, msg): - print fill(re.sub("\s\s+", " ", msg), self.WIDTH) + self.wmf = False + self.proj = None + self.lang = None + + def _print(self, text): + print fill(re.sub("\s\s+", " ", text), self.WIDTH) def _ask(self, text, default=None): text = "> " + text if default: text += " [{0}]".format(default) - lines = wrap(re.sub("\s\s+", " ", msg), self.WIDTH) + lines = wrap(re.sub("\s\s+", " ", text), self.WIDTH) if len(lines) > 1: print "\n".join(lines[:-1]) return raw_input(lines[-1] + " ") or default @@ -74,7 +80,7 @@ class ConfigScript(object): text += " [Y/n]" else: text += " [y/N]" - lines = wrap(re.sub("\s\s+", " ", msg), self.WIDTH) + lines = wrap(re.sub("\s\s+", " ", text), self.WIDTH) if len(lines) > 1: print "\n".join(lines[:-1]) while True: @@ -86,6 +92,9 @@ class ConfigScript(object): if answer.startswith("n"): return False + def _ask_list(self, text): + pass + def _set_metadata(self): print self.data["metadata"] = OrderedDict(("version", 1)) @@ -140,7 +149,7 @@ class ConfigScript(object): self.config.wiki._load(self.data["wiki"]) print "Trying to login to the site...", try: - site = self.config.bot.wiki.add_site(**kargs) + site = self.config.bot.wiki.add_site(**kwargs) except exceptions.APIError: print " API error!" question = "Would you like to re-enter the site information?" @@ -168,20 +177,20 @@ class ConfigScript(object): def _set_wiki(self): print - wmf = self._ask_bool("""Will this bot run on Wikimedia Foundation - wikis, like Wikipedia?""") - if wmf: + self.wmf = self._ask_bool("""Will this bot run on Wikimedia Foundation + wikis, like Wikipedia?""") + if self.wmf: msg = "Site project (e.g. 'wikipedia', 'wiktionary', 'wikimedia'):" - project = self._ask(msg, default="wikipedia").lower() + self.proj = project = self._ask(msg, default="wikipedia").lower() msg = "Site language code (e.g. 'en', 'fr', 'commons'):" - lang = self._ask(msg, default="en").lower() + self.lang = lang = self._ask(msg, default="en").lower() kwargs = {"project": project, "lang": lang} else: msg = "Site base URL, without the script path and trailing slash;" msg += " can be protocol-insensitive (e.g. '//en.wikipedia.org'):" url = self._ask(msg) script = self._ask("Site script path:", default="/w") - kwargs = {"base_url": url, "script_path": script, "sql": sql} + kwargs = {"base_url": url, "script_path": script} self.data["wiki"]["username"] = self._ask("Bot username:") self.data["wiki"]["password"] = getpass("> Bot password: ") @@ -194,11 +203,11 @@ class ConfigScript(object): self.data["wiki"]["defaultSite"] = self._login(kwargs).name self.data["wiki"]["sql"] = {} - if wmf: + if self.wmf: msg = "Will this bot run from the Wikimedia Toolserver?" toolserver = self._ask_bool(msg, default=False) if toolserver: - args = (("host", "$1-p.rrdb.toolserver.org"), ("db": "$1_p")) + args = (("host", "$1-p.rrdb.toolserver.org"), ("db", "$1_p")) self.data["wiki"]["sql"] = OrderedDict(args) self.data["wiki"]["shutoff"] = {} @@ -216,9 +225,68 @@ class ConfigScript(object): self.data["wiki"]["search"] = {} def _set_irc(self): - # create permissions.db with us if frontend - # create rules.py if watcher - pass + if self.data["components"]["irc_frontend"]: + print + frontend = self.data["irc"]["frontend"] = OrderedDict() + msg = "Hostname of the frontend's IRC server, without 'irc://'" + frontend["host"] = self._ask(msg, "irc.freenode.net") + frontend["port"] = self._ask("Frontend port", 6667) + frontend["nick"] = self._ask("Frontend bot's nickname") + frontend["ident"] = self._ask("Frontend bot's ident", + frontend["nick"].lower()) + question = "Frontend bot's real name (gecos)" + frontend["realname"] = self._ask(question) + if self._ask_bool("Should the bot identify to NickServ?"): + frontend["nickservUsername"] = self._ask("NickServ username", + frontend["nick"]) + frontend["nickservPassword"] = getpass("> Nickserv password: ") + chan_question = "Frontend channels to join by default" + frontend["channels"] = self._ask_list(chan_question) + self._print("""The bot keeps a database of its admins (users who + can use certain sensitive commands) and owners + (users who can quit the bot and modify its access + list), identified by nick, ident, and/or hostname. + Hostname is most secure since it cannot be easily + spoofed. If you have a cloak, it will probably look + like 'wikipedia/Username' or + 'unaffiliated/nickname'.""") + host = self._ask("Your hostname on the IRC frontend") + if host: + self.config._permissions.load() + self.config._permissions.add_owner(host=host) + self.config._permissions.add_admin(host=host) + else: + frontend = {} + + if self.data["components"]["irc_watcher"]: + print + watcher = self.data["irc"]["watcher"] = OrderedDict() + if self.wmf: + watcher["host"] = "irc.wikimedia.org" + watcher["port"] = 6667 + else: + msg = "Hostname of the watcher's IRC server, without 'irc://'" + watcher["host"] = self._ask(msg) + watcher["port"] = self._ask("Watcher port", 6667) + watcher["nick"] = self._ask("Watcher bot's nickname", + frontend.get("nick")) + watcher["ident"] = self._ask("Watcher bot's ident", + watcher["nick"].lower()) + question = "Watcher bot's real name (gecos)" + watcher["realname"] = self._ask(question, frontend.get("realname")) + watcher_ns = "Should the bot identify to NickServ?" + if not self.wmf and self._ask_bool(watcher_ns): + watcher["nickservUsername"] = self._ask("NickServ username", + watcher["nick"]) + watcher["nickservPassword"] = getpass("> Nickserv password: ") + if self.wmf: + watcher["channels"] = ["#{0}.{1}".format(self.lang, self.proj)] + else: + chan_question = "Watcher channels to join" + watcher["channels"] = self._ask_list(chan_question) + # create rules.py + + self.data["irc"]["version"] = "EarwigBot - $1 - Python/$2 https://github.com/earwig/earwigbot" def _set_commands(self): # disable: True if no IRC frontend or prompted @@ -234,8 +302,10 @@ class ConfigScript(object): pass def _save(self): - with open(self.config.path, "w") as fp: - yaml.dump(self.data, stream=fp, default_flow_style=False) + open(self.config.path, "w").close() + chmod(self.config.path, stat.S_IRUSR|stat.S_IWUSR) + with open(self.config.path, "w") as stream: + yaml.dump(self.data, stream=stream, default_flow_style=False) def make_new(self): """Make a new config file based on the user's input."""