def get_text(): pb = Pushbullet('PUSHBULLET API KEY') while True: pushes = pb.get_pushes() latest = pushes[0]['body'] check = open('2fa.txt', 'r').read() if latest == check: time.sleep(10) else: open('2fa.txt', 'w').close() with open("2fa.txt", "w") as text_file: text_file.write(latest) break pb.delete_push(pushes[0].get("iden")) code = latest.replace(' is your Amazon security code.', '') return code
class PushBulletWSClient(WebSocketBaseClient): def init(self, interface): """ Initializes the PB WS Client""" self.logger = logging.getLogger('PAI').getChild(__name__) self.pb = Pushbullet(cfg.PUSHBULLET_KEY, cfg.PUSHBULLET_SECRET) self.manager = WebSocketManager() self.alarm = None self.interface = interface def stop(self): self.terminate() self.manager.stop() def set_alarm(self, alarm): """ Sets the paradox alarm object """ self.alarm = alarm def handshake_ok(self): """ Callback trigger when connection succeeded""" self.logger.info("Handshake OK") self.manager.add(self) self.manager.start() for chat in self.pb.chats: self.logger.debug("Associated contacts: {}".format(chat)) # Receiving pending messages self.received_message(json.dumps({"type": "tickle", "subtype": "push"})) self.send_message("Active") def received_message(self, message): """ Handle Pushbullet message. It should be a command """ self.logger.debug("Received Message {}".format(message)) try: message = json.loads(str(message)) except: self.logger.exception("Unable to parse message") return if self.alarm is None: return if message['type'] == 'tickle' and message['subtype'] == 'push': now = time.time() pushes = self.pb.get_pushes(modified_after=int(now) - 20, limit=1, filter_inactive=True) self.logger.debug("got pushes {}".format(pushes)) for p in pushes: self.pb.dismiss_push(p.get("iden")) self.pb.delete_push(p.get("iden")) if p.get('direction') == 'outgoing' or p.get('dismissed'): continue if p.get('sender_email_normalized') in cfg.PUSHBULLET_CONTACTS: ret = self.interface.send_command(p.get('body')) if ret: self.logger.info("From {} ACCEPTED: {}".format(p.get('sender_email_normalized'), p.get('body'))) else: self.logger.warning("From {} UNKNOWN: {}".format(p.get('sender_email_normalized'), p.get('body'))) else: self.logger.warning("Command from INVALID SENDER {}: {}".format(p.get('sender_email_normalized'), p.get('body'))) def unhandled_error(self, error): self.logger.error("{}".format(error)) try: self.terminate() except Exception: self.logger.exception("Closing Pushbullet WS") self.close() def send_message(self, msg, dstchat=None): if dstchat is None: dstchat = self.pb.chats if not isinstance(dstchat, list): dstchat = [dstchat] for chat in dstchat: if chat.email in cfg.PUSHBULLET_CONTACTS: try: self.pb.push_note("paradox", msg, chat=chat) except Exception: self.logger.exception("Sending message") time.sleep(5) def notify(self, source, message, level): try: if level.value >= EventLevel.WARN.value: self.send_message("{}".format(message)) except Exception: logging.exception("Pushbullet notify")
class PushBulletWSClient(WebSocketBaseClient): def init(self): """ Initializes the PB WS Client""" self.pb = Pushbullet(cfg.PUSHBULLET_KEY, cfg.PUSHBULLET_SECRET) self.manager = WebSocketManager() self.alarm = None def set_alarm(self, alarm): """ Sets the paradox alarm object """ self.alarm = alarm def handshake_ok(self): """ Callback trigger when connection succeeded""" logger.info("Handshake OK") self.manager.add(self) for chat in self.pb.chats: logger.debug("Associated contacts: {}".format(chat)) # Receiving pending messages self.received_message(json.dumps({ "type": "tickle", "subtype": "push" })) self.send_message("Active") def handle_message(self, message): """ Handle Pushbullet message. It should be a command """ logger.debug("Received Message {}".format(message)) try: message = json.loads(str(message)) except: logger.exception("Unable to parse message") return if self.alarm == None: return if message['type'] == 'tickle' and msg['subtype'] == 'push': now = time.time() pushes = self.pb.get_pushes(modified_after=int(now) - 10, limit=1, filter_inactive=True) for p in pushes: self.pb.dismiss_push(p.get("iden")) self.pb.delete_push(p.get("iden")) if p.get('direction') == 'outgoing' or p.get('dismissed'): continue if p.get('sender_email_normalized') in PUSHBULLET_CONTACTS: ret = self.send_command(p.get('body')) if ret: logger.info("From {} ACCEPTED: {}".format( p.get('sender_email_normalized'), p.get('body'))) else: logger.warning("From {} UNKNOWN: {}".format( p.get('sender_email_normalized'), p.get('body'))) else: logger.warning("Command from INVALID SENDER {}: {}".format( p.get('sender_email_normalized'), p.get('body'))) def unhandled_error(self, error): logger.error("{}".format(error)) try: self.terminate() except: logger.exception("Closing Pushbullet WS") self.close() def send_message(self, msg, dstchat=None): for chat in self.pb.chats: if chat.email in PUSHBULLET_CONTACTS: try: self.pb.push_note("paradox", msg, chat=chat) except: logger.exception("Sending message") time.sleep(5) def send_command(self, message): """Handle message received from the MQTT broker""" """Format TYPE LABEL COMMAND """ tokens = message.split(" ") if len(tokens) != 3: logger.warning("Message format is invalid") return if self.alarm == None: logger.error("No alarm registered") return element_type = tokens[0].lower() element = tokens[1] command = self.normalize_payload(tokens[2]) # Process a Zone Command if element_type == 'zone': if command not in ['bypass', 'clear_bypass']: logger.error("Invalid command for Zone {}".format(command)) return if not self.alarm.control_zone(element, command): logger.warning("Zone command refused: {}={}".format( element, command)) # Process a Partition Command elif element_type == 'partition': if command not in ['arm', 'disarm', 'arm_stay', 'arm_sleep']: logger.error( "Invalid command for Partition {}".format(command)) return if not self.alarm.control_partition(element, command): logger.warning("Partition command refused: {}={}".format( element, command)) # Process an Output Command elif element_type == 'output': if command not in ['on', 'off', 'pulse']: logger.error("Invalid command for Output {}".format(command)) return if not self.alarm.control_output(element, command): logger.warning("Output command refused: {}={}".format( element, command)) else: logger.error("Invalid control property {}".format(element)) def normalize_payload(self, message): message = message.strip().lower() if message in ['true', 'on', '1', 'enable']: return 'on' elif message in ['false', 'off', '0', 'disable']: return 'off' elif message in [ 'pulse', 'arm', 'disarm', 'arm_stay', 'arm_sleep', 'bypass', 'clear_bypass' ]: return message return None def notify(self, source, message, level): if level < logging.INFO: return try: self.send_message("{}".format(message)) except: logging.exception("Pushbullet notify") def event(self, raw): """Handle Live Event""" return def change(self, element, label, property, value): """Handle Property Change""" #logger.debug("Property Change: element={}, label={}, property={}, value={}".format( # element, # label, # property, # value)) return
def watch_tgtg(): if tgtg_email is not None and tgtg_password is not None: tgtg_client = TgtgClient(email=tgtg_email, password=tgtg_password) elif tgtg_user_id is not None and tgtg_access_token is not None: tgtg_client = TgtgClient(user_id=tgtg_user_id, access_token=tgtg_access_token) else: print( "Neither email and password nor user id and access token for TGTG were specified. Aborting..." ) pb_client = None if pb_api_key is not None: pb_client = Pushbullet(pb_api_key) pb_notification_channel = pb_client.get_channel( pb_notification_channel_tag ) if pb_notification_channel_tag is not None else None if bool(environ.get('PB_CLEAR_CHANNEL', False)) and pb_notification_channel is not None: for push in pb_client.get_pushes(): if 'channel_iden' in push and push[ 'channel_iden'] == pb_notification_channel.iden: pb_client.delete_push(push['iden']) available_items = {} while True: for available_item in available_items.values(): available_item['still_available'] = False items = tgtg_client.get_items(favorites_only=True, latitude=tgtg_search_lat, longitude=tgtg_search_lon, radius=tgtg_search_range) print( f"Found {len(items)} favourited stores of which {len([_ for _ in items if _['items_available'] > 0])} have available items..." ) for item in items: if item['items_available'] > 0: if item['item']['item_id'] in available_items: available_items[item['item'] ['item_id']]['still_available'] = True else: print( f"Found newly available product: {item['display_name']} since {datetime.now().strftime('%H:%M:%S (%d.%m.%Y)')}" ) if pb_client is not None: push_guid = uuid4().hex pb_client.push_link( f"New TGTG product available", f"https://share.toogoodtogo.com/item/{item['item']['item_id']}", f"{item['display_name']} since {datetime.now().strftime('%H:%M:%S (%d.%m.%Y)')}", channel=pb_notification_channel, guid=push_guid) available_items[item['item']['item_id']] = { 'item': item, 'still_available': True, 'push_guid': push_guid } keys_to_delete = [] for available_item_id, available_item in available_items.items(): if not available_item['still_available']: print( f"Product is no longer available: {available_item['item']['display_name']} since {datetime.now().strftime('%H:%M:%S (%d.%m.%Y)')}" ) if pb_client is not None: push_to_delete = next( (push for push in pb_client.get_pushes() if 'guid' in push and push['guid'] == available_item['push_guid']), None) if push_to_delete is not None: pb_client.delete_push(push_to_delete['iden']) keys_to_delete.append(available_item_id) for key_to_delete in keys_to_delete: del available_items[key_to_delete] print( f"All favourited stores were processed. Sleeping {environ.get('SLEEP_INTERVAL', '60')} seconds..." ) time.sleep(int(environ.get('SLEEP_INTERVAL', '60')))