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.

126 line
4.6 KiB

  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. task_thread_num = 0
  42. for thread in threads:
  43. tname = thread.name
  44. if tname == "MainThread":
  45. tname = self.get_main_thread_name()
  46. normal_threads.append("\x0302{}\x0301 (as main thread, id {})".format(tname, thread.ident))
  47. elif tname in ["irc-frontend", "irc-watcher", "wiki-scheduler"]:
  48. normal_threads.append("\x0302{}\x0301 (id {})".format(tname, thread.ident))
  49. else:
  50. task_thread_num += 1
  51. task_threads.append("\x0302{}\x0301 (id {})".format(tname, thread.ident))
  52. if task_threads:
  53. msg = "\x02{}\x0F threads active: {}, and \x02{}\x0F task threads: {}.".format(len(threads), ', '.join(normal_threads), task_thread_num, ', '.join(task_threads))
  54. else:
  55. msg = "\x02{}\x0F threads active: {}, and \x020\x0F task threads.".format(len(threads), ', '.join(normal_threads))
  56. self.connection.reply(self.data, msg)
  57. def do_listall(self):
  58. tasks = task_manager.task_list.keys()
  59. threads = map(lambda t: t.name, threading.enumerate())
  60. tasklist = []
  61. tasks.sort()
  62. for task in tasks:
  63. if task in threads:
  64. tasklist.append("\x0302{}\x0301 (\x02active\x0F)".format(task))
  65. else:
  66. tasklist.append("\x0302{}\x0301 (idle)".format(task))
  67. tasklist = ", ".join(tasklist)
  68. msg = "{} tasks loaded: {}.".format(len(tasks), tasklist)
  69. self.connection.reply(self.data, msg)
  70. def do_start(self):
  71. data = self.data
  72. try:
  73. task_name = data.args[1]
  74. except IndexError: # no task name given
  75. self.connection.reply(data, "what task do you want me to start?")
  76. return
  77. try:
  78. data.parse_kwargs()
  79. except KwargParseException, arg:
  80. self.connection.reply(data, "error parsing argument: \x0303{}\x0301.".format(arg))
  81. return
  82. if task_name not in task_manager.task_list.keys(): # this task does not exist or hasn't been loaded
  83. 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))
  84. return
  85. if data.kwargs:
  86. task_manager.start_task(task_name, **data.kwargs)
  87. self.connection.reply(data, "task \x0302{}\x0301 started with arguments: {}.".format(task_name, data.kwargs))
  88. else:
  89. task_manager.start_task(task_name)
  90. self.connection.reply(data, "task \x0302{}\x0301 started.".format(task_name))
  91. def get_main_thread_name(self):
  92. """Return the "proper" name of the MainThread; e.g. "irc-frontend" or "irc-watcher"."""
  93. if enable_irc_frontend:
  94. return "irc-frontend"
  95. elif enable_wiki_schedule:
  96. return "wiki-scheduler"
  97. else:
  98. return "irc-watcher"