A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

100 行
3.9 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. EarwigBot's IRC Front-end Component
  4. The IRC frontend runs on a normal IRC server and expects users to interact with
  5. it and give it commands. Commands are stored as "command classes", subclasses
  6. of BaseCommand in irc/base_command.py. All command classes are automatically
  7. imported by irc/command_handler.py if they are in irc/commands.
  8. """
  9. from re import findall
  10. from core import config
  11. from irc import command_handler
  12. from irc.classes import Connection, Data, BrokenSocketException
  13. connection = None
  14. def get_connection():
  15. """Return a new Connection() instance with information about our server
  16. connection, but don't actually connect yet."""
  17. cf = config.irc.frontend
  18. connection = Connection(cf.host, cf.port, cf.nick, cf.nick, cf.realname)
  19. return connection
  20. def startup(conn):
  21. """Accept a single arg, a Connection() object, and set our global variable
  22. 'connection' to it. Load all command classes in irc/commands with
  23. command_handler, and then establish a connection with the IRC server."""
  24. global connection
  25. connection = conn
  26. command_handler.load_commands(connection)
  27. connection.connect()
  28. def main():
  29. """Main loop for the Frontend IRC Bot component. get_connection() and
  30. startup() should have already been called."""
  31. read_buffer = str()
  32. while 1:
  33. try:
  34. read_buffer = read_buffer + connection.get()
  35. except BrokenSocketException:
  36. print "Socket has broken on front-end; restarting bot..."
  37. return
  38. lines = read_buffer.split("\n")
  39. read_buffer = lines.pop()
  40. for line in lines: # handle a single message from IRC
  41. line = line.strip().split()
  42. data = Data() # new Data() instance to store info about this line
  43. data.line = line
  44. if line[1] == "JOIN":
  45. data.nick, data.ident, data.host = findall(
  46. ":(.*?)!(.*?)@(.*?)\Z", line[0])[0]
  47. data.chan = line[2][1:]
  48. command_handler.check("join", data) # check for 'join' hooks in
  49. # our commands
  50. if line[1] == "PRIVMSG":
  51. data.nick, data.ident, data.host = findall(
  52. ":(.*?)!(.*?)@(.*?)\Z", line[0])[0]
  53. data.msg = ' '.join(line[3:])[1:]
  54. data.chan = line[2]
  55. if data.chan == config.irc.frontend.nick:
  56. # this is a privmsg to us, so set 'chan' as the nick of the
  57. # sender, then check for private-only command hooks
  58. data.chan = data.nick
  59. command_handler.check("msg_private", data)
  60. else:
  61. # check for public-only command hooks
  62. command_handler.check("msg_public", data)
  63. # check for command hooks that apply to all messages
  64. command_handler.check("msg", data)
  65. # hardcode the !restart command (we can't restart from within
  66. # an ordinary command)
  67. if data.msg in ["!restart", ".restart"]:
  68. if data.host in config.irc.permissions["owners"]:
  69. print "Restarting bot per owner request..."
  70. return
  71. if line[0] == "PING": # if we are pinged, pong back to the server
  72. connection.send("PONG %s" % line[1])
  73. if line[1] == "376": # we've successfully connected to the network
  74. ns = config.irc.frontend.nickserv
  75. if ns: # if we're supposed to auth to nickserv, do that
  76. connection.say("NickServ", "IDENTIFY %s %s" % (ns.username,
  77. ns.password))
  78. # join all of our startup channels
  79. for chan in config.irc.frontend.channels:
  80. connection.join(chan)