Add metadata interchange to pubsub mode

This commit is contained in:
dave 2018-01-16 17:18:15 -08:00
parent facfcbe3bc
commit 98433abe76
4 changed files with 90 additions and 21 deletions

View File

@ -14,17 +14,13 @@ from pyircbot.common import TouchReload
from json import dumps from json import dumps
# IRCEvent = namedtuple("IRCEvent", "command args prefix trailing")
# UserPrefix = namedtuple("UserPrefix", "nick username hostname")
# ServerPrefix = namedtuple("ServerPrefix", "hostname")
class PyIRCBotSub(PrimitiveBot): class PyIRCBotSub(PrimitiveBot):
def __init__(self, name, host, port, config): def __init__(self, name, host, port, config):
super().__init__(config) super().__init__(config)
self.name = name self.name = name
self.host = host self.host = host
self.port = port self.port = port
self.meta = {}
self.client = None # PubSub socket self.client = None # PubSub socket
def run(self): def run(self):
@ -37,6 +33,8 @@ class PyIRCBotSub(PrimitiveBot):
self.client.sub("pyircbot_part") self.client.sub("pyircbot_part")
self.client.sub("pyircbot_mode") self.client.sub("pyircbot_mode")
self.client.sub("pyircbot_quit") self.client.sub("pyircbot_quit")
self.client.sub("pyircbot_meta_update")
self.client.pub("pyircbot_meta_req", "x")
while True: while True:
try: try:
channel, body = self.client.recv() channel, body = self.client.recv()
@ -49,11 +47,17 @@ class PyIRCBotSub(PrimitiveBot):
if name != self.name: if name != self.name:
return 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) args, sender, trailing, extras = loads(rest)
nick, username, hostname = extras["prefix"] nick, username, hostname = extras["prefix"]
msg = IRCEvent(command, msg = IRCEvent(command.upper(),
args, args,
UserPrefix(nick, UserPrefix(nick,
username, username,
@ -89,7 +93,6 @@ class PyIRCBotSub(PrimitiveBot):
os.mkdir(module_dir) os.mkdir(module_dir)
return module_dir return module_dir
" IRC methods "
def act_PRIVMSG(self, towho, message): def act_PRIVMSG(self, towho, message):
"""Use the `/msg` command """Use the `/msg` command
@ -100,6 +103,14 @@ class PyIRCBotSub(PrimitiveBot):
# self.sendRaw("PRIVMSG %s :%s" % (towho, message)) # self.sendRaw("PRIVMSG %s :%s" % (towho, message))
self.client.pub("pyircbot_send", "{} {} {}".format(self.name, "privmsg", dumps([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__": if __name__ == "__main__":
logging.basicConfig(level=logging.WARNING, logging.basicConfig(level=logging.WARNING,

View File

@ -134,7 +134,7 @@ def load(filepath):
raise Exception("Unknown config format") 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. Process one line of text irc sent us.

View File

@ -22,6 +22,7 @@ class PubSubClient(ModuleBase):
ModuleBase.__init__(self, bot, moduleName) ModuleBase.__init__(self, bot, moduleName)
self.host, self.port = self.config.get("servers")[0].split(":") self.host, self.port = self.config.get("servers")[0].split(":")
self.bus = None 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 = Thread(target=self.bus_listener)
self.bus_listener_thread.daemon = True self.bus_listener_thread.daemon = True
self.bus_listener_thread.start() self.bus_listener_thread.start()
@ -40,16 +41,21 @@ class PubSubClient(ModuleBase):
except Again: except Again:
sleep(0.01) sleep(0.01)
continue continue
try: if channel == self.config.get("publish", "pyircbot_{}").format("meta_req"):
print(channel, "--", message) if self.services:
name, subcommand, message = message.split(" ", 2) self.bus.pub(self.config.get("publish", "pyircbot_{}").format("meta_update"),
if name != self.config.get("name", "default") and name != "default": "{} {}".format(self.config.get("name", "default"),
continue dumps({"nick": self.services.nick()})))
if subcommand == "privmsg": else:
dest, message = loads(message) try:
self.bot.act_PRIVMSG(dest, message) name, subcommand, message = message.split(" ", 2)
except: if name != self.config.get("name", "default") and name != "default":
print_exc() continue
if subcommand == "privmsg":
dest, message = loads(message)
self.bot.act_PRIVMSG(dest, message)
except:
print_exc()
def publish(self, subchannel, message): def publish(self, subchannel, message):
""" """
@ -59,9 +65,10 @@ class PubSubClient(ModuleBase):
:param message: message body :param message: message body
:type message: str :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): def busdriver(self, msg, cmd):
""" """
Relay a privmsg to the event bus Relay a privmsg to the event bus
@ -92,6 +99,7 @@ class PubSubClient(ModuleBase):
Connect to the message bus when the module is enabled Connect to the message bus when the module is enabled
""" """
self.bus = MsgbusSubClient(self.host, int(self.port)) 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"): for channel in self.config.get("subscriptions"):
self.bus.sub(channel) self.bus.sub(channel)
self.publish("sys", "online") self.publish("sys", "online")

50
tools/pubsubasciisend.py Executable file
View File

@ -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()