/jsb/plugs/socket/irccat.py

https://code.google.com/p/boty/ · Python · 163 lines · 123 code · 19 blank · 21 comment · 26 complexity · c336d586a475674518868f9bee38ac8f MD5 · raw file

  1. #!/usr/bin/env python
  2. """
  3. irccat.py - jsonbot "irccat" Module
  4. Copyright 2011, Richard Bateman
  5. Licensed under the New BSD License.
  6. Written to be used in the #firebreath IRC channel: http://www.firebreath.org
  7. To test, set up the host and port, then use something like:
  8. echo "@taxilian I am awesome" | netcat -g0 localhost 54321
  9. echo "#channel I am awesome" | netcat -g0 localhost 54321
  10. you can specify multiple users (with @) and channels (with #) by seperating them
  11. with commas. Not that with jabber, channels tend to be treated as users
  12. unless you set up an alias in your channel:
  13. !irccat_add_alias #channel
  14. """
  15. ## jsb imports
  16. from jsb.lib.threads import start_new_thread
  17. from jsb.lib.persist import PlugPersist
  18. from jsb.lib.fleet import getfleet
  19. from jsb.lib.commands import cmnds
  20. from jsb.lib.examples import examples
  21. from jsb.lib.callbacks import callbacks
  22. ## basic imports
  23. import logging
  24. import time
  25. ## defines
  26. cfg = PlugPersist("irccat", {
  27. "botnames": ["default-sxmpp",],
  28. "host": "localhost",
  29. "port": "54321",
  30. "aliases": {},
  31. "enable": False,
  32. })
  33. import SocketServer
  34. from SocketServer import ThreadingMixIn, StreamRequestHandler
  35. shared_data = {}
  36. server = None
  37. class IrcCatListener(ThreadingMixIn, StreamRequestHandler):
  38. def handle(self):
  39. fleet = getfleet()
  40. msg = self.rfile.readline().strip()
  41. logging.warn("received %s" % msg)
  42. dest, msg = self.splitMsg(msg)
  43. for chan in dest:
  44. logging.info("sending to %s" % chan)
  45. for botname in fleet.list():
  46. bot = fleet.byname(botname)
  47. if bot:
  48. if chan[0] == "#" and chan not in bot.state['joinedchannels']:
  49. logging.warn("someone tried to make me say something in a channel i'm not in!")
  50. else:
  51. bot.say(chan, msg)
  52. else: logging.error("can't find %s bot in fleet" % botname)
  53. def splitMsg(self, message):
  54. if message[0] not in ('#', '@'): return [], message
  55. dest, message = message.split(" ", 1)
  56. dest = [x.strip().strip("@") for x in dest.split(",")]
  57. finalDest = []
  58. for d in dest:
  59. finalDest.append(d)
  60. if d in cfg.data["aliases"].keys():
  61. for alias in cfg.data["aliases"][d]:
  62. finalDest.append(alias)
  63. return finalDest, message
  64. def dummycb(bot, event): pass
  65. callbacks.add("START", dummycb)
  66. def init_threaded():
  67. global server
  68. if server: logging.warn("irccat server is already running.") ; return
  69. if not cfg.data.enable: logging.warn("irccat is not enabled.") ; return
  70. time.sleep(3)
  71. if "host" not in cfg.data or "port" not in cfg.data:
  72. cfg.data["host"] = "localhost"
  73. cfg.data["port"] = 54321
  74. cfg.data["botnames"] = ["default-sxmpp",]
  75. cfg.data["aliases"] = {}
  76. if not cfg.data.aliases: cfg.data.aliases = {}
  77. cfg.save()
  78. try:
  79. server = SocketServer.TCPServer((cfg.data["host"], int(cfg.data["port"])), IrcCatListener)
  80. except Exception, ex: logging.error(str(ex)) ; return
  81. logging.warn("starting irccat server on %s:%s" % (cfg.data["host"], cfg.data["port"]))
  82. start_new_thread(server.serve_forever, ())
  83. def shutdown():
  84. global server
  85. if server:
  86. logging.warn("shutting down the irccat server")
  87. server.shutdown()
  88. def handle_irccat_add_alias(bot, ievent):
  89. if len(ievent.args) != 1:
  90. ievent.reply("syntax: irccat_add_alias <alias> (where <alias> is the channel you want notifications for)")
  91. return
  92. dest = ievent.args[0]
  93. if not cfg.data.aliases: cfg.data.aliases = {}
  94. if dest not in cfg.data["aliases"]:
  95. cfg.data["aliases"][dest] = []
  96. if ievent.channel not in cfg.data["aliases"][dest]:
  97. cfg.data["aliases"][dest].append(ievent.channel)
  98. cfg.save()
  99. ievent.reply("%s will now receive irccat messages directed at %s" % (ievent.channel, dest))
  100. cmnds.add("irccat_add_alias", handle_irccat_add_alias, ['OPER'])
  101. examples.add("irccat_add_alias", "add an alias to the current channel from the specified one", "irccat_add_alias #firebreath")
  102. def handle_irccat_list_aliases(bot, ievent):
  103. """ List all aliases defined for the current channel """
  104. aliases = [dest for dest, chanlist in cfg.data["aliases"].iteritems() if ievent.channel in chanlist]
  105. ievent.reply("%s is receiving irccat messages directed at: %s" % (ievent.channel, ", ".join(aliases)))
  106. cmnds.add("irccat_list_aliases", handle_irccat_list_aliases, ['OPER'])
  107. examples.add("irccat_list_aliases", "lists the aliases for the current channel", "irccat_list_aliases")
  108. def handle_irccat_del_alias(bot, ievent):
  109. if len(ievent.args) != 1:
  110. ievent.reply("syntax: irccat_del_alias <alias> (where <alias> is the channel you no longer want notifications for)")
  111. return
  112. dest = ievent.args[0]
  113. if dest not in cfg.data["aliases"]or ievent.channel not in cfg.data["aliases"][dest]:
  114. ievent.reply("%s is not an alias for %s" % (ievent.channel, dest))
  115. return
  116. cfg.data["aliases"][dest].remove(ievent.channel)
  117. ievent.reply("%s will no longer receive irccat messages directed at %s" % (ievent.channel, dest))
  118. cfg.save()
  119. cmnds.add("irccat_del_alias", handle_irccat_del_alias, ['OPER'])
  120. examples.add("irccat_del_alias", "add an alias to the current channel from the specified one", "irccat_del_alias #firebreath")
  121. def handle_irccat_enable(bot, event):
  122. cfg.data.enable = True ; cfg.save() ; event.done()
  123. init_threaded()
  124. cmnds.add("irccat-enable", handle_irccat_enable, "OPER")
  125. examples.add("irccat-enable", "enable irccat server", "irccat-enable")
  126. def handle_irccat_disable(bot, event):
  127. cfg.data.enable = False ; cfg.save() ; event.done()
  128. shutdown()
  129. cmnds.add("irccat-disable", handle_irccat_disable, "OPER")
  130. examples.add("irccat-disable", "disable irccat server", "irccat-disable")