A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tasks.py 5.0 KiB

13 years ago
13 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # -*- coding: utf-8 -*-
  2. # Manage wiki tasks from IRC, and check on thread status.
  3. import threading, re
  4. from irc.base_command import BaseCommand
  5. from irc.data import *
  6. from wiki import task_manager
  7. from config.main import *
  8. from config.irc import *
  9. class Tasks(BaseCommand):
  10. def get_hooks(self):
  11. return ["msg"]
  12. def get_help(self, command):
  13. return "Manage wiki tasks from IRC, and check on thread status."
  14. def check(self, data):
  15. if data.is_command and data.command in ["tasks", "threads", "tasklist"]:
  16. return True
  17. return False
  18. def process(self, data):
  19. self.data = data
  20. if data.host not in OWNERS:
  21. self.connection.reply(data, "at this time, you must be a bot owner to use this command.")
  22. return
  23. if not data.args:
  24. if data.command == "tasklist":
  25. self.do_list()
  26. else:
  27. self.connection.reply(data, "no arguments provided. Maybe you wanted '!{cmnd} list', '!{cmnd} start', or '!{cmnd} listall'?".format(cmnd=data.command))
  28. return
  29. if data.args[0] == "list":
  30. self.do_list()
  31. elif data.args[0] == "start":
  32. self.do_start()
  33. elif data.args[0] in ["listall", "all"]:
  34. self.do_listall()
  35. else: # they asked us to do something we don't know
  36. self.connection.reply(data, "unknown argument: \x0303{}\x0301.".format(data.args[0]))
  37. def do_list(self):
  38. threads = threading.enumerate()
  39. normal_threads = []
  40. task_threads = []
  41. for thread in threads:
  42. tname = thread.name
  43. if tname == "MainThread":
  44. tname = self.get_main_thread_name()
  45. normal_threads.append("\x0302{}\x0301 (as main thread, id {})".format(tname, thread.ident))
  46. elif tname in ["irc-frontend", "irc-watcher", "wiki-scheduler"]:
  47. normal_threads.append("\x0302{}\x0301 (id {})".format(tname, thread.ident))
  48. else:
  49. tname, start_time = re.findall("^(.*?) \((.*?)\)$")[0]
  50. task_threads.append("\x0302{}\x0301 (id {}, spawned at {})".format(tname, thread.ident, start_time))
  51. if task_threads:
  52. msg = "\x02{}\x0F threads active: {}, and \x02{}\x0F task threads: {}.".format(len(threads), ', '.join(normal_threads), len(task_threads), ', '.join(task_threads))
  53. else:
  54. msg = "\x02{}\x0F threads active: {}, and \x020\x0F task threads.".format(len(threads), ', '.join(normal_threads))
  55. self.connection.reply(self.data, msg)
  56. def do_listall(self):
  57. tasks = task_manager.task_list.keys()
  58. threadlist = threading.enumerate()
  59. threads = map(lambda t: t.name, threadlist)
  60. tasklist = []
  61. tasks.sort()
  62. for task in tasks:
  63. if task in threads:
  64. threads_running_task = [t for t in threads if t.name.startswith(task)]
  65. ids = map(lambda t: t.ident, threads_running_task)
  66. if len(ids) == 1:
  67. tasklist.append("\x0302{}\x0301 (\x02active\x0F as id {})".format(task, ids[0]))
  68. else:
  69. tasklist.append("\x0302{}\x0301 (\x02active\x0F as ids {})".format(task, ' ,'.join(ids)))
  70. else:
  71. tasklist.append("\x0302{}\x0301 (idle)".format(task))
  72. tasklist = ", ".join(tasklist)
  73. msg = "{} tasks loaded: {}.".format(len(tasks), tasklist)
  74. self.connection.reply(self.data, msg)
  75. def do_start(self):
  76. data = self.data
  77. try:
  78. task_name = data.args[1]
  79. except IndexError: # no task name given
  80. self.connection.reply(data, "what task do you want me to start?")
  81. return
  82. try:
  83. data.parse_kwargs()
  84. except KwargParseException, arg:
  85. self.connection.reply(data, "error parsing argument: \x0303{}\x0301.".format(arg))
  86. return
  87. if task_name not in task_manager.task_list.keys(): # this task does not exist or hasn't been loaded
  88. self.connection.reply(data, "task could not be found; either wiki/tasks/{}.py doesn't exist, or it wasn't loaded correctly.".format(task_name))
  89. return
  90. if data.kwargs:
  91. task_manager.start_task(task_name, **data.kwargs)
  92. self.connection.reply(data, "task \x0302{}\x0301 started with arguments: {}.".format(task_name, data.kwargs))
  93. else:
  94. task_manager.start_task(task_name)
  95. self.connection.reply(data, "task \x0302{}\x0301 started.".format(task_name))
  96. def get_main_thread_name(self):
  97. """Return the "proper" name of the MainThread; e.g. "irc-frontend" or "irc-watcher"."""
  98. if enable_irc_frontend:
  99. return "irc-frontend"
  100. elif enable_wiki_schedule:
  101. return "wiki-scheduler"
  102. else:
  103. return "irc-watcher"