async def post(self): data = self.request.body.decode('utf-8') data = json.loads(data) data['block'] = json.loads(data['block']) if data['block']['type'] == 'send': target = data['block']['destination'] if subscriptions.get(target): print(" Pushing to client %s" % subscriptions[target]) logging.info('push to client;' + json.dumps(data['block']) + ';' + subscriptions[target]) clients[subscriptions[target]].write_message(json.dumps(data)) elif data['block']['type'] == 'state': link = data['block']['link_as_account'] if subscriptions.get(link): print(" Pushing to client %s" % subscriptions[link]) logging.info('push to client;' + json.dumps(data) + ';' + subscriptions[link]) clients[subscriptions[link]].write_message(json.dumps(data)) # Push FCM notification if this is a send fcm_tokens = get_fcm_tokens(link) if fcm_tokens is None or len(fcm_tokens) == 0: return rpc = tornado.httpclient.AsyncHTTPClient() response = await rpc_request(rpc, json.dumps({"action":"block", "hash":data['block']['previous']})) if response is None or response.error: return # See if this block was already pocketed cached_hash = rdata.get(f"link_{data['hash']}") if cached_hash is not None: return prev_data = json.loads(response.body.decode('ascii')) prev_data = prev_data['contents'] = json.loads(prev_data['contents']) prev_balance = int(prev_data['contents']['balance']) cur_balance = int(data['block']['balance']) send_amount = prev_balance - cur_balance if send_amount >= 1000000000000000000000000: # This is a send, push notifications fcm = aiofcm.FCM(fcm_sender_id, fcm_api_key) # Send notification with generic title, send amount as body. App should have localizations and use this information at its discretion for t in fcm_tokens: message = aiofcm.Message( device_token=t, data = { "amount": str(send_amount) } ) await fcm.send_message(message) elif subscriptions.get(data['account']): print(" Pushing to client %s" % subscriptions[data['account']]) logging.info('push to client;' + json.dumps(data) + ';' + subscriptions[data['account']]) clients[subscriptions[data['account']]].write_message(json.dumps(data))
async def check_and_do_push_notification(redis: Redis, op): # Only if configured if fcm_client is None: return # Only do pending operations, and only to the receiver if op['maturation'] is not None or 'receivers' not in op or not op[ 'receivers']: return # Check if we already pushed this op op_pushed = await redis.get(f'pncache_{op["ophash"]}') if op_pushed is not None: return else: await redis.set(f'pncache_{op["ophash"]}', 'tru', expire=10000) # Check tokens fcm_tokens = await get_fcm_tokens(op['receivers'][0]['account'], redis) notification_title = f"Received {abs(float(op['receivers'][0]['amount']))} PASCAL" notification_body = f"Open Blaise to view this transaction." for t in fcm_tokens: b58_pubkey = await redis.get(f'fcm{t}') if b58_pubkey is not None: # Verify pubkey account = op['receivers'][0]['account'] acct_resp = await jrpc_client.getaccount(account) if acct_resp is None: continue expected_pubkey_enc = acct_resp['enc_pubkey'].upper() if Util.b58_to_enc_pubkey(b58_pubkey) != expected_pubkey_enc: continue message = aiofcm.Message(device_token=t, notification={ "title": notification_title, "body": notification_body, "sound": "default", "tag": str(op['receivers'][0]['account']) }, data={ "click_action": "FLUTTER_NOTIFICATION_CLICK", "account": str(op['receivers'][0]['account']) }, priority=aiofcm.PRIORITY_HIGH) await fcm_client.send_message(message)
async def callback(r: web.Request): try: request_json = await r.json() hash = request_json['hash'] log.server_logger.debug(f"callback received {hash}") request_json['block'] = json.loads(request_json['block']) link = request_json['block']['link_as_account'] # Push FCM notification if this is a send if fcm_api_key is None: return web.HTTPOk() fcm_tokens = set(await get_fcm_tokens(link, r)) fcm_tokens_v2 = set(await get_fcm_tokens(link, r, v2=True)) if (fcm_tokens is None or len(fcm_tokens) == 0) and (fcm_tokens_v2 is None or len(fcm_tokens_v2) == 0): return web.HTTPOk() message = { "action": "block", "hash": request_json['block']['previous'] } response = await rpc.json_post(message) if response is None: return web.HTTPOk() # See if this block was already pocketed cached_hash = await r.app['rdata'].get(f"link_{hash}") if cached_hash is not None: return web.HTTPOk() prev_data = response prev_data = prev_data['contents'] = json.loads(prev_data['contents']) prev_balance = int(prev_data['contents']['balance']) cur_balance = int(request_json['block']['balance']) send_amount = prev_balance - cur_balance if send_amount >= 1000000000000000000000000: # This is a send, push notifications fcm = aiofcm.FCM(fcm_sender_id, fcm_api_key) # Send notification with generic title, send amount as body. App should have localizations and use this information at its discretion for t in fcm_tokens: message = aiofcm.Message(device_token=t, data={"amount": str(send_amount)}, priority=aiofcm.PRIORITY_HIGH) await fcm.send_message(message) notification_title = f"Received {util.raw_to_nano(send_amount)} {'NANO' if not banano_mode else 'BANANO'}" notification_body = f"Open {'Natrium' if not banano_mode else 'Kalium'} to view this transaction." for t2 in fcm_tokens_v2: message = aiofcm.Message(device_token=t2, notification={ "title": notification_title, "body": notification_body, "sound": "default", "tag": link }, data={ "click_action": "FLUTTER_NOTIFICATION_CLICK", "account": link }, priority=aiofcm.PRIORITY_HIGH) await fcm.send_message(message) return web.HTTPOk() except Exception: log.server_logger.exception("received exception in callback") return web.HTTPInternalServerError( reason=f"Something went wrong {str(sys.exc_info())}")
async def post(self): data = self.request.body.decode('utf-8') data = json.loads(data) data['block'] = json.loads(data['block']) if data['block']['type'] == 'send': target = data['block']['destination'] if subscriptions.get(target): print(" Pushing to client %s" % subscriptions[target]) logging.info('push to client;' + json.dumps(data['block']) + ';' + subscriptions[target]) clients[subscriptions[target]].write_message(json.dumps(data)) elif data['block']['type'] == 'state': link = data['block']['link_as_account'] if subscriptions.get(link): print(" Pushing to client %s" % subscriptions[link]) logging.info('push to client;' + json.dumps(data) + ';' + subscriptions[link]) clients[subscriptions[link]].write_message(json.dumps(data)) # Push FCM notification if this is a send fcm_tokens = set(get_fcm_tokens(link)) fcm_tokens_v2 = set(get_fcm_tokens(link, v2=True)) if (fcm_tokens is None or len(fcm_tokens) == 0) and (fcm_tokens_v2 is None or len(fcm_tokens_v2) == 0): return rpc = tornado.httpclient.AsyncHTTPClient() response = await rpc_request(rpc, json.dumps({"action":"block", "hash":data['block']['previous']})) if response is None or response.error: return # See if this block was already pocketed cached_hash = rdata.get(f"link_{data['hash']}") if cached_hash is not None: return prev_data = json.loads(response.body.decode('ascii')) prev_data = prev_data['contents'] = json.loads(prev_data['contents']) prev_balance = int(prev_data['contents']['balance']) cur_balance = int(data['block']['balance']) send_amount = prev_balance - cur_balance if send_amount >= 1000000000000000000000000: # This is a send, push notifications fcm = aiofcm.FCM(fcm_sender_id, fcm_api_key) # Send notification with generic title, send amount as body. App should have localizations and use this information at its discretion for t in fcm_tokens: message = aiofcm.Message( device_token=t, data = { "amount": str(send_amount) }, priority=aiofcm.PRIORITY_HIGH ) await fcm.send_message(message) notification_title = f"Received {NanoConversions.raw_to_nano(send_amount)} NANO" notification_body = "Open Natrium to view this transaction." for t2 in fcm_tokens_v2: message = aiofcm.Message( device_token = t2, notification = { "title":notification_title, "body":notification_body, "sound":"default", "tag":link }, data = { "click_action": "FLUTTER_NOTIFICATION_CLICK", "account": link }, priority=aiofcm.PRIORITY_HIGH ) await fcm.send_message(message) elif subscriptions.get(data['account']): print(" Pushing to client %s" % subscriptions[data['account']]) logging.info('push to client;' + json.dumps(data) + ';' + subscriptions[data['account']]) clients[subscriptions[data['account']]].write_message(json.dumps(data))
async def callback(r : web.Request): try: request_json = await r.json() hash = request_json['hash'] log.server_logger.debug(f"callback received {hash}") request_json['block'] = json.loads(request_json['block']) link = request_json['block']['link_as_account'] if r.app['subscriptions'].get(link): log.server_logger.info("Pushing to clients %s", str(r.app['subscriptions'][link])) for sub in r.app['subscriptions'][link]: if sub in r.app['clients']: await r.app['clients'][sub].send_str(json.dumps(request_json)) # If natrium account and send, send to web page for donations if 'is_send' in request_json and (request_json['is_send'] or request_json['is_send'] == 'true') and link == 'nano_1natrium1o3z5519ifou7xii8crpxpk8y65qmkih8e8bpsjri651oza8imdd': log.server_logger.info('Detected send to natrium account') if 'amount' in request_json: log.server_logger.info(f'emitting donation event for amount: {request_json["amount"]}') await sio.emit('donation_event', {'amount':request_json['amount']}) # Push FCM notification if this is a send if fcm_api_key is None: return web.HTTPOk() fcm_tokens = set(await get_fcm_tokens(link, r)) fcm_tokens_v2 = set(await get_fcm_tokens(link, r, v2=True)) if (fcm_tokens is None or len(fcm_tokens) == 0) and (fcm_tokens_v2 is None or len(fcm_tokens_v2) == 0): return web.HTTPOk() message = { "action":"block", "hash":request_json['block']['previous'] } response = await rpc.json_post(message) if response is None: return web.HTTPOk() # See if this block was already pocketed cached_hash = await r.app['rdata'].get(f"link_{hash}") if cached_hash is not None: return web.HTTPOk() prev_data = response prev_data = prev_data['contents'] = json.loads(prev_data['contents']) prev_balance = int(prev_data['contents']['balance']) cur_balance = int(request_json['block']['balance']) send_amount = prev_balance - cur_balance if send_amount >= 1000000000000000000000000: # This is a send, push notifications fcm = aiofcm.FCM(fcm_sender_id, fcm_api_key) # Send notification with generic title, send amount as body. App should have localizations and use this information at its discretion for t in fcm_tokens: message = aiofcm.Message( device_token=t, data = { "amount": str(send_amount) }, priority=aiofcm.PRIORITY_HIGH ) await fcm.send_message(message) notification_title = f"Received {util.raw_to_nano(send_amount)} {'NANO' if not banano_mode else 'BANANO'}" notification_body = f"Open {'Natrium' if not banano_mode else 'Kalium'} to view this transaction." for t2 in fcm_tokens_v2: message = aiofcm.Message( device_token = t2, notification = { "title":notification_title, "body":notification_body, "sound":"default", "tag":link }, data = { "click_action": "FLUTTER_NOTIFICATION_CLICK", "account": link }, priority=aiofcm.PRIORITY_HIGH ) await fcm.send_message(message) return web.HTTPOk() except Exception: log.server_logger.exception("received exception in callback") return web.HTTPInternalServerError(reason=f"Something went wrong {str(sys.exc_info())}")