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.

пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. # -*- coding: utf-8 -*-
  2. import threading
  3. import re
  4. from classes import BaseCommand, Data, KwargParseException
  5. import tasks
  6. import config
  7. class Command(BaseCommand):
  8. """Manage wiki tasks from IRC, and check on thread status."""
  9. name = "threads"
  10. def check(self, data):
  11. commands = ["tasks", "task", "threads", "tasklist"]
  12. if data.is_command and data.command in commands:
  13. return True
  14. return False
  15. def process(self, data):
  16. self.data = data
  17. if data.host not in config.irc["permissions"]["owners"]:
  18. msg = "you must be a bot owner to use this command."
  19. self.connection.reply(data, msg)
  20. return
  21. if not data.args:
  22. if data.command == "tasklist":
  23. self.do_list()
  24. else:
  25. msg = "no arguments provided. Maybe you wanted '!{0} list', '!{0} start', or '!{0} listall'?"
  26. self.connection.reply(data, msg.format(data.command))
  27. return
  28. if data.args[0] == "list":
  29. self.do_list()
  30. elif data.args[0] == "start":
  31. self.do_start()
  32. elif data.args[0] in ["listall", "all"]:
  33. self.do_listall()
  34. else: # They asked us to do something we don't know
  35. msg = "unknown argument: \x0303{0}\x0301.".format(data.args[0])
  36. self.connection.reply(data, msg)
  37. def do_list(self):
  38. """With !tasks list (or abbreviation !tasklist), list all running
  39. threads. This includes the main threads, like the irc frontend and the
  40. watcher, and task threads."""
  41. threads = threading.enumerate()
  42. normal_threads = []
  43. task_threads = []
  44. for thread in threads:
  45. tname = thread.name
  46. if tname == "MainThread":
  47. tname = self.get_main_thread_name()
  48. t = "\x0302{0}\x0301 (as main thread, id {1})"
  49. normal_threads.append(t.format(tname, thread.ident))
  50. elif tname in ["irc-frontend", "irc-watcher", "wiki-scheduler"]:
  51. t = "\x0302{0}\x0301 (id {1})"
  52. normal_threads.append(t.format(tname, thread.ident))
  53. elif tname.startswith("reminder"):
  54. tname = tname.replace("reminder ", "")
  55. t = "\x0302reminder\x0301 (until {0})"
  56. normal_threads.append(t.format(tname))
  57. else:
  58. tname, start_time = re.findall("^(.*?) \((.*?)\)$", tname)[0]
  59. t = "\x0302{0}\x0301 (id {1}, since {2})"
  60. task_threads.append(t.format(tname, thread.ident, start_time))
  61. if task_threads:
  62. msg = "\x02{0}\x0F threads active: {1}, and \x02{2}\x0F task threads: {3}."
  63. msg = msg.format(len(threads), ', '.join(normal_threads),
  64. len(task_threads), ', '.join(task_threads))
  65. else:
  66. msg = "\x02{0}\x0F threads active: {1}, and \x020\x0F task threads."
  67. msg = msg.format(len(threads), ', '.join(normal_threads))
  68. self.connection.reply(self.data, msg)
  69. def do_listall(self):
  70. """With !tasks listall or !tasks all, list all loaded tasks, and report
  71. whether they are currently running or idle."""
  72. all_tasks = tasks.get_all().keys()
  73. threads = threading.enumerate()
  74. tasklist = []
  75. all_tasks.sort()
  76. for task in all_tasks:
  77. threadlist = [t for t in threads if t.name.startswith(task)]
  78. ids = [str(t.ident) for t in threadlist]
  79. if not ids:
  80. tasklist.append("\x0302{0}\x0301 (idle)".format(task))
  81. elif len(ids) == 1:
  82. t = "\x0302{0}\x0301 (\x02active\x0F as id {1})"
  83. tasklist.append(t.format(task, ids[0]))
  84. else:
  85. t = "\x0302{0}\x0301 (\x02active\x0F as ids {1})"
  86. tasklist.append(t.format(task, ', '.join(ids)))
  87. tasklist = ", ".join(tasklist)
  88. msg = "{0} tasks loaded: {1}.".format(len(all_tasks), tasklist)
  89. self.connection.reply(self.data, msg)
  90. def do_start(self):
  91. """With !tasks start, start any loaded task by name with or without
  92. kwargs."""
  93. data = self.data
  94. try:
  95. task_name = data.args[1]
  96. except IndexError: # No task name given
  97. self.connection.reply(data, "what task do you want me to start?")
  98. return
  99. try:
  100. data.parse_kwargs()
  101. except KwargParseException, arg:
  102. msg = "error parsing argument: \x0303{0}\x0301.".format(arg)
  103. self.connection.reply(data, msg)
  104. return
  105. if task_name not in tasks.get_all().keys():
  106. # This task does not exist or hasn't been loaded:
  107. msg = "task could not be found; either bot/tasks/{0}.py doesn't exist, or it wasn't loaded correctly."
  108. self.connection.reply(data, msg.format(task_name))
  109. return
  110. data.kwargs["fromIRC"] = True
  111. tasks.start(task_name, **data.kwargs)
  112. msg = "task \x0302{0}\x0301 started.".format(task_name)
  113. self.connection.reply(data, msg)
  114. def get_main_thread_name(self):
  115. """Return the "proper" name of the MainThread."""
  116. if "irc_frontend" in config.components:
  117. return "irc-frontend"
  118. elif "wiki_schedule" in config.components:
  119. return "wiki-scheduler"
  120. else:
  121. return "irc-watcher"