mirror of
https://github.com/believethehype/nostrdvm.git
synced 2025-11-19 22:26:28 +01:00
lots of fixes related to subscriptions
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
2
ui/noogle/.env_example
Normal file
@@ -0,0 +1,2 @@
|
||||
VITE_NOOGLE_PK=""
|
||||
VITE_SUBSCRIPTIPON_VERIFIER_PUBKEY=""
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user