def lninvoice_paid_handler(sender, instance, **kwargs): print("received...!") print(f"received Sender: {sender}") print(f"received Instance: {instance}") shop_item_content_type = instance.po.item_details.first().content_type shop_item_id = instance.po.item_details.first().object_id if shop_item_content_type == ContentType.objects.get_for_model(TorBridge): shop_item = TorBridge.objects.get(id=shop_item_id) elif shop_item_content_type == ContentType.objects.get_for_model(RSshTunnel): shop_item = RSshTunnel.objects.get(id=shop_item_id) else: raise NotImplementedError if shop_item.status == Bridge.INITIAL: print(f"set to PENDING") shop_item.status = Bridge.NEEDS_ACTIVATE elif shop_item.status == Bridge.ACTIVE: print(f"is already ACTIVE - assume extend") # ToDo(frennkie): check/set suspend after time shop_item.suspend_after = shop_item.suspend_after + timedelta(seconds=shop_item.host.tor_bridge_duration) elif shop_item.status == Bridge.SUSPENDED or shop_item.status == Bridge.NEEDS_SUSPEND: print(f"is reactivate") shop_item.status = Bridge.NEEDS_ACTIVATE # ToDo(frennkie): check/set suspend after time if shop_item.suspend_after <= timezone.now(): shop_item.suspend_after = timezone.now() + timedelta(seconds=shop_item.host.tor_bridge_duration) shop_item.save() add_change_log_entry(shop_item, "ran lninvoice_paid_handler")
def set_needs_delete_on_initial_tor_bridges(days=3): counter = 0 initials = TorBridge.objects.filter(status=TorBridge.INITIAL) if initials: for item in initials: logger.debug('Running on: %s' % item) if timezone.now() > item.modified_at + timedelta(days=days): logger.debug('Needs to be set to deleted.') item.status = TorBridge.NEEDS_DELETE item.save() add_change_log_entry(item, "set to NEEDS_DELETE") counter += 1 return f'Set NEEDS_DELETE on {counter}/{len(initials)} Tor Bridge(s) (previous state: INITIAL).'
def set_needs_delete_on_suspended_tor_bridges(days=45): counter = 0 suspended = TorBridge.objects.filter(status=TorBridge.SUSPENDED) if suspended: for item in suspended: logger.debug('Running on: %s' % item) if timezone.now() > item.modified_at + timedelta(days=days): logger.debug('Needs to be set to deleted.') item.status = TorBridge.NEEDS_DELETE item.save() add_change_log_entry(item, "set to NEEDS_DELETE") counter += 1 return f'Set NEEDS_DELETE on {counter}/{len(suspended)} Tor Bridge(s) (previous state: SUSPENDED).'
def set_needs_suspend_on_expired_tor_bridges(): counter = 0 actives = TorBridge.objects.filter(status=TorBridge.ACTIVE) if actives: for item in actives: logger.info('Running on: %s' % item) if timezone.now() > item.suspend_after: logger.info('Needs to be suspended.') item.status = TorBridge.NEEDS_SUSPEND item.save() add_change_log_entry(item, "set to NEEDS_SUSPEND") counter += 1 return f'Set NEEDS_SUSPEND on {counter}/{len(actives)} Tor Bridge(s) (previous state: ACTIVE).'
def create(self, host, target, comment=None): tor_bridge = TorBridge.objects.create(comment=comment, host=host, target=target) po = PurchaseOrder.objects.create() po_item = PurchaseOrderItemDetail(price=host.tor_bridge_price_initial, product=tor_bridge, quantity=1) po.item_details.add(po_item, bulk=False) po_item.save() add_change_log_entry(po_item, "added item_details") po.save() add_change_log_entry(po, "new po created") return po
def lnnode_sync_invoice(self): previous_status = self.status super().lnnode_sync_invoice() if previous_status == self.status: return if self.po.status == PurchaseOrder.PAID: return if self.status == self.PAID: self.po.status = PurchaseOrder.PAID self.po.save() add_change_log_entry(self.po, "set to PAID") elif self.status != self.PAID: self.po.status = PurchaseOrder.NEEDS_TO_BE_PAID self.po.save() add_change_log_entry(self.po, "set to NEEDS_TO_BE_PAID")
def lnnode_create_invoice(self): add_change_log_entry(self, "create_invoice on node started") create_result = self.lnnode.create_invoice( memo=f'{self.label}', value=int(self.amount_full_satoshi), expiry=self.expiry) add_change_log_entry(self, "create_invoice on node finished") self.refresh_from_db() # ToDo(frennkie) error handling? _r_hash = create_result.get('r_hash') if _r_hash: self.payment_hash = base64.b64decode(_r_hash) self.status = self.UNPAID self.save() add_change_log_entry(self, "set to UNPAID") self.refresh_from_db() self.lnnode_sync_invoice() lninvoice_invoice_created_on_node.send(sender=self.__class__, instance=self) return True
def post_save_tor_bridge(sender, instance: TorBridge, **kwargs): created = kwargs.get('created') if instance.previous_status != instance.status or created: if instance.status == sender.ACTIVE: instance.process_activation() elif instance.status == sender.NEEDS_SUSPEND: instance.process_suspension() if created: print("Tor Bridge created - setting random port...") instance.port = instance.host.get_random_port() if instance.host.tor_bridge_duration == 0: instance.suspend_after = timezone.make_aware(timezone.datetime.max, timezone.get_default_timezone()) else: instance.suspend_after = timezone.now() \ + timedelta(seconds=instance.host.tor_bridge_duration) \ + timedelta(seconds=getattr(settings, 'SHOP_BRIDGE_DURATION_GRACE_TIME', 600)) instance.save() add_change_log_entry(instance, "created")
def extend(self, request, pk=None): tor_bridge = self.get_object() # create a new PO po = PurchaseOrder.objects.create() po_item = PurchaseOrderItemDetail( price=tor_bridge.host.tor_bridge_price_extension, product=tor_bridge, quantity=1) po.item_details.add(po_item, bulk=False) po_item.save() add_change_log_entry(po_item, "set created") po.save() add_change_log_entry(po, "added item_details") return Response({ 'status': 'ok', 'po_id': po.id, 'po': reverse('v1:purchaseorder-detail', args=(po.id, ), request=request) })
def lnnode_sync_invoice(self): payment_detected = False # ToDo(frennkie) error handling? lookup_result = self.lnnode.get_invoice(r_hash=self.payment_hash) # ToDo(frennkie) sync *complete* data here.. if not self.preimage: _r_preimage = lookup_result.get('r_preimage') if _r_preimage: self.preimage = base64.b64decode(_r_preimage) if not self.payment_request: _payment_request = lookup_result.get('payment_request') if _payment_request: self.payment_request = _payment_request _expiry = lookup_result.get('expiry') if self.expiry: if _expiry: if self.expiry != int(_expiry): self.expiry = int(_expiry) else: if _expiry: self.expiry = int(_expiry) if not self.creation_at: try: _creation_date = lookup_result.get('creation_date') if _creation_date: self.creation_at = make_aware( timezone.datetime.utcfromtimestamp( int(_creation_date))) except TypeError: return if not self.expires_at: if self.creation_at: expire_date = self.creation_at + timezone.timedelta( seconds=self.expiry) self.expires_at = expire_date if not self.qr_image: temp_name, file_obj_qr_image = self.make_qr_image() self.qr_image.save(temp_name, file_obj_qr_image, True) if self.status == self.INITIAL: self.status = self.UNPAID if self.status == self.UNPAID: if lookup_result.get('settled'): payment_detected = True self.status = self.PAID self.paid_at = make_aware( timezone.datetime.utcfromtimestamp( int(lookup_result.get('settle_date')))) if self.has_expired and self.status != self.PAID: self.status = self.EXPIRED self.save() add_change_log_entry(self, f"synced (current status: {self.status})") if payment_detected: print('Has been PAID!') # ToDo(frennkie) remove this add_change_log_entry(self, "payment detected") key = f'ip2tor.metrics.payments.sats' con = get_redis_connection("default") con.rpush(key, self.amount_full_satoshi) lninvoice_paid.send(sender=self.__class__, instance=self) return True
def process_initial_purchase_order(obj_id): logger.info('Running on ID: %s' % obj_id) # checks obj: PurchaseOrder = PurchaseOrder.objects \ .filter(id=obj_id) \ .filter(status=PurchaseOrder.INITIAL) \ .first() if not obj: logger.info('Not found') return None if not obj.total_price_msat: logger.info('No total price - skipping: %s' % obj) return None logger.debug('set to: NEEDS_LOCAL_CHECKS') obj.status = PurchaseOrder.NEEDS_LOCAL_CHECKS obj.save() add_change_log_entry(obj, 'set to: NEEDS_LOCAL_CHECKS') # ToDo(frennkie) this should not live in Django Charged target_with_port = obj.item_details.first().product.target try: target = target_with_port.split(':')[0] except IndexError: target = target_with_port try: target_port = target_with_port.split(':')[1] except IndexError: target_port = 80 if TorDenyList.objects.filter(is_denied=True).filter(target=target): logger.info('Target is on Deny List: %s' % target) obj.status = PurchaseOrder.REJECTED obj.message = "Target is on Deny List" obj.save() add_change_log_entry(obj, 'set to: REJECTED') return None logger.debug('set to: NEEDS_REMOTE_CHECKS') obj.status = PurchaseOrder.NEEDS_REMOTE_CHECKS obj.save() add_change_log_entry(obj, 'set to: NEEDS_REMOTE_CHECKS') # ToDo(frennkie) move to settings (env) whitelisted_service_ports = ['8333', '9735'] if target_port in whitelisted_service_ports: logger.info('REMOTE CHECKS: target port is whitelisted: %s' % target_port) else: url = f'https://{target}:{target_port}/' result = ensure_https(url) if not result: logger.info('REMOTE CHECKS: Target is not HTTPS') obj.status = PurchaseOrder.REJECTED obj.message = "Target is not HTTPS" obj.save() add_change_log_entry(obj, 'set to: REJECTED') return None logger.debug('set to: NEEDS_INVOICE') obj.status = PurchaseOrder.NEEDS_INVOICE obj.save() add_change_log_entry(obj, 'set to: NEEDS_INVOICE') tax_ex_rate_obj = FiatRate.objects \ .filter(is_aggregate=False) \ .filter(fiat_symbol=FiatRate.EUR) \ .first() if tax_ex_rate_obj: tax_ex_rate = tax_ex_rate_obj.rate else: tax_ex_rate = Money(0.00, getattr(settings, 'CHARGED_TAX_CURRENCY_FIAT')) info_ex_rate_obj = FiatRate.objects \ .filter(is_aggregate=False) \ .filter(fiat_symbol=FiatRate.USD) \ .first() if info_ex_rate_obj: info_ex_rate = info_ex_rate_obj.rate else: info_ex_rate = Money(0.00, getattr(settings, 'CHARGED_TAX_CURRENCY_FIAT')) # ToDo(frennkie) check this! owned_nodes = get_all_nodes(obj.owner.id) for node_tuple in owned_nodes: node = node_tuple[1] if not node.is_enabled: continue # skip disabled nodes if not node.is_alive: continue # skip dead nodes invoice = PurchaseOrderInvoice(label="PO: {}".format(obj.id), msatoshi=obj.total_price_msat, tax_rate=Decimal.from_float( getattr(settings, 'CHARGED_TAX_RATE')), tax_currency_ex_rate=tax_ex_rate, info_currency_ex_rate=info_ex_rate, lnnode=node) invoice.save() add_change_log_entry(invoice, f'created poi for po: {obj.id}') obj.ln_invoices.add(invoice) add_change_log_entry(obj, f'added new poi: {invoice.id}') obj.status = PurchaseOrder.NEEDS_TO_BE_PAID obj.save() add_change_log_entry(obj, 'set to: NEEDS_TO_BE_PAID') logger.info('Created LnInvoice: %s (%s)' % (invoice.id, invoice)) break else: raise RuntimeError("no owned nodes found") if invoice: return invoice.id else: raise NoInvoiceCreatedError