mirror of
https://github.com/believethehype/nostrdvm.git
synced 2025-09-27 13:56:38 +02:00
fixes
This commit is contained in:
@@ -126,7 +126,7 @@ class DVM:
|
||||
print("[" + self.dvm_config.NIP89.NAME + "] Checking Subscription status")
|
||||
subscription_status = nip88_has_active_subscription(PublicKey.parse(user.npub),
|
||||
self.dvm_config.NIP88.DTAG, self.client,
|
||||
self.dvm_config)
|
||||
self.dvm_config.PUBLIC_KEY)
|
||||
|
||||
if subscription_status["isActive"]:
|
||||
print("User subscribed until: " + str(
|
||||
@@ -317,7 +317,7 @@ class DVM:
|
||||
config=self.dvm_config)
|
||||
|
||||
# a regular note
|
||||
elif not anon:
|
||||
elif not anon and dvm_config.NIP88 is None:
|
||||
print("[" + self.dvm_config.NIP89.NAME + "] Profile Zap received for DVM balance: " +
|
||||
str(invoice_amount) + " Sats from " + str(user.name))
|
||||
update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client,
|
||||
|
@@ -11,10 +11,12 @@ from nostr_sdk import (Keys, Client, Timestamp, Filter, nip04_decrypt, HandleNot
|
||||
from nostr_dvm.utils.database_utils import fetch_user_metadata
|
||||
from nostr_dvm.utils.definitions import EventDefinitions
|
||||
from nostr_dvm.utils.dvmconfig import DVMConfig
|
||||
from nostr_dvm.utils.nip88_utils import nip88_has_active_subscription
|
||||
from nostr_dvm.utils.nip89_utils import NIP89Config
|
||||
from nostr_dvm.utils.nwc_tools import nwc_zap
|
||||
from nostr_dvm.utils.subscription_utils import create_subscription_sql_table, add_to_subscription_sql_table, \
|
||||
get_from_subscription__sql_table, update_subscription_sql_table
|
||||
get_from_subscription_sql_table, update_subscription_sql_table, get_all_subscriptions_from_sql_table, \
|
||||
delete_from_subscription_sql_table
|
||||
from nostr_dvm.utils.zap_utils import create_bolt11_lud16, zaprequest
|
||||
|
||||
|
||||
@@ -95,13 +97,85 @@ class Subscription:
|
||||
kind7001eventid = tag.as_vec()[1]
|
||||
|
||||
if kind7001eventid != "":
|
||||
subscription = get_from_subscription__sql_table("db/subscriptions", kind7001eventid)
|
||||
subscription = get_from_subscription_sql_table("db/subscriptions", kind7001eventid)
|
||||
|
||||
if subscription is not None:
|
||||
update_subscription_sql_table("db/subscriptions", kind7001eventid, recipient,
|
||||
subscription.subscriber, subscription.nwc, subscription.cadence,
|
||||
subscription.amount, subscription.begin, subscription.end,
|
||||
subscription.tier_dtag, subscription.zaps, subscription.recipe, False)
|
||||
subscription.tier_dtag, subscription.zaps, subscription.recipe,
|
||||
False, Timestamp.now().as_secs())
|
||||
|
||||
def infer_subscription_end_time(start, cadence):
|
||||
end = start
|
||||
if cadence == "daily":
|
||||
end = start + 60 * 60 * 24
|
||||
elif cadence == "weekly":
|
||||
end = start + 60 * 60 * 24 * 7
|
||||
elif cadence == "monthly":
|
||||
# TODO check days of month -.-
|
||||
end = start + 60 * 60 * 24 * 31
|
||||
elif cadence == "yearly":
|
||||
# TODO check extra day every 4 years
|
||||
end = start + 60 * 60 * 24 * 356
|
||||
return end
|
||||
|
||||
def pay_zap_split(nwc, overall_amount, zaps):
|
||||
overallsplit = 0
|
||||
|
||||
for zap in zaps:
|
||||
overallsplit += int(zap['split'])
|
||||
|
||||
zapped_amount = 0
|
||||
for zap in zaps:
|
||||
name, nip05, lud16 = fetch_user_metadata(zap['key'], self.client)
|
||||
splitted_amount = math.floor(
|
||||
(int(zap['split']) / overallsplit) * int(overall_amount) / 1000)
|
||||
# invoice = create_bolt11_lud16(lud16, splitted_amount)
|
||||
# TODO add details about DVM in message
|
||||
invoice = zaprequest(lud16, splitted_amount, "DVM subscription", None,
|
||||
PublicKey.parse(zap['key']), self.keys, DVMConfig.RELAY_LIST)
|
||||
print(invoice)
|
||||
if invoice is not None:
|
||||
nwc_event_id = nwc_zap(nwc, invoice, self.keys, zap['relay'])
|
||||
if nwc_event_id is None:
|
||||
print("error zapping " + lud16)
|
||||
else:
|
||||
zapped_amount = zapped_amount + (splitted_amount * 1000)
|
||||
print(str(zapped_amount) + "/" + str(overall_amount))
|
||||
|
||||
if zapped_amount < overall_amount * 0.8: # TODO how do we handle failed zaps for some addresses? we are ok with 80% for now
|
||||
success = False
|
||||
else:
|
||||
print("Zapped successfully")
|
||||
success = True
|
||||
# if no active subscription exists OR the subscription ended, pay
|
||||
|
||||
return success
|
||||
|
||||
def make_subscription_zap_recipe(event7001, recipient, subscriber, start, end, tier_dtag):
|
||||
message = "payed by subscription service"
|
||||
pTag = Tag.parse(["p", recipient])
|
||||
PTag = Tag.parse(["P", subscriber])
|
||||
eTag = Tag.parse(["e", event7001])
|
||||
validTag = Tag.parse(["valid", str(start), str(end)])
|
||||
tierTag = Tag.parse(["tier", tier_dtag])
|
||||
alttag = Tag.parse(["alt", "This is a NIP90 DVM Subscription Payment Recipe"])
|
||||
|
||||
tags = [pTag, PTag, eTag, validTag, tierTag, alttag]
|
||||
|
||||
event = EventBuilder(EventDefinitions.KIND_NIP88_PAYMENT_RECIPE,
|
||||
message, tags).to_event(self.keys)
|
||||
|
||||
dvmconfig = DVMConfig()
|
||||
signer = NostrSigner.keys(self.keys)
|
||||
client = Client(signer)
|
||||
for relay in dvmconfig.RELAY_LIST:
|
||||
client.add_relay(relay)
|
||||
client.connect()
|
||||
recipeid = client.send_event(event)
|
||||
recipe = recipeid.to_hex()
|
||||
return recipe
|
||||
|
||||
def handle_dm(nostr_event):
|
||||
|
||||
@@ -123,105 +197,59 @@ class Subscription:
|
||||
tier_dtag = jsonevent['tier_dtag']
|
||||
|
||||
start = Timestamp.now().as_secs()
|
||||
end = Timestamp.now().as_secs()
|
||||
|
||||
isactivesubscription = False
|
||||
recipe = ""
|
||||
|
||||
subscription = get_from_subscription__sql_table("db/subscriptions", event7001)
|
||||
if subscription is not None and subscription.end > start:
|
||||
start = subscription.end
|
||||
isactivesubscription = True
|
||||
subscription = get_from_subscription_sql_table("db/subscriptions", event7001)
|
||||
#if subscription is not None and subscription.end > start:
|
||||
# start = subscription.end
|
||||
# isactivesubscription = True
|
||||
|
||||
|
||||
|
||||
if cadence == "daily":
|
||||
end = start + 60 * 60 * 24
|
||||
elif cadence == "weekly":
|
||||
end = start + 60 * 60 * 24 * 7
|
||||
elif cadence == "monthly":
|
||||
# TODO check days of month -.-
|
||||
end = start + 60 * 60 * 24 * 31
|
||||
elif cadence == "yearly":
|
||||
# TODO check extra day every 4 years
|
||||
end = start + 60 * 60 * 24 * 356
|
||||
zapsstr = json.dumps(jsonevent['zaps'])
|
||||
print(zapsstr)
|
||||
success = True
|
||||
if subscription is None or subscription.end <= Timestamp.now().as_secs():
|
||||
#rather check nostr if our db is right
|
||||
subscription_status = nip88_has_active_subscription(
|
||||
PublicKey.parse(subscriber),
|
||||
tier_dtag, self.client, recipient)
|
||||
|
||||
overallsplit = 0
|
||||
if not subscription_status["isActive"]:
|
||||
success = pay_zap_split(nwc, overall_amount, jsonevent['zaps'])
|
||||
start = Timestamp.now().as_secs()
|
||||
end = infer_subscription_end_time(start, cadence)
|
||||
else:
|
||||
start = Timestamp.now().as_secs()
|
||||
end = subscription_status["validUntil"]
|
||||
else:
|
||||
start = subscription.begin
|
||||
end = subscription.end
|
||||
|
||||
for zap in jsonevent['zaps']:
|
||||
overallsplit += int(zap['split'])
|
||||
|
||||
zapped_amount = 0
|
||||
for zap in jsonevent['zaps']:
|
||||
name, nip05, lud16 = fetch_user_metadata(zap['key'], self.client)
|
||||
splitted_amount = math.floor(
|
||||
(int(zap['split']) / overallsplit) * int(jsonevent['overall_amount']) / 1000)
|
||||
# invoice = create_bolt11_lud16(lud16, splitted_amount)
|
||||
# TODO add details about DVM in message
|
||||
invoice = zaprequest(lud16, splitted_amount, "DVM subscription", None,
|
||||
PublicKey.parse(zap['key']), self.keys, DVMConfig.RELAY_LIST)
|
||||
print(invoice)
|
||||
if invoice is not None:
|
||||
nwc_event_id = nwc_zap(nwc, invoice, self.keys, zap['relay'])
|
||||
if nwc_event_id is None:
|
||||
print("error zapping " + lud16)
|
||||
else:
|
||||
zapped_amount = zapped_amount + (splitted_amount * 1000)
|
||||
print(str(zapped_amount) + "/" + str(overall_amount))
|
||||
|
||||
if zapped_amount < overall_amount * 0.8: # TODO how do we handle failed zaps for some addresses? we are ok with 80% for now
|
||||
success = False
|
||||
else:
|
||||
print("Zapped successfully")
|
||||
# if no active subscription exists OR the subscription ended, pay
|
||||
|
||||
if success:
|
||||
message = "payed by subscription service"
|
||||
pTag = Tag.parse(["p", recipient])
|
||||
PTag = Tag.parse(["P", subscriber])
|
||||
eTag = Tag.parse(["e", event7001])
|
||||
validTag = Tag.parse(["valid", str(start), str(end)])
|
||||
tierTag = Tag.parse(["tier", tier_dtag])
|
||||
alttag = Tag.parse(["alt", "This is a NIP90 DVM Subscription Payment Recipe"])
|
||||
|
||||
tags = [pTag, PTag, eTag, validTag, tierTag, alttag]
|
||||
|
||||
event = EventBuilder(EventDefinitions.KIND_NIP88_PAYMENT_RECIPE,
|
||||
message, tags).to_event(self.keys)
|
||||
|
||||
dvmconfig = DVMConfig()
|
||||
signer = NostrSigner.keys(self.keys)
|
||||
client = Client(signer)
|
||||
for relay in dvmconfig.RELAY_LIST:
|
||||
client.add_relay(relay)
|
||||
client.connect()
|
||||
recipeid = client.send_event(event)
|
||||
recipe = recipeid.to_hex()
|
||||
recipe = make_subscription_zap_recipe(event7001, recipient, subscriber, start, end, tier_dtag)
|
||||
print("RECIPE " + recipe)
|
||||
isactivesubscription = True
|
||||
|
||||
if subscription is None:
|
||||
add_to_subscription_sql_table("db/subscriptions", event7001, recipient, subscriber, nwc,
|
||||
cadence, overall_amount, start, end, tier_dtag,
|
||||
zapsstr, recipe, isactivesubscription)
|
||||
zapsstr, recipe, isactivesubscription, Timestamp.now().as_secs())
|
||||
print("new subscription entry")
|
||||
else:
|
||||
update_subscription_sql_table("db/subscriptions", event7001, recipient, subscriber, nwc,
|
||||
cadence, overall_amount, start, end,
|
||||
tier_dtag, zapsstr, recipe, isactivesubscription)
|
||||
tier_dtag, zapsstr, recipe, isactivesubscription,
|
||||
Timestamp.now().as_secs())
|
||||
print("updated subscription entry")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print("Error in Subscriber " + str(e))
|
||||
|
||||
@@ -230,9 +258,65 @@ class Subscription:
|
||||
try:
|
||||
while True:
|
||||
time.sleep(60.0)
|
||||
subscriptions = get_all_subscriptions_from_sql_table("db/subscriptions")
|
||||
print("Checking " + str(len(subscriptions)) + " entries..")
|
||||
for subscription in subscriptions:
|
||||
if subscription.active:
|
||||
if subscription.end < Timestamp.now().as_secs():
|
||||
# We could directly zap, but let's make another check if our subscription expired
|
||||
subscription_status = nip88_has_active_subscription(
|
||||
PublicKey.parse(subscription.subscriber),
|
||||
subscription.tier_dtag, self.client, subscription.recipent)
|
||||
|
||||
if not subscription_status["isActive"] or subscription_status["expires"]:
|
||||
update_subscription_sql_table("db/subscriptions", subscription.id,
|
||||
subscription.recipent,
|
||||
subscription.subscriber, subscription.nwc,
|
||||
subscription.cadence, subscription.amount,
|
||||
subscription.begin, subscription.end,
|
||||
subscription.tier_dtag, subscription.zaps,
|
||||
subscription.recipe,
|
||||
False,
|
||||
Timestamp.now().as_secs())
|
||||
else:
|
||||
zaps = json.loads(subscription.zaps)
|
||||
success = pay_zap_split(subscription.nwc, subscription.amount, zaps)
|
||||
if success:
|
||||
end = infer_subscription_end_time(Timestamp.now().as_secs(), subscription.cadence)
|
||||
recipe = make_subscription_zap_recipe(subscription.id, subscription.recipent,
|
||||
subscription.subscriber, subscription.begin,
|
||||
end, subscription.tier_dtag)
|
||||
else:
|
||||
end = Timestamp.now().as_secs()
|
||||
recipe = subscription.recipe
|
||||
|
||||
update_subscription_sql_table("db/subscriptions", subscription.id,
|
||||
subscription.recipent,
|
||||
subscription.subscriber, subscription.nwc,
|
||||
subscription.cadence, subscription.amount,
|
||||
subscription.begin, end,
|
||||
subscription.tier_dtag, subscription.zaps, recipe,
|
||||
success,
|
||||
Timestamp.now().as_secs())
|
||||
print("updated subscription entry")
|
||||
|
||||
|
||||
print("Checking Subscription")
|
||||
else:
|
||||
delete_threshold = 60 * 60 * 24 * 365
|
||||
if subscription.cadence == "daily":
|
||||
delete_threshold = 60 * 60 * 24 * 7 # After 7 days, delete the subscription, user can make a new one
|
||||
elif subscription.cadence == "weekly":
|
||||
delete_threshold = 60 * 60 * 24 * 21 # After 21 days, delete the subscription, user can make a new one
|
||||
elif subscription.cadence == "monthly":
|
||||
delete_threshold = 60 * 60 * 24 * 60 # After 60 days, delete the subscription, user can make a new one
|
||||
elif subscription.cadence == "yearoy":
|
||||
delete_threshold = 60 * 60 * 24 * 500 # After 500 days, delete the subscription, user can make a new one
|
||||
|
||||
if subscription.end < (Timestamp.now().as_secs() - delete_threshold):
|
||||
delete_from_subscription_sql_table("db/subscriptions", subscription.id)
|
||||
print("Delete expired subscription")
|
||||
|
||||
print(str(Timestamp.now().as_secs()) + " Checking Subscription")
|
||||
except KeyboardInterrupt:
|
||||
print('Stay weird!')
|
||||
os.kill(os.getpid(), signal.SIGTERM)
|
||||
|
@@ -219,7 +219,7 @@ def build_example_subscription(name, identifier, admin_config):
|
||||
"lud16": dvm_config.LN_ADDRESS,
|
||||
"encryptionSupported": True,
|
||||
"cashuAccepted": True,
|
||||
"amount": "subscription",
|
||||
"subscription": True,
|
||||
"nip90Params": {
|
||||
"max_results": {
|
||||
"required": False,
|
||||
|
@@ -88,15 +88,16 @@ def nip88_delete_announcement(eid: str, keys: Keys, dtag: str, client: Client, c
|
||||
send_event(event, client, config)
|
||||
|
||||
|
||||
def nip88_has_active_subscription(user: PublicKey, tiereventdtag, client: Client, dvm_config):
|
||||
def nip88_has_active_subscription(user: PublicKey, tiereventdtag, client: Client, receiver_public_key_hex):
|
||||
subscription_status = {
|
||||
"isActive": False,
|
||||
"validUntil": 0,
|
||||
"subscriptionId": "",
|
||||
"expires": False,
|
||||
}
|
||||
|
||||
subscriptionfilter = Filter().kind(definitions.EventDefinitions.KIND_NIP88_PAYMENT_RECIPE).pubkey(
|
||||
PublicKey.parse(dvm_config.PUBLIC_KEY)).custom_tag(SingleLetterTag.uppercase(Alphabet.P),
|
||||
PublicKey.parse(receiver_public_key_hex)).custom_tag(SingleLetterTag.uppercase(Alphabet.P),
|
||||
[user.to_hex()]).limit(1)
|
||||
evts = client.get_events_of([subscriptionfilter], timedelta(seconds=5))
|
||||
if len(evts) > 0:
|
||||
@@ -114,6 +115,17 @@ def nip88_has_active_subscription(user: PublicKey, tiereventdtag, client: Client
|
||||
if subscription_status["validUntil"] > Timestamp.now().as_secs() & matchesdtag:
|
||||
subscription_status["isActive"] = True
|
||||
|
||||
if subscription_status["isActive"]:
|
||||
cancel_filter = Filter().kind(EventDefinitions.KIND_NIP88_STOP_SUBSCRIPTION_EVENT).author(
|
||||
user).pubkey(PublicKey.parse(receiver_public_key_hex)).event(EventId.parse(subscription_status["subscriptionId"])).limit(1)
|
||||
cancel_events = client.get_events_of([cancel_filter], timedelta(seconds=5))
|
||||
if len(cancel_events) > 0:
|
||||
if cancel_events[0].created_at().as_secs() > evts[0].created_at().as_secs():
|
||||
subscription_status["expires"] = True
|
||||
|
||||
|
||||
|
||||
|
||||
return subscription_status
|
||||
|
||||
|
||||
|
@@ -17,6 +17,7 @@ class Subscription:
|
||||
zaps: str
|
||||
recipe: str
|
||||
active: bool
|
||||
lastupdate: int
|
||||
|
||||
|
||||
def create_subscription_sql_table(db):
|
||||
@@ -40,7 +41,8 @@ def create_subscription_sql_table(db):
|
||||
tier_dtag text,
|
||||
zaps text,
|
||||
recipe text,
|
||||
active boolean
|
||||
active boolean,
|
||||
lastupdate int
|
||||
|
||||
|
||||
); """)
|
||||
@@ -52,23 +54,23 @@ def create_subscription_sql_table(db):
|
||||
|
||||
|
||||
def add_to_subscription_sql_table(db, id, recipient, subscriber, nwc, cadence, amount, begin, end, tier_dtag, zaps,
|
||||
recipe, active):
|
||||
recipe, active, lastupdate):
|
||||
try:
|
||||
con = sqlite3.connect(db)
|
||||
cur = con.cursor()
|
||||
data = (id, recipient, subscriber, nwc, cadence, amount, begin, end, tier_dtag, zaps, recipe, active)
|
||||
data = (id, recipient, subscriber, nwc, cadence, amount, begin, end, tier_dtag, zaps, recipe, active, lastupdate)
|
||||
print(id)
|
||||
print(recipient)
|
||||
print(subscriber)
|
||||
print(nwc)
|
||||
cur.execute("INSERT or IGNORE INTO subscriptions VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", data)
|
||||
cur.execute("INSERT or IGNORE INTO subscriptions VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", data)
|
||||
con.commit()
|
||||
con.close()
|
||||
except Error as e:
|
||||
print("Error when Adding to DB: " + str(e))
|
||||
|
||||
|
||||
def get_from_subscription__sql_table(db, id):
|
||||
def get_from_subscription_sql_table(db, id):
|
||||
try:
|
||||
con = sqlite3.connect(db)
|
||||
cur = con.cursor()
|
||||
@@ -91,6 +93,7 @@ def get_from_subscription__sql_table(db, id):
|
||||
subscription.zaps = row[9]
|
||||
subscription.recipe = row[10]
|
||||
subscription.active = row[11]
|
||||
subscription.lastupdate = row[12]
|
||||
|
||||
return subscription
|
||||
|
||||
@@ -99,12 +102,59 @@ def get_from_subscription__sql_table(db, id):
|
||||
return None
|
||||
|
||||
|
||||
def update_subscription_sql_table(db, id, recipient, subscriber, nwc, cadence, amount, begin, end, tier_dtag, zaps,
|
||||
recipe, active):
|
||||
def get_all_subscriptions_from_sql_table(db):
|
||||
try:
|
||||
con = sqlite3.connect(db)
|
||||
cursor = con.cursor()
|
||||
|
||||
sqlite_select_query = """SELECT * from subscriptions"""
|
||||
cursor.execute(sqlite_select_query)
|
||||
records = cursor.fetchall()
|
||||
subscriptions = []
|
||||
for row in records:
|
||||
subscription = Subscription
|
||||
subscription.id = row[0]
|
||||
subscription.recipent = row[1]
|
||||
subscription.subscriber = row[2]
|
||||
subscription.nwc = row[3]
|
||||
subscription.cadence = row[4]
|
||||
subscription.amount = row[5]
|
||||
subscription.begin = row[6]
|
||||
subscription.end = row[7]
|
||||
subscription.tier_dtag = row[8]
|
||||
subscription.zaps = row[9]
|
||||
subscription.recipe = row[10]
|
||||
subscription.active = row[11]
|
||||
subscription.lastupdate = row[12]
|
||||
subscriptions.append(subscription)
|
||||
|
||||
|
||||
cursor.close()
|
||||
return subscriptions
|
||||
|
||||
except sqlite3.Error as error:
|
||||
print("Failed to read data from sqlite table", error)
|
||||
finally:
|
||||
if con:
|
||||
con.close()
|
||||
#print("The SQLite connection is closed")
|
||||
|
||||
def delete_from_subscription_sql_table(db, id):
|
||||
try:
|
||||
con = sqlite3.connect(db)
|
||||
cur = con.cursor()
|
||||
data = (recipient, subscriber, nwc, cadence, amount, begin, end, tier_dtag, zaps, recipe, active, id)
|
||||
cur.execute("DELETE FROM subscriptions WHERE id=?", (id,))
|
||||
con.commit()
|
||||
con.close()
|
||||
except Error as e:
|
||||
print(e)
|
||||
|
||||
def update_subscription_sql_table(db, id, recipient, subscriber, nwc, cadence, amount, begin, end, tier_dtag, zaps,
|
||||
recipe, active, lastupdate):
|
||||
try:
|
||||
con = sqlite3.connect(db)
|
||||
cur = con.cursor()
|
||||
data = (recipient, subscriber, nwc, cadence, amount, begin, end, tier_dtag, zaps, recipe, active, lastupdate, id)
|
||||
|
||||
cur.execute(""" UPDATE subscriptions
|
||||
SET recipient = ? ,
|
||||
@@ -117,7 +167,8 @@ def update_subscription_sql_table(db, id, recipient, subscriber, nwc, cadence, a
|
||||
tier_dtag = ?,
|
||||
zaps = ?,
|
||||
recipe = ?,
|
||||
active = ?
|
||||
active = ?,
|
||||
lastupdate = ?
|
||||
|
||||
WHERE id = ?""", data)
|
||||
con.commit()
|
||||
|
@@ -757,7 +757,7 @@ export default {
|
||||
if(!jsonentry.amount){
|
||||
jsonentry.amount = ""
|
||||
}
|
||||
if(jsonentry.amount === "subscription"){
|
||||
if(jsonentry.subscription === true){
|
||||
// if(susbcrition_tier) {
|
||||
const filter = new Filter().kind(37001).author(entry.author)
|
||||
let tiers = await client.getEventsOf([filter], Duration.fromSecs(5))
|
||||
|
@@ -90,8 +90,8 @@
|
||||
<div style="margin-left: auto; margin-right: 10px;">
|
||||
<p v-if="dvm.amount.toString().toLowerCase()==='free'" class="badge bg-nostr">Free</p>
|
||||
<p v-if="dvm.amount.toString().toLowerCase()==='flexible'" class="badge bg-nostr2" >Flexible</p>
|
||||
<p v-if="dvm.subscription" class="badge text-white bg-gradient-to-br from-pink-500 to-orange-400">Subscription</p>
|
||||
|
||||
<p v-if="dvm.amount.toString().toLowerCase()==='subscription'" class="badge bg-orange-500">Subscription</p>
|
||||
<p v-if="dvm.amount.toString()===''" ></p>
|
||||
<p v-if="!isNaN(parseInt(dvm.amount))" class="text-sm text-gray-600 rounded" ><div class="flex"><svg style="margin-top:3px" xmlns="http://www.w3.org/2000/svg" width="14" height="16" fill="currentColor" class="bi bi-lightning" viewBox="0 0 16 20">
|
||||
<path d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641zM6.374 1 4.168 8.5H7.5a.5.5 0 0 1 .478.647L6.78 13.04 11.478 7H8a.5.5 0 0 1-.474-.658L9.306 1z"/></svg> {{dvm.amount/1000}}</div></p>
|
||||
|
@@ -60,6 +60,9 @@ function set_subscription_props(amount, cadence, dvm) {
|
||||
this.current_subscription_amount = amount
|
||||
this.current_subscription_cadence = cadence
|
||||
this.current_subscription_dvm = dvm
|
||||
this.nwcalby = ""
|
||||
this.nwcmutiny = ""
|
||||
this.nwc = ""
|
||||
|
||||
}
|
||||
|
||||
@@ -905,7 +908,18 @@ const closeNWCModal = () => {
|
||||
|
||||
|
||||
<button v-if="dvm.status !== 'finished' && dvm.status !== 'paid' && dvm.status !== 'payment-required' && dvm.status !== 'subscription-required' && dvm.status !== 'subscription-success' && dvm.status !== 'error' && dvm.status !== 'announced'" className="btn">{{dvm.status}}</button>
|
||||
<button v-if="dvm.status === 'finished'" @click="generate_feed(dvm.id)" className="request-Button">Done, again?</button>
|
||||
<button v-if="dvm.status === 'finished' && !dvm.nip88 ||(dvm.nip88 && !dvm.nip88.hasActiveSubscription)" @click="generate_feed(dvm.id)" class="relative inline-flex items-center justify-center p-0.5 mb-2 me-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-purple-600 to-blue-500 group-hover:from-purple-600 group-hover:to-blue-500 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 dark:focus:ring-blue-800">
|
||||
<span class="relative px-5 py-2.5 transition-all ease-in duration-75 bg-white dark:bg-gray-900 rounded-md group-hover:bg-opacity-0">
|
||||
Done, again?
|
||||
</span>
|
||||
</button>
|
||||
<button v-if="dvm.status === 'finished' && dvm.nip88 && dvm.nip88.hasActiveSubscription" @click="generate_feed(dvm.id);" class="relative inline-flex items-center justify-center p-0.5 mb-2 me-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-pink-500 to-orange-400 group-hover:from-pink-500 group-hover:to-orange-400 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-pink-200 dark:focus:ring-pink-800">
|
||||
<span class="relative px-5 py-2.5 transition-all ease-in duration-75 bg-white dark:bg-gray-900 rounded-md group-hover:bg-opacity-0">
|
||||
Done, Again?
|
||||
</span>
|
||||
</button>
|
||||
|
||||
|
||||
<button v-if="dvm.status === 'paid'" className="btn">Paid, waiting for DVM..</button>
|
||||
<button v-if="dvm.status === 'error'" className="btn">Error</button>
|
||||
|
||||
@@ -922,7 +936,7 @@ const closeNWCModal = () => {
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button v-if="dvm.status === 'announced' && dvm.nip88 && dvm.nip88.hasActiveSubscription" @click="generate_feed(dvm.id);"class="relative inline-flex items-center justify-center p-0.5 mb-2 me-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-pink-500 to-orange-400 group-hover:from-pink-500 group-hover:to-orange-400 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-pink-200 dark:focus:ring-pink-800">
|
||||
<button v-if="dvm.status === 'announced' && dvm.nip88 && dvm.nip88.hasActiveSubscription" @click="generate_feed(dvm.id);" class="relative inline-flex items-center justify-center p-0.5 mb-2 me-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-pink-500 to-orange-400 group-hover:from-pink-500 group-hover:to-orange-400 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-pink-200 dark:focus:ring-pink-800">
|
||||
<span class="relative px-5 py-2.5 transition-all ease-in duration-75 bg-white dark:bg-gray-900 rounded-md group-hover:bg-opacity-0">
|
||||
Request
|
||||
</span>
|
||||
@@ -939,8 +953,9 @@ const closeNWCModal = () => {
|
||||
</div>
|
||||
|
||||
<div style="margin-left: auto; margin-right: 3px;">
|
||||
<p v-if="dvm.subscription ==='' && dvm.amount.toString().toLowerCase()==='free'" class="badge bg-nostr" >Free</p>
|
||||
<p v-if="dvm.subscription ==='' && dvm.amount.toString().toLowerCase()==='flexible'" class="badge bg-nostr2" >Flexible</p>
|
||||
<p v-if="!dvm.subscription && dvm.amount.toString().toLowerCase()==='free'" class="badge bg-nostr" >Free</p>
|
||||
<p v-if="!dvm.subscription && dvm.amount.toString().toLowerCase()==='flexible'" class="badge bg-nostr2" >Flexible</p>
|
||||
<p v-if="dvm.nip88" class="badge text-white bg-gradient-to-br from-pink-500 to-orange-400">Subscription</p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
@@ -982,7 +997,7 @@ const closeNWCModal = () => {
|
||||
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<button style="margin-top: 20px;" @click="connect_alby_nwc()">
|
||||
<button v-if="!nwcalby.startsWith('nostr')" style="margin-top: 20px;" @click="connect_alby_nwc()">
|
||||
<svg width="211" height="40" viewBox="0 0 211 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.5" width="210" height="40" rx="6" fill="url(#paint0_linear_1_148)"/>
|
||||
<circle cx="1.575" cy="1.575" r="1.575" transform="matrix(-1 0 0 1 22.1176 13.8575)" fill="black"/>
|
||||
@@ -1004,6 +1019,7 @@ const closeNWCModal = () => {
|
||||
</svg>
|
||||
|
||||
</button>
|
||||
<p style="margin-top: 20px;" v-if="nwcalby.startsWith('nostr')">Connected to Alby Wallet.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1049,7 +1065,12 @@ const closeNWCModal = () => {
|
||||
<form method="dialog">
|
||||
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn" @click="store_nwc(); subscribe_to_dvm()">Subscribe</button>
|
||||
<button @click="store_nwc(); subscribe_to_dvm()" class=" relative inline-flex items-center justify-center p-0.5 mb-2 me-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-pink-500 to-orange-400 group-hover:from-pink-500 group-hover:to-orange-400 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-pink-200 dark:focus:ring-pink-800">
|
||||
<span class="relative px-5 py-2.5 transition-all ease-in duration-75 rounded-md group-hover:bg-opacity-0">
|
||||
Subscribe
|
||||
</span>
|
||||
</button>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
@@ -1060,7 +1081,7 @@ const closeNWCModal = () => {
|
||||
|
||||
<dialog id="subscr" class="modal">
|
||||
<div className="modal-box rounded-3xl inner shadow-lg p-6 flex flex-col items-center transition-all duration-1000 bg-gradient-to-br from-pink-500 to-orange-400 ">
|
||||
<h3 class="font-bold text-lg">Subscribe</h3>
|
||||
<h3 class="font-bold text-lg">Manage your Subscription</h3>
|
||||
<img style="flex: content" :src="dvm.nip88.image"></img>
|
||||
<div class="glass" className="card-body">
|
||||
|
||||
@@ -1076,10 +1097,10 @@ const closeNWCModal = () => {
|
||||
</div>
|
||||
<br>
|
||||
<h3 v-if="dvm.nip88.hasActiveSubscription && !dvm.nip88.expires ">Subscription renewing at
|
||||
{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[2].trim()}}.{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[1].trim()}}.{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[0].trim().slice(2)}} {{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[1].split("Z")[0].trim()}}</h3>
|
||||
{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[2].trim()}}.{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[1].trim()}}.{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[0].trim().slice(2)}} {{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[1].split("Z")[0].trim()}} GMT</h3>
|
||||
|
||||
<h3 v-if="dvm.nip88.hasActiveSubscription && dvm.nip88.expires ">Subscription expires on
|
||||
{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[2].trim()}}.{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[1].trim()}}.{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[0].trim().slice(2)}} {{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[1].split("Z")[0].trim()}}</h3>
|
||||
{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[2].trim()}}.{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[1].trim()}}.{{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[0].split("-")[0].trim().slice(2)}} {{Timestamp.fromSecs(parseInt(dvm.nip88.subscribedUntil)).toHumanDatetime().split("T")[1].split("Z")[0].trim()}} GMT</h3>
|
||||
<h3 v-if="dvm.nip88.hasActiveSubscription && dvm.nip88.expires"> Changed your mind? Resubscribe! The current subscription will continue with a new NWC string</h3>
|
||||
<div v-if="!dvm.nip88.hasActiveSubscription || dvm.nip88.expires" v-for="amount_item in dvm.nip88.amounts">
|
||||
<br>
|
||||
|
Reference in New Issue
Block a user