A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

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