|
- # -*- coding: utf-8 -*-
-
- ## EarwigBot's Core
-
- ## EarwigBot has three components that can run independently of each other: an
- ## IRC front-end, an IRC watcher, and a wiki scheduler.
- ## * The IRC front-end runs on a normal IRC server and expects users to
- ## interact with it/give it commands.
- ## * The IRC watcher runs on a wiki recent-changes server and listens for
- ## edits. Users cannot interact with this part of the bot.
- ## * The wiki scheduler runs wiki-editing bot tasks in separate threads at
- ## user-defined times through a cron-like interface.
-
- ## There is a "priority" system here:
- ## 1. If the IRC frontend is enabled, it will run on the main thread, and the
- ## IRC watcher and wiki scheduler (if enabled) will run on separate threads.
- ## 2. If the wiki scheduler is enabled, it will run on the main thread, and the
- ## IRC watcher (if enabled) will run on a separate thread.
- ## 3. If the IRC watcher is enabled, it will run on the main (and only) thread.
- ## Else, the bot will stop, as no components are enabled.
-
- import threading
- import time
- import traceback
- import sys
- import os
-
- parent_dir = os.path.split(sys.path[0])[0]
- sys.path.append(parent_dir) # make sure we look in the parent directory for modules
-
- from core import config
- from irc import frontend, watcher
- from wiki import task_manager
-
- f_conn = None
- w_conn = None
-
- def irc_watcher(f_conn):
- """Function to handle the IRC watcher as another thread (if frontend and/or
- scheduler is enabled), otherwise run as the main thread."""
- global w_conn
- print "\nStarting IRC watcher..."
- while 1: # restart the watcher component if (just) it breaks
- w_conn = watcher.get_connection()
- w_conn.connect()
- print # print a blank line here to signify that the bot has finished starting up
- try:
- watcher.main(w_conn, f_conn)
- except:
- traceback.print_exc()
- time.sleep(5) # sleep a bit before restarting watcher
- print "\nWatcher has stopped; restarting component..."
-
- def wiki_scheduler():
- """Function to handle the wiki scheduler as another thread, or as the
- primary thread if the IRC frontend is not enabled."""
- while 1:
- time_start = time.time()
- now = time.gmtime(time_start)
-
- task_manager.start_tasks(now)
-
- time_end = time.time()
- time_diff = time_start - time_end
- if time_diff < 60: # sleep until the next minute
- time.sleep(60 - time_diff)
-
- def irc_frontend():
- """If the IRC frontend is enabled, make it run on our primary thread, and
- enable the wiki scheduler and IRC watcher on new threads if they are
- enabled."""
- global f_conn
-
- print "\nStarting IRC frontend..."
- f_conn = frontend.get_connection()
- frontend.startup(f_conn)
-
- if enable_wiki_schedule:
- print "\nStarting wiki scheduler..."
- task_manager.load_tasks()
- t_scheduler = threading.Thread(target=wiki_scheduler)
- t_scheduler.name = "wiki-scheduler"
- t_scheduler.daemon = True
- t_scheduler.start()
-
- if enable_irc_watcher:
- t_watcher = threading.Thread(target=irc_watcher, args=(f_conn,))
- t_watcher.name = "irc-watcher"
- t_watcher.daemon = True
- t_watcher.start()
-
- frontend.main()
-
- if enable_irc_watcher:
- w_conn.close()
- f_conn.close()
-
- def run():
- config.load()
- components = config.config["main"]
-
- if components["enable_irc_frontend"]: # make the frontend run on our primary thread if enabled, and enable additional components through that function
- irc_frontend()
-
- elif components["enable_wiki_schedule"]: # the scheduler is enabled - run it on the main thread, but also run the IRC watcher on another thread if it is enabled
- print "\nStarting wiki scheduler..."
- task_manager.load_tasks()
- if enable_irc_watcher:
- t_watcher = threading.Thread(target=irc_watcher, args=(f_conn,))
- t_watcher.name = "irc-watcher"
- t_watcher.daemon = True
- t_watcher.start()
- wiki_scheduler()
-
- elif components["enable_irc_watcher"]: # the IRC watcher is our only enabled component, so run its function only and don't worry about anything else
- irc_watcher()
-
- else: # nothing is enabled!
- exit("\nNo bot parts are enabled; stopping...")
-
- if __name__ == "__main__":
- try:
- run()
- except KeyboardInterrupt:
- exit("\nKeyboardInterrupt: stopping main bot loop.")
|