diff --git a/bin/pubsubbot b/bin/pubsubbot index 0c00a64..1af9815 100755 --- a/bin/pubsubbot +++ b/bin/pubsubbot @@ -14,17 +14,13 @@ from pyircbot.common import TouchReload from json import dumps -# IRCEvent = namedtuple("IRCEvent", "command args prefix trailing") -# UserPrefix = namedtuple("UserPrefix", "nick username hostname") -# ServerPrefix = namedtuple("ServerPrefix", "hostname") - - class PyIRCBotSub(PrimitiveBot): def __init__(self, name, host, port, config): super().__init__(config) self.name = name self.host = host self.port = port + self.meta = {} self.client = None # PubSub socket def run(self): @@ -37,6 +33,8 @@ class PyIRCBotSub(PrimitiveBot): self.client.sub("pyircbot_part") self.client.sub("pyircbot_mode") self.client.sub("pyircbot_quit") + self.client.sub("pyircbot_meta_update") + self.client.pub("pyircbot_meta_req", "x") while True: try: channel, body = self.client.recv() @@ -49,11 +47,17 @@ class PyIRCBotSub(PrimitiveBot): if name != self.name: return - command = channel.split("_", 1)[1].upper() + command = channel.split("_", 1)[1] + + if command == "meta_update": + self.meta.update(loads(rest)) + print(self.meta) + return + args, sender, trailing, extras = loads(rest) nick, username, hostname = extras["prefix"] - msg = IRCEvent(command, + msg = IRCEvent(command.upper(), args, UserPrefix(nick, username, @@ -89,7 +93,6 @@ class PyIRCBotSub(PrimitiveBot): os.mkdir(module_dir) return module_dir - " IRC methods " def act_PRIVMSG(self, towho, message): """Use the `/msg` command @@ -100,6 +103,14 @@ class PyIRCBotSub(PrimitiveBot): # self.sendRaw("PRIVMSG %s :%s" % (towho, message)) self.client.pub("pyircbot_send", "{} {} {}".format(self.name, "privmsg", dumps([towho, message]))) + def getBestModuleForService(self, service): + if service == "services": + return self + return super().getBestModuleForService(service) + + def nick(self): + return self.meta.get("nick", None) + if __name__ == "__main__": logging.basicConfig(level=logging.WARNING, diff --git a/pyircbot/common.py b/pyircbot/common.py index 96a2a66..f77c7ef 100644 --- a/pyircbot/common.py +++ b/pyircbot/common.py @@ -134,7 +134,7 @@ def load(filepath): raise Exception("Unknown config format") -def parse_irc_line(data, client=True): +def parse_irc_line(data): """ Process one line of text irc sent us. diff --git a/pyircbot/modules/PubSubClient.py b/pyircbot/modules/PubSubClient.py index 3bf62e8..80bbc22 100644 --- a/pyircbot/modules/PubSubClient.py +++ b/pyircbot/modules/PubSubClient.py @@ -22,6 +22,7 @@ class PubSubClient(ModuleBase): ModuleBase.__init__(self, bot, moduleName) self.host, self.port = self.config.get("servers")[0].split(":") self.bus = None + self.services = (self.bot.getmodulesbyservice("services") or [None]).pop(0) self.bus_listener_thread = Thread(target=self.bus_listener) self.bus_listener_thread.daemon = True self.bus_listener_thread.start() @@ -40,16 +41,21 @@ class PubSubClient(ModuleBase): except Again: sleep(0.01) continue - try: - print(channel, "--", message) - name, subcommand, message = message.split(" ", 2) - if name != self.config.get("name", "default") and name != "default": - continue - if subcommand == "privmsg": - dest, message = loads(message) - self.bot.act_PRIVMSG(dest, message) - except: - print_exc() + if channel == self.config.get("publish", "pyircbot_{}").format("meta_req"): + if self.services: + self.bus.pub(self.config.get("publish", "pyircbot_{}").format("meta_update"), + "{} {}".format(self.config.get("name", "default"), + dumps({"nick": self.services.nick()}))) + else: + try: + name, subcommand, message = message.split(" ", 2) + if name != self.config.get("name", "default") and name != "default": + continue + if subcommand == "privmsg": + dest, message = loads(message) + self.bot.act_PRIVMSG(dest, message) + except: + print_exc() def publish(self, subchannel, message): """ @@ -59,9 +65,10 @@ class PubSubClient(ModuleBase): :param message: message body :type message: str """ - self.bus.pub(self.config.get("publish").format(subchannel), "{} {}".format("default", message)) + self.bus.pub(self.config.get("publish", "pyircbot_{}").format(subchannel), + "{} {}".format(self.config.get("name", "default"), message)) - @hook("PRIVMSG", "JOIN", "PART", "KICK", "MODE", "QUIT", "NICK", "PING") + @hook("PRIVMSG", "JOIN", "PART", "KICK", "MODE", "QUIT", "NICK") def busdriver(self, msg, cmd): """ Relay a privmsg to the event bus @@ -92,6 +99,7 @@ class PubSubClient(ModuleBase): Connect to the message bus when the module is enabled """ self.bus = MsgbusSubClient(self.host, int(self.port)) + self.bus.sub(self.config.get("publish", "pyircbot_{}").format("meta_req")) for channel in self.config.get("subscriptions"): self.bus.sub(channel) self.publish("sys", "online") diff --git a/tools/pubsubasciisend.py b/tools/pubsubasciisend.py new file mode 100755 index 0000000..af19d7e --- /dev/null +++ b/tools/pubsubasciisend.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +from contextlib import closing +from msgbus.client import MsgbusSubClient +import argparse +from time import sleep +from json import dumps + + +def main(): + parser = argparse.ArgumentParser(description="send irc art") + parser.add_argument("-i", "--host", default="127.0.0.1", help="host to connect to") + parser.add_argument("-p", "--port", default=7003, help="port to connect to") + parser.add_argument("-c", "--channel", required=True, help="irc channel") + parser.add_argument("-f", "--file", required=True, help="file containing irc lines to send") + parser.add_argument("--delay", type=float, default=1.0, help="delay between lines (s)") + parser.add_argument("--names", default=["default"], nargs="+", help="bot pubsub names to send via") + parser.add_argument("--name-burst", default=1, type=int, help="num lines to send before choosing next name") + parser.add_argument("--name-burst-delay", default=0.0, type=float, help="delay between single name bursts") + parser.add_argument("--name-change-delay", type=float, default=0.0) + args = parser.parse_args() + + with open(args.file) as f: + with closing(MsgbusSubClient(args.host, args.port)) as client: + name = 0 + per_name = 0 + for line in f: + line = line.rstrip() + print(line) + client.pub("pyircbot_send", "{} privmsg {}".format(args.names[name], dumps([args.channel, line]))) + per_name += 1 + # if the current name has reached its quota + if per_name >= args.name_burst: + # Do the main sleep + sleep(args.delay) + per_name = 0 + # Advance to the next name + name += 1 + if name >= len(args.names): + name = 0 + if args.name_change_delay: + sleep(args.name_change_delay) + else: + # Same name, do the burst delay + if args.name_burst_delay: + sleep(args.name_burst_delay) + + +if __name__ == '__main__': + main()