def onenable(self): """ 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")
def onenable(self): """ Connect to the message bus when the module is enabled """ self.bus = MsgbusSubClient(self.host, int(self.port)) for channel in self.config.get("subscriptions"): self.bus.sub(channel) self.publish("sys", "online")
def pong(host, port): """ Subscribe to the ping channel and send pongs in reply """ with closing(MsgbusSubClient(host, port)) as client: client.sub("ping") while True: _, msg = client.recv() client.pub("pong", "{} {}".format(msg, time())) print("pong(): >< {} {}".format(_, msg))
def main(): c = MsgbusSubClient("127.0.0.1", 7200) c.sub("orderbook") print(c.recv()) # returns (channel, message) c.pub("hello_world", "asdf1234") c.pub("hello_world", "qwer5678")
def send_native(host, port, pubport, channel, messages): """ Send some messages on a specified channel using the msgbus client. Note that if we don't specify a non-None publishing port when creating the client, which means the client will find it using metadata the server publishes on `port`. """ from contextlib import closing from msgbus.client import MsgbusSubClient with closing(MsgbusSubClient(host, port)) as client: for message in messages: client.pub(channel, message)
def listen_native(host, port, channels): """ Subscribe to the given server/channels using the msgbus client """ from contextlib import closing from msgbus.client import MsgbusSubClient with closing(MsgbusSubClient(host, port)) as client: if channels: for channel in channels: client.sub(channel) else: client.sub() while True: yield "{} {}".format(*client.recv())
def main(): args = get_args() with closing(MsgbusSubClient(args.host, args.port)) as client: client.sub("pyircbot_command_ping") # subscribe to .ping commnad while True: channel, msg = client.recv() _, rest = msg.split(" ", 1) channel, sender, trailing, extras = loads(rest) channel = channel[0] if not channel[0] == "#": # ignore PMs continue print("Pong: {} in {}".format(sender, channel)) client.pub( "pyircbot_send", "default privmsg {}".format( dumps([channel, "{}: pong".format(sender)])))
def run(self): # Connect to msgbus and loop through messages with closing(MsgbusSubClient(self.host, self.port)) as self.client: self.client.prepare_pub() self.client.sub("pyircbot_privmsg") self.client.sub("pyircbot_join") self.client.sub("pyircbot_kick") 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() self.process_line(channel, body) except Exception as e: traceback.print_exc()
def ping(host, port, count=5, interval=1): """ Send a ping and wait for the reply. In a loop """ with closing(MsgbusSubClient(host, port)) as client: client.prepare_pub() client.sub("pong") sleep(2) def ping_recver(): recvtime = 0 while True: _, msg = client.recv() recvtime = time() seq, msgtime, remotetime = msg.split(" ") msgtime = float(msgtime) remotetime = float(remotetime) transittime = recvtime - msgtime # out = remotetime - msgtime # back = recvtime - remotetime # These aren't printed because clock sync imperfection makes them unreliable print("ping(): < {} {} rtt: {:f}\n".format( _, seq, round(transittime, 8))) recv = Thread(target=ping_recver) recv.daemon = True recv.start() seq = 0 while seq < count: print("ping(): > ping {}".format(seq)) client.pub("ping", "{} {}".format(seq, time())) sleep(interval) seq += 1 sleep(interval * 2)
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)
class PubSubClient(ModuleBase): def __init__(self, bot, moduleName): 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() def bus_listener(self): """ Listen to the bus for send messages and act on recv """ sleep(3) while True: if not self.bus: sleep(0.01) continue try: channel, message = self.bus.recv(block=False) except Again: sleep(0.01) continue 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): """ Abstracted callback for proxying irc messages to the bs :param subchannel: event type such as "privmsg" :type subchannel: str :param message: message body :type message: str """ 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") def busdriver(self, msg, cmd): """ Relay a privmsg to the event bus """ self.publish( msg.command.lower(), dumps([ msg.args, msg.prefix[0], msg.trailing, { "prefix": msg.prefix } ])) @hook("PRIVMSG") def bus_command(self, msg, cmd): """ Parse commands and publish as separate channels on the bus. Commands like `.seen nick` will be published to channel `command_seen`. """ match = COMMAND_RE.match(msg.trailing) if match: cmd_name = match.groups()[1] cmd_args = msg.trailing[len(cmd_name) + 1:].strip() self.publish( "command_{}".format(cmd_name), dumps([ msg.args, msg.prefix[0], cmd_args, { "prefix": msg.prefix } ])) def onenable(self): """ 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") def ondisable(self): """ Disconnect to the message bus on shutdown """ self.log.warning("clean it up") self.publish("sys", "offline") self.bus.close() # This will crash the listener thread
class PubSubClient(ModuleBase): def __init__(self, bot, moduleName): ModuleBase.__init__(self, bot, moduleName) self.host, self.port = self.config.get("servers")[0].split(":") self.bus = None self.bus_listener_thread = Thread(target=self.bus_listener) self.bus_listener_thread.daemon = True self.bus_listener_thread.start() def bus_listener(self): """ Listen to the bus for send messages and act on recv """ sleep(3) while True:#TODO clean exit onenable/ondisable etc if not self.bus: sleep(0.01) continue try: channel, message = self.bus.recv(block=False) 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() def publish(self, subchannel, message): """ Abstracted callback for proxying irc messages to the bs :param subchannel: event type such as "privmsg" :type subchannel: str :param message: message body :type message: str """ self.bus.pub(self.config.get("publish").format(subchannel), "{} {}".format("default", message)) @hook("PRIVMSG") def bus_privmsg(self, msg): """ Relay a privmsg to the event bus """ self.publish("privmsg", dumps([msg.args, msg.prefix[0], msg.trailing, {"prefix": msg.prefix}])) @hook("JOIN") def bus_join(self, msg): """ Relay a join message to the event bus """ self.publish("join", dumps([msg.prefix[0], msg.trailing, {"prefix": msg.prefix}])) @hook("PART") def bus_part(self, msg): """ Relay a part message to the event bus """ self.publish("part", dumps([msg.args, msg.prefix[0], msg.trailing, {"prefix": msg.prefix}])) @hook("PRIVMSG") def bus_command(self, msg): """ Parse commands and publish as separate channels on the bus. Commands like `.seen nick` will be published to channel `command_seen`. """ match = COMMAND_RE.match(msg.trailing) if match: cmd_name = match.groups()[1] cmd_args = msg.trailing[len(cmd_name) + 1:].strip() self.publish("command_{}".format(cmd_name), dumps([msg.args, msg.prefix[0], cmd_args, {"prefix": msg.prefix}])) def onenable(self): """ Connect to the message bus when the module is enabled """ self.bus = MsgbusSubClient(self.host, int(self.port)) for channel in self.config.get("subscriptions"): self.bus.sub(channel) self.publish("sys", "online") def ondisable(self): """ Disconnect to the message bus on shutdown """ self.log.warning("clean it up") self.publish("sys", "offline") self.bus.close()