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 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # -*- coding: utf-8 -*-
  2. """
  3. EarwigBot's IRC Frontend 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. import logging
  10. import re
  11. import config
  12. import commands
  13. from classes import Connection, Data, BrokenSocketException
  14. __all__ = ["get_connection", "startup", "main"]
  15. connection = None
  16. logger = logging.getLogger("frontend")
  17. sender_regex = re.compile(":(.*?)!(.*?)@(.*?)\Z")
  18. def get_connection():
  19. """Return a new Connection() instance with information about our server
  20. connection, but don't actually connect yet."""
  21. cf = config.irc["frontend"]
  22. connection = Connection(cf["host"], cf["port"], cf["nick"], cf["ident"],
  23. cf["realname"], logger)
  24. return connection
  25. def startup(conn):
  26. """Accept a single arg, a Connection() object, and set our global variable
  27. 'connection' to it. Load all command classes in irc/commands with
  28. command_handler, and then establish a connection with the IRC server."""
  29. global connection
  30. connection = conn
  31. commands.load(connection)
  32. connection.connect()
  33. def main():
  34. """Main loop for the frontend component.
  35. get_connection() and startup() should have already been called before this.
  36. """
  37. read_buffer = str()
  38. while 1:
  39. try:
  40. read_buffer = read_buffer + connection.get()
  41. except BrokenSocketException:
  42. logger.warn("Socket has broken on front-end; restarting bot")
  43. return
  44. lines = read_buffer.split("\n")
  45. read_buffer = lines.pop()
  46. for line in lines:
  47. ret = _process_message(line)
  48. if ret:
  49. return
  50. def _process_message(line):
  51. """Process a single message from IRC."""
  52. line = line.strip().split()
  53. data = Data(line) # new Data instance to store info about this line
  54. if line[1] == "JOIN":
  55. data.nick, data.ident, data.host = sender_regex.findall(line[0])[0]
  56. data.chan = line[2]
  57. # Check for 'join' hooks in our commands:
  58. commands.check("join", data)
  59. elif line[1] == "PRIVMSG":
  60. data.nick, data.ident, data.host = sender_regex.findall(line[0])[0]
  61. data.msg = ' '.join(line[3:])[1:]
  62. data.chan = line[2]
  63. if data.chan == config.irc["frontend"]["nick"]:
  64. # This is a privmsg to us, so set 'chan' as the nick of the, sender
  65. # then check for private-only command hooks:
  66. data.chan = data.nick
  67. commands.check("msg_private", data)
  68. else:
  69. # Check for public-only command hooks:
  70. commands.check("msg_public", data)
  71. # Check for command hooks that apply to all messages:
  72. commands.check("msg", data)
  73. # Hardcode the !restart command (we can't restart from within an
  74. # ordinary command):
  75. if data.msg in ["!restart", ".restart"]:
  76. if data.host in config.irc["permissions"]["owners"]:
  77. logger.info("Restarting bot per owner request")
  78. return True
  79. # If we are pinged, pong back:
  80. elif line[0] == "PING":
  81. msg = " ".join(("PONG", line[1]))
  82. connection.send(msg)
  83. # On successful connection to the server:
  84. elif line[1] == "376":
  85. # If we're supposed to auth to NickServ, do that:
  86. try:
  87. username = config.irc["frontend"]["nickservUsername"]
  88. password = config.irc["frontend"]["nickservPassword"]
  89. except KeyError:
  90. pass
  91. else:
  92. msg = " ".join(("IDENTIFY", username, password))
  93. connection.say("NickServ", msg)
  94. # Join all of our startup channels:
  95. for chan in config.irc["frontend"]["channels"]:
  96. connection.join(chan)