Quellcode durchsuchen

A number of fixes; color and stdout flushing.

tags/v0.1^2
Ben Kurtovic vor 11 Jahren
Ursprung
Commit
110e83fb6b
2 geänderte Dateien mit 46 neuen und 21 gelöschten Zeilen
  1. +12
    -7
      earwigbot/config/__init__.py
  2. +34
    -14
      earwigbot/config/script.py

+ 12
- 7
earwigbot/config/__init__.py Datei anzeigen

@@ -117,6 +117,15 @@ class BotConfig(object):
"""Return a nice string representation of the BotConfig."""
return "<BotConfig at {0}>".format(self.root_dir)

def _handle_missing_config(self):
print "Config file missing or empty:", self._config_path
msg = "Would you like to create a config file now? [Y/n] "
choice = raw_input(msg)
if choice.lower().startswith("n"):
raise NoConfigError()
else:
ConfigScript(self).make_new()

def _load(self):
"""Load data from our JSON config file (config.yml) into self._data."""
filename = self._config_path
@@ -263,15 +272,11 @@ class BotConfig(object):
decrypted if they were decrypted earlier.
"""
if not path.exists(self._config_path):
print "Config file not found:", self._config_path
choice = raw_input("Would you like to create a config file now? [Y/n] ")
if choice.lower().startswith("n"):
raise NoConfigError()
else:
ConfigScript(self).make_new()

self._handle_missing_config()
self._load()
data = self._data
if not data:
self._handle_missing_config()
self.components._load(data.get("components", OrderedDict()))
self.wiki._load(data.get("wiki", OrderedDict()))
self.irc._load(data.get("irc", OrderedDict()))


+ 34
- 14
earwigbot/config/script.py Datei anzeigen

@@ -26,6 +26,7 @@ from hashlib import sha256
from os import chmod, mkdir, path
import re
import stat
import sys
from textwrap import fill, wrap

try:
@@ -60,6 +61,7 @@ def process(bot, rc):
class ConfigScript(object):
"""A script to guide a user through the creation of a new config file."""
WIDTH = 79
PROMPT = "\x1b[32m> \x1b[0m"
BCRYPT_ROUNDS = 12

def __init__(self, config):
@@ -82,24 +84,28 @@ class ConfigScript(object):
def _print(self, text):
print fill(re.sub("\s\s+", " ", text), self.WIDTH)

def _print_no_nl(self, text):
sys.stdout.write(fill(re.sub("\s\s+", " ", text), self.WIDTH))
sys.stdout.flush()

def _pause(self):
raw_input("> Press enter to continue: ")
raw_input(self.PROMPT + "Press enter to continue: ")

def _ask(self, text, default=None):
text = "> " + text
text = self.PROMPT + text
if default:
text += " [{0}]".format(default)
text += " \x1b[33m[{0}]\x1b[0m".format(default)
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

def _ask_bool(self, text, default=True):
text = "> " + text
text = self.PROMPT + text
if default:
text += " [Y/n]"
text += " \x1b[33m[Y/n]\x1b[0m"
else:
text += " [y/N]"
text += " \x1b[33m[y/N]\x1b[0m"
lines = wrap(re.sub("\s\s+", " ", text), self.WIDTH)
if len(lines) > 1:
print "\n".join(lines[:-1])
@@ -113,7 +119,7 @@ class ConfigScript(object):
return False

def _ask_pass(self, text):
password = getpass("> " + text + " ")
password = getpass(self.PROMPT + text + " ")
if self._cipher:
mod = len(password) % 8
if mod:
@@ -123,11 +129,11 @@ class ConfigScript(object):
return password

def _ask_list(self, text):
print fill(re.sub("\s\s+", " ", "> " + text), self.WIDTH)
print fill(re.sub("\s\s+", " ", self.PROMPT + text), self.WIDTH)
print "[one item per line; blank line to end]:"
result = []
while True:
line = raw_input("> ")
line = raw_input(self.PROMPT)
if line:
result.append(line)
else:
@@ -144,8 +150,9 @@ class ConfigScript(object):
the bot may be annoying.""")
if self._ask_bool("Encrypt stored passwords?"):
self.data["metadata"]["encryptPasswords"] = True
key = getpass("> Enter an encryption key: ")
print "Running {0} rounds of bcrypt...".format(self.BCRYPT_ROUNDS), # STDOUT
key = getpass(self.PROMPT + "Enter an encryption key: ")
msg = "Running {0} rounds of bcrypt...".format(self.BCRYPT_ROUNDS)
self._print_no_nl(msg)
signature = bcrypt.hashpw(key, bcrypt.gensalt(self.BCRYPT_ROUNDS))
self.data["metadata"]["signature"] = signature
self._cipher = Blowfish.new(sha256(key).digest())
@@ -153,6 +160,7 @@ class ConfigScript(object):
else:
self.data["metadata"]["encryptPasswords"] = False

print
self._print("""The bot can temporarily store its logs in the logs/
subdirectory. Error logs are kept for a month whereas
normal logs are kept for a week. If you disable this,
@@ -186,11 +194,12 @@ class ConfigScript(object):

def _login(self, kwargs):
self.config.wiki._load(self.data["wiki"])
print "Trying to login to the site...",
self._print_no_nl("Trying to connect to the site...")
try:
site = self.config.bot.wiki.add_site(**kwargs)
except exceptions.APIError:
except exceptions.APIError as exc:
print " API error!"
print "\x1b[31m" + exc.message + "\x1b[0m"
question = "Would you like to re-enter the site information?"
if self._ask_bool(question):
return self._set_wiki()
@@ -198,8 +207,9 @@ class ConfigScript(object):
if self._ask_bool(question, default=False):
raise exceptions.NoConfigError()
return self._set_wiki()
except exceptions.LoginError:
except exceptions.LoginError as exc:
print " login error!"
print "\x1b[31m" + exc.message + "\x1b[0m"
question = "Would you like to re-enter your login information?"
if self._ask_bool(question):
self.data["wiki"]["username"] = self._ask("Bot username:")
@@ -210,6 +220,13 @@ class ConfigScript(object):
return self._set_wiki()
self._print("""Moving on. You can modify the login information
stored in the bot's config in the future.""")
password = self.data["wiki"]["password"]
self.data["wiki"]["password"] = None # Clear so we don't login
self.config.wiki._load(self.data["wiki"])
self._print_no_nl("Trying to connect to the site...")
site = self.config.bot.wiki.add_site(**kwargs)
print " success."
self.data["wiki"]["password"] = password # Reset original value
else:
print " success."
return site
@@ -252,6 +269,7 @@ class ConfigScript(object):
self.data["wiki"]["shutoff"] = {}
msg = "Would you like to enable an automatic shutoff page for the bot?"
if self._ask_bool(msg):
print
self._print("""The page title can contain two wildcards: $1 will be
substituted with the bot's username, and $2 with the
current task number. This can be used to implement a
@@ -282,6 +300,7 @@ class ConfigScript(object):
frontend["nickservPassword"] = ns_pass
chan_question = "Frontend channels to join by default:"
frontend["channels"] = self._ask_list(chan_question)
print
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
@@ -327,6 +346,7 @@ class ConfigScript(object):
else:
chan_question = "Watcher channels to join by default:"
watcher["channels"] = self._ask_list(chan_question)
print
self._print("""I am now creating a blank 'rules.py' file, which
will determine how the bot handles messages received
from the IRC watcher. It contains a process()


Laden…
Abbrechen
Speichern