소스 검색

tons of improvements, import fixes, cleanup, etc

tags/v0.1^2
Ben Kurtovic 13 년 전
부모
커밋
b0da4531b2
9개의 변경된 파일220개의 추가작업 그리고 199개의 파일을 삭제
  1. +3
    -3
      bot/classes/data.py
  2. +32
    -28
      bot/commands/__init__.py
  3. +2
    -3
      bot/config.py
  4. +71
    -63
      bot/frontend.py
  5. +7
    -13
      bot/main.py
  6. +42
    -39
      bot/tasks/__init__.py
  7. +50
    -37
      bot/watcher.py
  8. +10
    -10
      bot/watcher_logic.py
  9. +3
    -3
      earwigbot.py

+ 3
- 3
bot/classes/data.py 파일 보기

@@ -11,9 +11,9 @@ class KwargParseException(Exception):
pass pass


class Data(object): class Data(object):
def __init__(self):
"""store data from an individual line received on IRC"""
self.line = str()
def __init__(self, line):
"""Store data from an individual line received on IRC."""
self.line = line
self.chan = str() self.chan = str()
self.nick = str() self.nick = str()
self.ident = str() self.ident = str()


+ 32
- 28
bot/commands/__init__.py 파일 보기

@@ -5,29 +5,11 @@
import os import os
import traceback import traceback


commands = []
__all__ = ["load", "get_all", "check"]


def load_commands(connection):
"""load all valid command classes from irc/commmands/ into the commands variable"""
files = os.listdir(os.path.join("irc", "commands")) # get all files in irc/commands/
files.sort() # alphabetically sort list of files
_commands = []


for f in files:
if f.startswith("_") or not f.endswith(".py"): # ignore non-python files or files beginning with "_"
continue
module = f[:-3] # strip .py from end
try:
exec "from irc.commands import %s" % module
except: # importing the file failed for some reason...
print "Couldn't load file %s:" % f
traceback.print_exc()
continue
process_module(connection, eval(module)) # 'module' is a string, so get the actual object for processing by eval-ing it

pretty_cmnds = map(lambda c: c.__class__.__name__, commands)
print "Found %s command classes: %s." % (len(commands), ', '.join(pretty_cmnds))

def process_module(connection, module):
def _process_module(connection, module):
"""go through all objects in a module and add valid command classes to the commands variable""" """go through all objects in a module and add valid command classes to the commands variable"""
global commands global commands
objects = dir(module) objects = dir(module)
@@ -43,19 +25,41 @@ def process_module(connection, module):
for base in bases: for base in bases:
if base.__name__ == "BaseCommand": # this inherits BaseCommand, so it must be a command class if base.__name__ == "BaseCommand": # this inherits BaseCommand, so it must be a command class
command = obj(connection) # initialize a new command object command = obj(connection) # initialize a new command object
commands.append(command)
_commands.append(command)
print "Added command class %s from %s..." % (this_obj, module.__name__) print "Added command class %s from %s..." % (this_obj, module.__name__)
continue continue


def get_commands():
"""get our commands"""
return commands
def load(connection):
"""load all valid command classes from irc/commmands/ into the commands variable"""
files = os.listdir(os.path.join("irc", "commands")) # get all files in irc/commands/
files.sort() # alphabetically sort list of files

for f in files:
if f.startswith("_") or not f.endswith(".py"): # ignore non-python files or files beginning with "_"
continue
module = f[:-3] # strip .py from end
try:
exec "from irc.commands import %s" % module
except: # importing the file failed for some reason...
print "Couldn't load file %s:" % f
traceback.print_exc()
continue
process_module(connection, eval(module)) # 'module' is a string, so get the actual object for processing by eval-ing it

pretty_cmnds = map(lambda c: c.__class__.__name__, commands)
print "Found %s command classes: %s." % (len(commands), ', '.join(pretty_cmnds))

def get_all():
"""Return our list of all commands."""
return _commands


def check(hook, data): def check(hook, data):
"""given an event on IRC, check if there's anything we can respond to by calling each command class"""
data.parse_args() # parse command arguments into data.command and data.args
"""Given an event on IRC, check if there's anything we can respond to by
calling each command class"""
# parse command arguments into data.command and data.args
data.parse_args()


for command in commands:
for command in _commands:
if hook in command.get_hooks(): if hook in command.get_hooks():
if command.check(data): if command.check(data):
try: try:


+ 2
- 3
bot/config.py 파일 보기

@@ -18,9 +18,9 @@ from within config's three global variables and one function:
""" """


import json import json
from os import makedirs, path
from os import path


from lib import blowfish
import blowfish


script_dir = path.dirname(path.abspath(__file__)) script_dir = path.dirname(path.abspath(__file__))
root_dir = path.split(script_dir)[0] root_dir = path.split(script_dir)[0]
@@ -149,7 +149,6 @@ def schedule(minute, hour, month_day, month, week_day):


def make_new_config(): def make_new_config():
"""Make a new config file based on the user's input.""" """Make a new config file based on the user's input."""
makedirs(config_dir)


encrypt = raw_input("Would you like to encrypt passwords stored in " + encrypt = raw_input("Would you like to encrypt passwords stored in " +
"config.json? [y/n] ") "config.json? [y/n] ")


+ 71
- 63
bot/frontend.py 파일 보기

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-


""" """
EarwigBot's IRC Front-end Component
EarwigBot's IRC Frontend Component


The IRC frontend runs on a normal IRC server and expects users to interact with The IRC frontend runs on a normal IRC server and expects users to interact with
it and give it commands. Commands are stored as "command classes", subclasses it and give it commands. Commands are stored as "command classes", subclasses
@@ -9,13 +9,16 @@ of BaseCommand in irc/base_command.py. All command classes are automatically
imported by irc/command_handler.py if they are in irc/commands. imported by irc/command_handler.py if they are in irc/commands.
""" """


from re import findall
import re


from core import config
from irc import command_handler
from irc.classes import Connection, Data, BrokenSocketException
import config
import commands
from classes import Connection, Data, BrokenSocketException

__all__ = ["get_connection", "startup", "main"]


connection = None connection = None
sender_regex = re.compile(":(.*?)!(.*?)@(.*?)\Z")


def get_connection(): def get_connection():
"""Return a new Connection() instance with information about our server """Return a new Connection() instance with information about our server
@@ -31,16 +34,18 @@ def startup(conn):
command_handler, and then establish a connection with the IRC server.""" command_handler, and then establish a connection with the IRC server."""
global connection global connection
connection = conn connection = conn
command_handler.load_commands(connection)
commands.load(connection)
connection.connect() connection.connect()


def main(): def main():
"""Main loop for the Frontend IRC Bot component. get_connection() and
startup() should have already been called."""
"""Main loop for the frontend component.

get_connection() and startup() should have already been called before this.
"""
read_buffer = str() read_buffer = str()


while 1: while 1:
try:
try:
read_buffer = read_buffer + connection.get() read_buffer = read_buffer + connection.get()
except BrokenSocketException: except BrokenSocketException:
print "Socket has broken on front-end; restarting bot..." print "Socket has broken on front-end; restarting bot..."
@@ -48,57 +53,60 @@ def main():


lines = read_buffer.split("\n") lines = read_buffer.split("\n")
read_buffer = lines.pop() read_buffer = lines.pop()

for line in lines: # handle a single message from IRC
line = line.strip().split()
data = Data() # new Data() instance to store info about this line
data.line = line

if line[1] == "JOIN":
data.nick, data.ident, data.host = findall(
":(.*?)!(.*?)@(.*?)\Z", line[0])[0]
data.chan = line[2][1:]
command_handler.check("join", data) # check for 'join' hooks in
# our commands

if line[1] == "PRIVMSG":
data.nick, data.ident, data.host = findall(
":(.*?)!(.*?)@(.*?)\Z", line[0])[0]
data.msg = ' '.join(line[3:])[1:]
data.chan = line[2]

if data.chan == config.irc["frontend"]["nick"]:
# this is a privmsg to us, so set 'chan' as the nick of the
# sender, then check for private-only command hooks
data.chan = data.nick
command_handler.check("msg_private", data)
else:
# check for public-only command hooks
command_handler.check("msg_public", data)

# check for command hooks that apply to all messages
command_handler.check("msg", data)

# hardcode the !restart command (we can't restart from within
# an ordinary command)
if data.msg in ["!restart", ".restart"]:
if data.host in config.irc["permissions"]["owners"]:
print "Restarting bot per owner request..."
return

if line[0] == "PING": # if we are pinged, pong back to the server
connection.send("PONG %s" % line[1])

if line[1] == "376": # we've successfully connected to the network
try: # if we're supposed to auth to nickserv, do that
ns_username = config.irc["frontend"]["nickservUsername"]
ns_password = config.irc["frontend"]["nickservPassword"]
except KeyError:
pass
else:
connection.say("NickServ", "IDENTIFY {0} {1}".format(
ns_username, ns_password))
# join all of our startup channels
for chan in config.irc["frontend"]["channels"]:
connection.join(chan)
for line in lines:
_process_message(line)

def _process_message(line):
"""Process a single message from IRC."""
line = line.strip().split()
data = Data(line) # new Data instance to store info about this line

if line[1] == "JOIN":
data.nick, data.ident, data.host = sender_regex.findall(line[0])[0]
data.chan = line[2][1:]
# Check for 'join' hooks in our commands:
commands.check("join", data)

elif line[1] == "PRIVMSG":
data.nick, data.ident, data.host = sender_regex.findall(line[0])[0]
data.msg = ' '.join(line[3:])[1:]
data.chan = line[2]

if data.chan == config.irc["frontend"]["nick"]:
# This is a privmsg to us, so set 'chan' as the nick of the, sender
# then check for private-only command hooks:
data.chan = data.nick
commands.check("msg_private", data)
else:
# Check for public-only command hooks:
commands.check("msg_public", data)

# Check for command hooks that apply to all messages:
commands.check("msg", data)

# Hardcode the !restart command (we can't restart from within an
# ordinary command):
if data.msg in ["!restart", ".restart"]:
if data.host in config.irc["permissions"]["owners"]:
print "Restarting bot per owner request..."
return

# If we are pinged, pong back to the server:
if line[0] == "PING":
connection.send("PONG %s" % line[1])

# On successful connection to the server:
if line[1] == "376":
# If we're supposed to auth to NickServ, do that:
try:
username = config.irc["frontend"]["nickservUsername"]
password = config.irc["frontend"]["nickservPassword"]
except KeyError:
pass
else:
msg = " ".join(("IDENTIFY", username, password))
connection.say("NickServ", msg)

# Join all of our startup channels:
for chan in config.irc["frontend"]["channels"]:
connection.join(chan)

+ 7
- 13
bot/main.py 파일 보기

@@ -33,17 +33,11 @@ Else, the bot will stop, as no components are enabled.
import threading import threading
import time import time
import traceback import traceback
import sys
import os


script_dir = os.path.dirname(os.path.abspath(__file__))
root_dir = os.path.split(script_dir)[0] # the bot's "root" directory relative
# to its different components
sys.path.append(root_dir) # make sure we look in the root dir for modules

from core import config
from irc import frontend, watcher
from wiki import task_manager
import config
import frontend
import tasks
import watcher


f_conn = None f_conn = None
w_conn = None w_conn = None
@@ -70,7 +64,7 @@ def wiki_scheduler():
time_start = time.time() time_start = time.time()
now = time.gmtime(time_start) now = time.gmtime(time_start)


task_manager.start_tasks(now)
tasks.schedule(now)


time_end = time.time() time_end = time.time()
time_diff = time_start - time_end time_diff = time_start - time_end
@@ -89,7 +83,7 @@ def irc_frontend():


if "wiki_schedule" in config.components: if "wiki_schedule" in config.components:
print "\nStarting wiki scheduler..." print "\nStarting wiki scheduler..."
task_manager.load_tasks()
tasks.load()
t_scheduler = threading.Thread(target=wiki_scheduler) t_scheduler = threading.Thread(target=wiki_scheduler)
t_scheduler.name = "wiki-scheduler" t_scheduler.name = "wiki-scheduler"
t_scheduler.daemon = True t_scheduler.daemon = True
@@ -123,7 +117,7 @@ def run():


elif "wiki_schedule" in enabled: # run the scheduler on the main elif "wiki_schedule" in enabled: # run the scheduler on the main
print "Starting wiki scheduler..." # thread, but also run the IRC print "Starting wiki scheduler..." # thread, but also run the IRC
task_manager.load_tasks() # watcher on another thread iff it
tasks.load() # watcher on another thread iff it
if "irc_watcher" in enabled: # is enabled if "irc_watcher" in enabled: # is enabled
print "\nStarting IRC watcher..." print "\nStarting IRC watcher..."
t_watcher = threading.Thread(target=irc_watcher, args=()) t_watcher = threading.Thread(target=irc_watcher, args=())


+ 42
- 39
bot/tasks/__init__.py 파일 보기

@@ -1,9 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-


""" """
EarwigBot's Wiki Bot Task Manager
EarwigBot's Wiki Task Manager


This module provides some functions to run and load bot tasks from wiki/tasks/.
This package provides the wiki bot "tasks" EarwigBot runs. Here in __init__,
you can find some functions used to load and run these tasks.
""" """


import time import time
@@ -11,28 +12,17 @@ import traceback
import threading import threading
import os import os


from core import config
import config

__all__ = ["load", "schedule", "start"]


# store loaded tasks as a dict where the key is the task name and the value is # store loaded tasks as a dict where the key is the task name and the value is
# an instance of the task class (wiki.tasks.task_file.Task()) # an instance of the task class (wiki.tasks.task_file.Task())
task_list = dict()
_tasks = dict()


def load_tasks():
"""Load all valid task classes from wiki/tasks/, and add them to the
task_list variable."""
files = os.listdir(os.path.join("wiki", "tasks"))
files.sort() # alphabetically sort all files in wiki/tasks/
for f in files:
if not os.path.isfile(os.path.join("wiki", "tasks", f)):
continue # ignore non-files
if f.startswith("_") or not f.endswith(".py"):
continue # ignore non-python files or files beginning with an _
load_class_from_file(f)
print "Found %s tasks: %s." % (len(task_list), ', '.join(task_list.keys()))

def load_class_from_file(f):
def _load_class_from_file(f):
"""Look in a given file for the task class.""" """Look in a given file for the task class."""
global task_list
global _tasks


module = f[:-3] # strip .py from end module = f[:-3] # strip .py from end
try: try:
@@ -48,45 +38,58 @@ def load_class_from_file(f):
traceback.print_exc() traceback.print_exc()
return return
task_name = task_class.task_name task_name = task_class.task_name
task_list[task_name] = task_class()
print "Added task %s from wiki/tasks/%s..." % (task_name, f)
_tasks[task_name] = task_class()
print "Added task %s from bot/tasks/%s..." % (task_name, f)

def _wrapper(task, **kwargs):
"""Wrapper for task classes: run the task and catch any errors."""
try:
task.run(**kwargs)
except:
print "Task '{0}' raised an exception and had to stop:".format(task.task_name)
traceback.print_exc()
else:
print "Task '{0}' finished without error.".format(task.task_name)


def start_tasks(now=time.gmtime()):
def load():
"""Load all valid task classes from bot/tasks/, and add them to the
_tasks variable."""
files = os.listdir(os.path.join("bot", "tasks"))
files.sort() # alphabetically sort all files in wiki/tasks/
for f in files:
if not os.path.isfile(os.path.join("bot", "tasks", f)):
continue # ignore non-files
if f.startswith("_") or not f.endswith(".py"):
continue # ignore non-python files or files beginning with an _
load_class_from_file(f)
print "Found %s tasks: %s." % (len(_tasks), ', '.join(_tasks.keys()))

def schedule(now=time.gmtime()):
"""Start all tasks that are supposed to be run at a given time.""" """Start all tasks that are supposed to be run at a given time."""
tasks = config.schedule(now.tm_min, now.tm_hour, now.tm_mday, now.tm_mon, tasks = config.schedule(now.tm_min, now.tm_hour, now.tm_mday, now.tm_mon,
now.tm_wday) # get list of tasks to run this turn now.tm_wday) # get list of tasks to run this turn


for task in tasks: for task in tasks:
if isinstance(task, list): # they've specified kwargs
start_task(task[0], **task[1]) # so pass those to start_task
if isinstance(task, list): # they've specified kwargs
start(task[0], **task[1]) # so pass those to start_task
else: # otherwise, just pass task_name else: # otherwise, just pass task_name
start_task(task)
start(task)


def start_task(task_name, **kwargs):
def start(task_name, **kwargs):
"""Start a given task in a new thread. Pass args to the task's run() """Start a given task in a new thread. Pass args to the task's run()
function.""" function."""
print "Starting task '{0}' in a new thread...".format(task_name) print "Starting task '{0}' in a new thread...".format(task_name)


try: try:
task = task_list[task_name]
task = _tasks[task_name]
except KeyError: except KeyError:
print ("Couldn't find task '{0}': wiki/tasks/{0}.py does not exist.").format(task_name)
print ("Couldn't find task '{0}': bot/tasks/{0}.py does not exist.").format(task_name)
return return


task_thread = threading.Thread(target=lambda: task_wrapper(task, **kwargs))
task_thread = threading.Thread(target=lambda: _wrapper(task, **kwargs))
task_thread.name = "{0} ({1})".format(task_name, time.strftime("%b %d %H:%M:%S")) task_thread.name = "{0} ({1})".format(task_name, time.strftime("%b %d %H:%M:%S"))


# stop bot task threads automagically if the main bot stops # stop bot task threads automagically if the main bot stops
task_thread.daemon = True task_thread.daemon = True


task_thread.start() task_thread.start()

def task_wrapper(task, **kwargs):
"""Wrapper for task classes: run the task and catch any errors."""
try:
task.run(**kwargs)
except:
print "Task '{0}' raised an exception and had to stop:".format(task.task_name)
traceback.print_exc()
else:
print "Task '{0}' finished without error.".format(task.task_name)

+ 50
- 37
bot/watcher.py 파일 보기

@@ -10,25 +10,30 @@ wiki bot tasks being started (listed in wiki/tasks/) or messages being sent to
channels in the IRC frontend. channels in the IRC frontend.
""" """


from core import config
from irc.classes import Connection, RC, BrokenSocketException
from irc import watcher_logic
import config
from classes import Connection, RC, BrokenSocketException
import watcher_logic as logic


frontend_conn = None frontend_conn = None


def get_connection(): def get_connection():
"""Return a new Connection() instance with information about our server
connection, but don't actually connect yet."""
"""Return a new Connection() instance with connection information.

Don't actually connect yet.
"""
cf = config.irc["watcher"] cf = config.irc["watcher"]
connection = Connection(cf["host"], cf["port"], cf["nick"], cf["ident"], connection = Connection(cf["host"], cf["port"], cf["nick"], cf["ident"],
cf["realname"]) cf["realname"])
return connection return connection


def main(connection, f_conn=None): def main(connection, f_conn=None):
"""Main loop for the Watcher IRC Bot component. get_connection() should
have already been called and the connection should have been started with
connection.connect(). Accept the frontend connection as well as an optional
parameter in order to send messages directly to frontend IRC channels."""
"""Main loop for the Watcher IRC Bot component.
get_connection() should have already been called and the connection should
have been started with connection.connect(). Accept the frontend connection
as well as an optional parameter in order to send messages directly to
frontend IRC channels.
"""
global frontend_conn global frontend_conn
frontend_conn = f_conn frontend_conn = f_conn
read_buffer = str() read_buffer = str()
@@ -43,34 +48,42 @@ def main(connection, f_conn=None):
read_buffer = lines.pop() read_buffer = lines.pop()


for line in lines: for line in lines:
line = line.strip().split()

if line[1] == "PRIVMSG":
chan = line[2]

# ignore messages originating from channels not in our list, to
# prevent someone PMing us false data
if chan not in config.irc["watcher"]["channels"]:
continue

msg = ' '.join(line[3:])[1:]
rc = RC(msg) # new RC object to store this event's data
rc.parse() # parse a message into pagenames, usernames, etc.
process(rc) # report to frontend channels or start tasks

if line[0] == "PING": # if we are pinged, pong back to the server
connection.send("PONG %s" % line[1])

# when we've finished starting up, join all watcher channels
if line[1] == "376":
for chan in config.irc["watcher"]["channels"]:
connection.join(chan)

def process(rc):
"""Process a message from IRC (technically, an RC object). The actual
processing is configurable, so we don't have that hard-coded here. We
simply call irc/watcher_logic.py's process() function and expect a list of
channels back, which we report the event data to."""
_process_message(line)

def _process_message(line):
"""Process a single message from IRC."""
line = line.strip().split()

if line[1] == "PRIVMSG":
chan = line[2]

# Ignore messages originating from channels not in our list, to prevent
# someone PMing us false data:
if chan not in config.irc["watcher"]["channels"]:
continue

msg = ' '.join(line[3:])[1:]
rc = RC(msg) # new RC object to store this event's data
rc.parse() # parse a message into pagenames, usernames, etc.
process_rc(rc) # report to frontend channels or start tasks

# If we are pinged, pong back to the server:
elif line[0] == "PING":
msg = " ".join(("PONG", line[1]))
connection.send(msg)

# When we've finished starting up, join all watcher channels:
elif line[1] == "376":
for chan in config.irc["watcher"]["channels"]:
connection.join(chan)

def process_rc(rc):
"""Process a recent change event from IRC (or, an RC object).

The actual processing is configurable, so we don't have that hard-coded
here. We simply call watcher_logic's process() function and expect a list
of channels back, which we report the event data to.
"""
chans = watcher_logic.process(rc) chans = watcher_logic.process(rc)
if chans and frontend_conn: if chans and frontend_conn:
pretty = rc.get_pretty() pretty = rc.get_pretty()


+ 10
- 10
bot/watcher_logic.py 파일 보기

@@ -12,7 +12,7 @@ sense for this sort of thing... so...


import re import re


from wiki import task_manager as tasks
import tasks


afc_prefix = "wikipedia( talk)?:(wikiproject )?articles for creation" afc_prefix = "wikipedia( talk)?:(wikiproject )?articles for creation"


@@ -39,8 +39,8 @@ def process(rc):
chans.update(("##earwigbot", "#wikipedia-en-afc")) chans.update(("##earwigbot", "#wikipedia-en-afc"))
if r_page.search(page_name): if r_page.search(page_name):
tasks.start_task("afc_statistics", action="process_edit", page=rc.page)
tasks.start_task("afc_copyvios", action="process_edit", page=rc.page)
tasks.start("afc_statistics", action="process_edit", page=rc.page)
tasks.start("afc_copyvios", action="process_edit", page=rc.page)
chans.add("#wikipedia-en-afc") chans.add("#wikipedia-en-afc")
elif r_ffu.match(page_name): elif r_ffu.match(page_name):
@@ -50,22 +50,22 @@ def process(rc):
chans.add("#wikipedia-en-afc") chans.add("#wikipedia-en-afc")
elif rc.flags == "move" and (r_move1.match(comment) or elif rc.flags == "move" and (r_move1.match(comment) or
r_move2.match(comment)):
r_move2.match(comment)):
p = r_moved_pages.findall(rc.comment)[0] p = r_moved_pages.findall(rc.comment)[0]
tasks.start_task("afc_statistics", action="process_move", pages=p)
tasks.start_task("afc_copyvios", action="process_move", pages=p)
tasks.start("afc_statistics", action="process_move", pages=p)
tasks.start("afc_copyvios", action="process_move", pages=p)
chans.add("#wikipedia-en-afc") chans.add("#wikipedia-en-afc")
elif rc.flags == "delete" and r_delete.match(comment): elif rc.flags == "delete" and r_delete.match(comment):
p = r_deleted_page.findall(rc.comment)[0] p = r_deleted_page.findall(rc.comment)[0]
tasks.start_task("afc_statistics", action="process_delete", page=p)
tasks.start_task("afc_copyvios", action="process_delete", page=p)
tasks.start("afc_statistics", action="process_delete", page=p)
tasks.start("afc_copyvios", action="process_delete", page=p)
chans.add("#wikipedia-en-afc") chans.add("#wikipedia-en-afc")
elif rc.flags == "restore" and r_restore.match(comment): elif rc.flags == "restore" and r_restore.match(comment):
p = r_restored_page.findall(rc.comment)[0] p = r_restored_page.findall(rc.comment)[0]
tasks.start_task("afc_statistics", action="process_restore", page=p)
tasks.start_task("afc_copyvios", action="process_restore", page=p)
tasks.start("afc_statistics", action="process_restore", page=p)
tasks.start("afc_copyvios", action="process_restore", page=p)
chans.add("#wikipedia-en-afc") chans.add("#wikipedia-en-afc")
elif rc.flags == "protect" and r_protect.match(comment): elif rc.flags == "protect" and r_protect.match(comment):


+ 3
- 3
earwigbot.py 파일 보기

@@ -20,7 +20,7 @@ from os import path
from sys import executable from sys import executable
from time import sleep from time import sleep


from core.config import verify_config
from bot import config


__author__ = "Ben Kurtovic" __author__ = "Ben Kurtovic"
__copyright__ = "Copyright (C) 2009, 2010, 2011 by Ben Kurtovic" __copyright__ = "Copyright (C) 2009, 2010, 2011 by Ben Kurtovic"
@@ -28,12 +28,12 @@ __license__ = "MIT License"
__version__ = "0.1-dev" __version__ = "0.1-dev"
__email__ = "ben.kurtovic@verizon.net" __email__ = "ben.kurtovic@verizon.net"


bot_script = path.join(path.dirname(path.abspath(__file__)), "core", "main.py")
bot_script = path.join(path.dirname(path.abspath(__file__)), "bot", "main.py")


def main(): def main():
print "EarwigBot v{0}\n".format(__version__) print "EarwigBot v{0}\n".format(__version__)


is_encrypted = verify_config()
is_encrypted = config.verify_config()
if is_encrypted: # passwords in the config file are encrypted if is_encrypted: # passwords in the config file are encrypted
key = getpass("Enter key to unencrypt bot passwords: ") key = getpass("Enter key to unencrypt bot passwords: ")
else: else:


불러오는 중...
취소
저장