lots of fixes related to subscriptions

This commit is contained in:
Believethehype
2024-03-21 13:41:11 +01:00
parent 8a9ba97cb3
commit 1341b7c86b
12 changed files with 236 additions and 133 deletions

View File

@@ -36,7 +36,7 @@ class DVM:
self.dvm_config = dvm_config
self.admin_config = admin_config
self.keys = Keys.parse(dvm_config.PRIVATE_KEY)
wait_for_send = True
wait_for_send = False
skip_disconnected_relays = True
opts = (Options().wait_for_send(wait_for_send).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))
.skip_disconnected_relays(skip_disconnected_relays))
@@ -111,7 +111,7 @@ class DVM:
if task_supported:
# fetch or add user contacting the DVM from/to local database
user = get_or_add_user(self.dvm_config.DB, nip90_event.author().to_hex(), client=self.client,
config=self.dvm_config)
config=self.dvm_config, skip_meta=False)
# if user is blacklisted for some reason, send an error reaction and return
if user.isblacklisted:
send_job_status_reaction(nip90_event, "error", client=self.client, dvm_config=self.dvm_config)
@@ -127,7 +127,8 @@ class DVM:
# If this is a subscription DVM and the Task is directed to us, check for active subscription
if dvm_config.NIP88 is not None and p_tag_str == self.dvm_config.PUBLIC_KEY:
send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client,
"Checking Subscription Status, please wait..",self.dvm_config)
# if we stored in the database that the user has an active subscription, we don't need to check it
print("User Subscription: " + str(user.subscribed) + " Current time: " + str(
Timestamp.now().as_secs()))
@@ -135,14 +136,24 @@ class DVM:
if int(user.subscribed) > int(Timestamp.now().as_secs()):
print("User subscribed until: " + str(Timestamp.from_secs(user.subscribed).to_human_datetime()))
user_has_active_subscription = True
send_job_status_reaction(nip90_event, "subscription-required", True, amount,
self.client, "User subscripton active until " +
Timestamp.from_secs(int(user.subscribed)).to_human_datetime().replace("Z", " ").replace("T", " ") + " GMT", self.dvm_config)
# otherwise we check for an active subscription by checking recipie events
else:
print("[" + self.dvm_config.NIP89.NAME + "] Checking Subscription status")
send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client,
"I Don't have information about subscription status, checking on the Nostr. This might take a few seconds",
self.dvm_config)
subscription_status = nip88_has_active_subscription(PublicKey.parse(user.npub),
self.dvm_config.NIP88.DTAG, self.client,
self.dvm_config.PUBLIC_KEY)
if subscription_status["isActive"]:
send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client,
"User subscripton active until " + Timestamp.from_secs(int(subscription_status["validUntil"])).to_human_datetime().replace("Z", " ").replace("T", " ") + " GMT",
self.dvm_config)
print("Checked Recipe: User subscribed until: " + str(
Timestamp.from_secs(int(subscription_status["validUntil"])).to_human_datetime()))
user_has_active_subscription = True
@@ -151,6 +162,9 @@ class DVM:
self.client, self.dvm_config)
else:
print("No active subscription found")
send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client,
"No active subscription found..",
self.dvm_config)
for dvm in self.dvm_config.SUPPORTED_DVMS:
if dvm.TASK == task and dvm.FIX_COST == 0 and dvm.PER_UNIT_COST == 0 and dvm_config.NIP88 is None:

View File

@@ -33,7 +33,7 @@ class Subscription:
self.dvm_config.NIP89 = nip89config
self.admin_config = admin_config
self.keys = Keys.parse(dvm_config.PRIVATE_KEY)
wait_for_send = True
wait_for_send = False
skip_disconnected_relays = True
opts = (Options().wait_for_send(wait_for_send).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))
.skip_disconnected_relays(skip_disconnected_relays))
@@ -213,7 +213,7 @@ class Subscription:
#rather check nostr if our db is right
subscription_status = nip88_has_active_subscription(
PublicKey.parse(subscriber),
tier_dtag, self.client, recipient)
tier_dtag, self.client, recipient, checkCanceled=False)
if not subscription_status["isActive"]:
success = pay_zap_split(nwc, overall_amount, jsonevent['zaps'])
@@ -307,7 +307,7 @@ class Subscription:
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":
elif subscription.cadence == "yearly":
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):

View File

@@ -225,11 +225,16 @@ def update_user_subscription(npub, subscribed_until, client, dvm_config):
send_event(evt, client=client, dvm_config=dvm_config)
def get_or_add_user(db, npub, client, config, update=False):
def get_or_add_user(db, npub, client, config, update=False, skip_meta = False):
user = get_from_sql_table(db, npub)
if user is None:
try:
name, nip05, lud16 = fetch_user_metadata(npub, client)
if skip_meta:
name = npub
nip05 = ""
lud16 = ""
else:
name, nip05, lud16 = fetch_user_metadata(npub, client)
print("Adding User: " + npub + " (" + npub + ")")
add_to_sql_table(db, npub, config.NEW_USER_BALANCE, False, False, nip05,
lud16, name, Timestamp.now().as_secs(), 0)

View File

@@ -19,7 +19,7 @@ class DVMConfig:
RELAY_LIST = ["wss://relay.damus.io", "wss://nos.lol", "wss://nostr.wine",
"wss://nostr.mom", "wss://nostr.oxtr.dev", "wss://relay.nostr.bg",
"wss://relay.f7z.io", "wss://pablof7z.nostr1.com", "wss://relay.nostr.net", "wss://140.f7z.io",
"wss://relay.snort.social", "wss://offchain.pub/", "wss://relay.nostr.band"]
"wss://relay.snort.social", "wss://offchain.pub/"]
RELAY_TIMEOUT = 5
EXTERNAL_POST_PROCESS_TYPE = PostProcessFunctionType.NONE # Leave this on None, except the DVM is external

View File

@@ -89,7 +89,7 @@ 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, receiver_public_key_hex):
def nip88_has_active_subscription(user: PublicKey, tiereventdtag, client: Client, receiver_public_key_hex, checkCanceled = True):
subscription_status = {
"isActive": False,
"validUntil": 0,
@@ -100,7 +100,7 @@ def nip88_has_active_subscription(user: PublicKey, tiereventdtag, client: Client
subscriptionfilter = Filter().kind(definitions.EventDefinitions.KIND_NIP88_PAYMENT_RECIPE).pubkey(
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))
evts = client.get_events_of([subscriptionfilter], timedelta(seconds=3))
if len(evts) > 0:
print(evts[0].as_json())
matchesdtag = False
@@ -116,12 +116,12 @@ 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"]:
if subscription_status["isActive"] and checkCanceled:
# if subscription seems active, check if it has been canceled, and if so mark it as expiring.
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))
cancel_events = client.get_events_of([cancel_filter], timedelta(seconds=3))
if len(cancel_events) > 0:
if cancel_events[0].created_at().as_secs() > evts[0].created_at().as_secs():
subscription_status["expires"] = True

View File

@@ -186,8 +186,12 @@ def build_status_reaction(status, task, amount, content, dvm_config):
alt_description = "This is a reaction to a NIP90 DVM AI task. "
if status == "processing":
alt_description = "NIP90 DVM AI task " + task + " started processing. "
reaction = alt_description + emoji.emojize(":thumbs_up:")
if content is not None and content != "":
alt_description = content
reaction = alt_description
else:
alt_description = "NIP90 DVM AI task " + task + " started processing. "
reaction = alt_description + emoji.emojize(":thumbs_up:")
elif status == "success":
alt_description = "NIP90 DVM AI task " + task + " finished successfully. "
reaction = alt_description + emoji.emojize(":call_me_hand:")
@@ -207,8 +211,13 @@ def build_status_reaction(status, task, amount, content, dvm_config):
reaction = alt_description + emoji.emojize(":orange_heart:")
elif status == "subscription-required":
alt_description = "NIP90 DVM AI task " + task + " requires payment for subscription"
reaction = alt_description + emoji.emojize(":orange_heart:")
if content is not None and content != "":
alt_description = content
reaction = alt_description
else:
alt_description = "NIP90 DVM AI task " + task + " requires payment for subscription"
reaction = alt_description + emoji.emojize(":orange_heart:")

2
ui/noogle/.env_example Normal file
View File

@@ -0,0 +1,2 @@
VITE_NOOGLE_PK=""
VITE_SUBSCRIPTIPON_VERIFIER_PUBKEY=""

View File

@@ -728,10 +728,6 @@ export default {
let jsonentry = JSON.parse(entry.content)
let susbcrition_tier = subscription_tiers.find(x => x.author.toHex() === entry.author.toHex())
let nip88 = {
title: "",
image: "",
@@ -817,8 +813,8 @@ export default {
}
console.log("hello")
let subscription_status = await hasActiveSubscription(store.state.pubkey.toHex(), nip88.d, evt.author.toHex(), nip88.amounts)
let subscription_status = await hasActiveSubscription(store.state.pubkey.toHex(), nip88.d, evt.author.toHex())
nip88.hasActiveSubscription = subscription_status.isActive
nip88.subscribedUntil = subscription_status.validUntil
nip88.subscriptionId = subscription_status.subscriptionId

View File

@@ -48,7 +48,7 @@
</div>
<div class="flex" v-if="!zapped" @click="zap_local(lud16, id, authorid)">
<div class="flex" v-if="lud16 != null && lud16 != '' && !zapped" @click="zap_local(lud16, id, authorid)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg style="margin-top:4px" 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"/>
@@ -58,7 +58,7 @@
<p style="float: left;">{{zapAmount/1000}}</p>
</div>
</div>
<div class="flex" v-if="zapped" @click="zap_local(lud16, id, authorid)" >
<div class="flex" v-if="lud16 != null && lud16 != '' && zapped" @click="zap_local(lud16, id, authorid)" >
<div style="margin-left: auto; margin-right: 5px;">
<svg style="margin-top:4px" xmlns="http://www.w3.org/2000/svg" width="14" height="16" class="bi bi-lightning fill-amber-400" 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-.641z"/>
@@ -93,7 +93,6 @@ import {Event, EventBuilder, EventId, PublicKey} from "@rust-nostr/nostr-sdk";
import amberSignerService from "@/components/android-signer/AndroidSigner";
import {zap, zap_lud16, createBolt11Lud16, zaprequest} from "@/components/helper/Zap.vue";
const props = defineProps<{
data: any[]
@@ -140,23 +139,50 @@ async function react(eventid, authorid){
objects.reacted = true
objects.reactions += 1
//props.data.push.apply(props.data.find(x=> x.id === eventid), objects)
console.log("reacted")
}
}
}
async function zap_local(lud16, eventid, authorid){
let success = await zap_lud16(lud16, eventid, authorid)
if (success){
let objects = props.data.find(x=> x.id === eventid)
if (objects !== undefined){
objects.zapped = true
objects.zapAmount += 21000
async function zap_local(lud16, eventid, authorid) {
if (lud16 == undefined || lud16 == ""){
console.log("User has no lightning address")
return
}
let success = await zap_lud16(lud16, eventid, authorid)
try {
if (success) {
let objects = props.data.find(x => x.id === eventid)
console.log(objects)
if (objects !== undefined) {
objects.zapped = true
objects.zapAmount += 21000
let index = props.data.indexOf(x => x.id === eventid)
props.data[index] = objects
console.log("zapped")
}
}
}
catch (error)
{
console.log(error)
}
}

File diff suppressed because one or more lines are too long

View File

@@ -369,7 +369,7 @@ export async function fetchAsync (url) {
export async function hasActiveSubscription(pubkeystring, tiereventdtag, tierauthorid, amounts) {
export async function hasActiveSubscription(pubkeystring, tiereventdtag, tierauthorid) {
console.log("Checking for subscription")
let client = store.state.client

View File

@@ -9,8 +9,8 @@ const store = createStore({
signer: NostrSigner,
dbclient: Client,
pubkey: PublicKey,
nooglekey: "ece3c0aa759c3e895ecb3c13ab3813c0f98430c6d4bd22160b9c2219efc9cf0e",
subscription_verifier_pubkey: "5b5c045ecdf66fb540bdf2049fe0ef7f1a566fa427a4fe50d400a011b65a3a7e",
nooglekey: import.meta.env.VITE_NOOGLE_PK,
subscription_verifier_pubkey: import.meta.env.VITE_SUBSCRIPTIPON_VERIFIER_PUBKEY,
requestidSearch: String,
requestidSearchProfile: String,
requestidImage: String,