From fea7b06d8461c948de9d78217a0c0cc4a518ffb3 Mon Sep 17 00:00:00 2001 From: Innectic Date: Sat, 1 Oct 2016 12:13:20 -0700 Subject: [PATCH 1/4] Implement Constellation --- beam.py | 174 +++++++++++++++++++++++------------------------------- cactus.py | 2 +- 2 files changed, 74 insertions(+), 102 deletions(-) diff --git a/beam.py b/beam.py index 1702269..a451eac 100644 --- a/beam.py +++ b/beam.py @@ -294,134 +294,106 @@ def read_chat(self, handler=None): if callable(handler): handler(response) - def connect_to_liveloading(self, channel_id, user_id): + def connect_to_constellation(self, channel_id, user_id): """Connect to Beam liveloading.""" - self.liveloading_connection_information = { + self.constellation_connection_information = { "channel_id": channel_id, "user_id": user_id } - liveloading_websocket_connection = websocket_connect( - "wss://realtime.beam.pro/socket.io/?EIO=3&transport=websocket") - liveloading_websocket_connection.add_done_callback( + constellation_websocket_connection = websocket_connect( + "wss://constellation.beam.pro") + constellation_websocket_connection.add_done_callback( partial(self.subscribe_to_liveloading, channel_id, user_id)) def subscribe_to_liveloading(self, channel_id, user_id, future): - """Subscribe to Beam liveloading.""" + """Subscribe to Beam constellation.""" if future.exception() is None: - self.liveloading_websocket = future.result() + self.constellation_websocket = future.result() self.logger.info( - "Successfully connected to liveloading websocket.") - - interfaces = ( - "channel:{channel_id}:update", - "channel:{channel_id}:followed", - "channel:{channel_id}:subscribed", - "channel:{channel_id}:resubscribed", - "channel:{channel_id}:hosted", - "user:{user_id}:update" - ) - self.subscribe_to_interfaces( - *tuple( - interface.format(channel_id=channel_id, user_id=user_id) - for interface in interfaces - ) - ) + "Successfully connected to constellation websocket.") + + interfaces = [ + "channel:{channel}:update".format(channel=channel_id), + "channel:{channel}:followed".format(channel=channel_id), + "channel:{channel}:subscribed".format(channel=channel_id), + "channel:{channel}:resubscribed".format(channel=channel_id), + "channel:{channel}:hosted".format(channel=channel_id), + "user:{user}:update".format(user=user_id) + ] + self.subscribe_to_interfaces(interfaces) self.logger.info( - "Successfully subscribed to liveloading interfaces.") + "Successfully subscribed to Constellation interfaces.") - self.watch_liveloading() + self.watch_constellation() else: self.logger.warning(future.exception()) - self.connect_to_liveloading(channel_id, user_id) - - def subscribe_to_interfaces(self, *interfaces): - """Subscribe to a Beam liveloading interface.""" - - packet = [ - "put", - { - "method": "put", - "headers": {}, - "data": { - "slug": interfaces - }, - "url": "/api/v1/live" - } - ] - self.liveloading_websocket.write_message('420' + dumps(packet)) - - def parse_liveloading_message(self, message): - """Parse a message received from the Beam liveloading websocket.""" + self.connect_to_constellation(channel_id, user_id) - sections = re.match(r"(\d+)(.+)?$", message).groups() + def subscribe_to_interfaces(self, interfaces: list): + """Subscribe to a Beam constellation interface.""" - return { - "code": sections[0], - "data": loads(sections[1]) if sections[1] is not None else None + packet = { + "type": "method", + "method": "livesubscribe", + "params": { + "events": interfaces + }, + "id": 1 } + self.constellation_websocket.write_message(dumps(packet)) + + def parse_constellation_message(self, packet): + try: + packet = loads(packet) + except: + return "" + else: + if "data" in packet and "payload" in packet["data"]: + return packet["data"] + else: + return "" @coroutine - def watch_liveloading(self, handler=None): + def watch_constellation(self): """Watch and handle packets from the Beam liveloading websocket.""" - response = yield self.liveloading_websocket.read_message() + response = yield self.constellation_websocket.read_message() if response is None: raise ConnectionError - packet = self.parse_liveloading_message(response) - - PeriodicCallback( - partial(self.liveloading_websocket.write_message, '2'), - packet["data"]["pingInterval"] - ).start() - while True: - message = yield self.liveloading_websocket.read_message() - - if message is None: - self.logger.info("Connection to Liveloading lost.") - self.logger.info("Attempting to reconnect.") - - return self.connect_to_liveloading( - **self.liveloading_connection_information) - - self.logger.info("Attempting to reconnect.") - self.watch_liveloading() - - packet = self.parse_liveloading_message(message) - - if packet.get("data") is not None: - self.logger.debug("LIVE: {}".format(packet)) - - if isinstance(packet["data"], list): - if isinstance(packet["data"][0], str): - if packet["data"][1].get("following"): + message = yield self.constellation_websocket.read_message() + message = self.parse_constellation_message(message) + if message is None or message is "": + pass + else: + self.logger.debug("LIVE: {}".format(message)) + if "followed" in message["channel"]: + if message["payload"]["following"]: + self.send_message("Thanks for the follow, @{} !".format( + message["payload"]["user"]["username"])) self.logger.info("- {} followed.".format( - packet["data"][1]["user"]["username"])) - - user = session.query(User).filter_by( - id=packet["data"][1]["user"]["id"]).first() - if user and (datetime.now() - user.follow_date).days: - self.send_message( - "Thanks for the follow, @{}!".format( - packet["data"][1]["user"]["username"])) - user.follow_date = datetime.now() - session.add(user) - session.commit() - elif packet["data"][1].get("subscribed"): - self.logger.info("- {} subscribed.".format( - packet["data"][1]["user"]["username"])) - self.send_message( - "Thanks for the subscription, @{}! <3".format( - packet["data"][1]["user"]["username"])) - elif packet["data"][1].get("hoster"): - self.logger.info("- {} hosted the channel.".format( - packet["data"][1]["hoster"]["token"])) - self.send_message( - "Thanks for hosting the channel, @{}!".format( - packet["data"][1]["hoster"]["token"])) + message["payload"]["user"]["username"])) + elif "subscribed" in message["channel"]: + self.send_message("Thanks for subscribing, @{} !".format( + message["payload"]["user"]["username"] + )) + elif "resubscribed" in message["channel"]: + self.send_message("Thanks for subscribing, @{} !".format( + message["payload"]["user"]["username"] + )) + + # if message is None: + # self.logger.info("Connection to Constellation lost.") + # self.logger.info("Attempting to reconnect.") + + # return self.connect_to_constellation( + # **self.constellation_connection_information) + + # self.logger.info("Attempting to reconnect.") + # self.watch_constellation() diff --git a/cactus.py b/cactus.py index 1797949..819c59f 100644 --- a/cactus.py +++ b/cactus.py @@ -129,7 +129,7 @@ def run(self, *args, **kwargs): def connect_liveloading(): try: - self.connect_to_liveloading( + self.connect_to_constellation( self.channel_data["id"], self.channel_data["userId"]) except ConnectionError as e: From f8a2f2a6fbc0056ba0575d07a179e3915f8d10ad Mon Sep 17 00:00:00 2001 From: Innectic Date: Sat, 1 Oct 2016 12:30:14 -0700 Subject: [PATCH 2/4] Fix friend command --- models.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/models.py b/models.py index 06a279e..753f8b7 100644 --- a/models.py +++ b/models.py @@ -491,11 +491,14 @@ def __call__(self, args, data): if len(args) < 2: return "Not enough arguments." elif len(args) == 2: - user = re.match(r'@?([\w_-]*[a-z][\w_-]*', args[1]) + user = re.match(r'@?([\w_-]*[a-z][\w_-])*', args[1], re.I) + user = str(user.group()).replace("@", "") + + # user = user.group().replace("@", "") if user is None: return "Invalid username '{}'.".format(args[1]) - channel_id = self.get_channel(user.group()) + channel_id = self.get_channel(user) if channel_id.get("statusCode") == 404: return "User has not entered this channel." @@ -506,7 +509,7 @@ def __call__(self, args, data): query.friend = not query.friend session.commit() return "{}ed @{} as a friend.".format( - ["Remov", "Add"][query.friend], user.group()) + ["Remov", "Add"][query.friend], user) else: return "User has not entered this channel." elif len(args) > 2: From f0ec64f5be1b7c15c3da00b36cc1bfd1599c4fd4 Mon Sep 17 00:00:00 2001 From: Innectic Date: Sat, 1 Oct 2016 12:34:25 -0700 Subject: [PATCH 3/4] Fix pylinting --- beam.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/beam.py b/beam.py index a451eac..e8eba31 100644 --- a/beam.py +++ b/beam.py @@ -2,7 +2,6 @@ from tornado.websocket import websocket_connect from tornado.gen import coroutine -from tornado.ioloop import PeriodicCallback from requests import Session from requests.compat import urljoin @@ -18,7 +17,6 @@ import time from models import User, session -from datetime import datetime class Beam: @@ -375,7 +373,8 @@ def watch_constellation(self): self.logger.debug("LIVE: {}".format(message)) if "followed" in message["channel"]: if message["payload"]["following"]: - self.send_message("Thanks for the follow, @{} !".format( + self.send_message( + "Thanks for the follow, @{} !".format( message["payload"]["user"]["username"])) self.logger.info("- {} followed.".format( message["payload"]["user"]["username"])) From 85b686a67c311c5da53758b737fc374aa3867595 Mon Sep 17 00:00:00 2001 From: Innectic Date: Sat, 1 Oct 2016 12:36:14 -0700 Subject: [PATCH 4/4] Fix it again --- beam.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beam.py b/beam.py index e8eba31..43d54cc 100644 --- a/beam.py +++ b/beam.py @@ -375,7 +375,7 @@ def watch_constellation(self): if message["payload"]["following"]: self.send_message( "Thanks for the follow, @{} !".format( - message["payload"]["user"]["username"])) + message["payload"]["user"]["username"])) self.logger.info("- {} followed.".format( message["payload"]["user"]["username"])) elif "subscribed" in message["channel"]: