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,10 +225,15 @@ 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:
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,

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,6 +186,10 @@ 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":
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":
@@ -207,6 +211,11 @@ def build_status_reaction(status, task, amount, content, dvm_config):
reaction = alt_description + emoji.emojize(":orange_heart:")
elif status == "subscription-required":
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){
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)
if (success){
let objects = props.data.find(x=> x.id === eventid)
if (objects !== undefined){
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)
}
}
}

View File

@@ -31,7 +31,7 @@ import {data} from "autoprefixer";
import {requestProvider} from "webln";
import Newnote from "@/components/Newnote.vue";
import SummarizationGeneration from "@/components/SummarizationGeneration.vue"
import {post_note, schedule, copyurl, copyinvoice, sleep, getEvents, get_user_infos, get_zaps, get_reactions, nextInput, getEventsOriginalOrder, parseandreplacenpubsName} from "../components/helper/Helper.vue"
import {sleep, get_user_infos, get_zaps, hasActiveSubscription, getEventsOriginalOrder, parseandreplacenpubsName} from "../components/helper/Helper.vue"
import {zap, createBolt11Lud16, zaprequest} from "../components/helper/Zap.vue"
import { ref } from "vue";
import ModalComponent from "../components/Newnote.vue";
@@ -151,23 +151,22 @@ async function listen() {
if (resonsetorequest === true) {
if (event.kind === 7000) {
try {
//console.log("7000: ", event.content);
// console.log("DVM: " + event.author.toHex())
console.log("7000: ", event.content);
console.log("DVM: " + event.author.toHex())
//miniToastr.showMessage("DVM: " + dvmname, event.content, VueNotifications.types.info)
dvms.find(i => i.id === event.author.toHex()).laststatusid = event.id.toHex()
let ob = dvms.find(i => i.id === event.author.toHex())
console.log(ob)
for (const tag in event.tags) {
if (event.tags[tag].asVec()[0] === "status") {
if (event.content !== "" && event.tags[tag].asVec()[1] === "processing") {
if (event.content !== "" && (event.tags[tag].asVec()[1] === "processing" || event.tags[tag].asVec()[1] === "subscription-required" ) ) {
if(event.tags[tag].asVec().length > 2) {
dvms.find(i => i.id === event.author.toHex()).status = event.tags[tag].asVec()[2]
}
else{
dvms.find(i => i.id === event.author.toHex()).status = event.content
}
}
else{
dvms.find(i => i.id === event.author.toHex()).status = event.tags[tag].asVec()[1]
@@ -549,19 +548,29 @@ async function subscribe_to_dvm() {
}
// We only arrive here if no subscription exists, we might create a 7001 if it doesnt exist and we zap it
let client = store.state.client
if (current_subscription_dvm.value.nip88.subscriptionId === ""){
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).status = "Subscribing, this might take up to a minute.."
store.commit('set_recommendation_dvms', dvms)
if (current_subscription_dvm.value.nip88.subscriptionId === '' || !current_subscription_dvm.value.nip88.subscriptionId ){
let res;
let requestid;
let kind = 7001
let content = "Subscription from noogle.lol"
let tags = [
[ "p", this.current_subscription_dvm.id],
[ "e" , this.current_subscription_dvm.nip88.eventid],
[ "event", JSON.stringify(this.current_subscription_dvm.nip88.event)],
[ "p", current_subscription_dvm.value.id],
[ "e" , current_subscription_dvm.value.nip88.eventid],
[ "event", JSON.stringify(current_subscription_dvm.value.nip88.event)],
[ "amount", (current_subscription_amount.value).toString(), "msats", current_subscription_cadence.value],
]
for(let zap of current_subscription_dvm.value.nip88.zaps){
console.log(zap.key + " " + zap.split)
let zaptag = [ "zap", zap.key, zap.split]
tags.push(zaptag)
}
@@ -580,20 +589,21 @@ async function subscribe_to_dvm() {
await client.sendEvent(Event.fromJson(JSON.stringify(res)))
requestid = res.id;
console.log(requestid)
}
else{
let tags_t = []
for (let tag of tags){
tags_t.push(Tag.parse(tag))
}
let evt = new EventBuilder(kind, content, tags)
let evt = new EventBuilder(kind, content, tags_t)
res = await client.sendEventBuilder(evt);
requestid = res.id
requestid = res.toHex()
console.log(res)
}
current_subscription_dvm.value.nip88.subscriptionId = requestid
console.log(current_subscription_dvm.value.nip88.subscriptionId)
}
@@ -622,31 +632,40 @@ async function subscribe_to_dvm() {
}
// TODO this is only for viewing, check event (happens on page reload now)
let subscribeduntil = Timestamp.now().asSecs()
if (current_subscription_cadence.value === "daily"){
subscribeduntil = Timestamp.now().asSecs() + 60*60*24
}
else if (current_subscription_cadence.value === "weekly"){
subscribeduntil = Timestamp.now().asSecs() + 60*60*24 * 7
}
else if (current_subscription_cadence.value === "monthly"){
subscribeduntil = Timestamp.now().asSecs() + 60*60*24 * 31
}
else if (current_subscription_cadence.value === "yearly"){
subscribeduntil = Timestamp.now().asSecs() + 60*60*24 * 365
}
console.log(content)
let msg = JSON.stringify(content)
console.log(msg)
let id = await nclient.sendDirectMsg(receiver, msg)
console.log(id)
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).nip88.hasActiveSubscription = true
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).nip88.expires = false
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).nip88.subscribedUntil = subscribeduntil
let isSubscribed = false
let timeout = 0
let subscription_status
while (!isSubscribed && timeout < 15){
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).status = "Subscribing, please wait.."
await sleep(5000)
timeout = timeout +1
subscription_status = await hasActiveSubscription(store.state.pubkey.toHex(), current_subscription_dvm.value.nip88.d, current_subscription_dvm.value.id)
if (subscription_status["isActive"] === true){
isSubscribed = true
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).status = "announced"
}
}
console.log(subscription_status)
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).nip88.hasActiveSubscription = subscription_status["isActive"]
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).nip88.expires = false
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).nip88.subscribedUntil = subscription_status.validUntil
if (subscription_status["isActive"] === false){
dvms.find(x => x.nip88.eventid === current_subscription_dvm.value.nip88.eventid).status = "Timeout, please refresh the page"
}
store.commit('set_recommendation_dvms', dvms)
}
catch(error){
console.log(error)
@@ -790,7 +809,7 @@ 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' && !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">
<button v-if="(dvm.status === 'finished' && !dvm.nip88) || (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-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>
@@ -812,7 +831,7 @@ const closeNWCModal = () => {
<button v-if="dvm.status === 'subscription-success'" className="sub-Button" @click="generate_feed(dvm.id);">Subscribed. Request job</button>
<!-- <button v-if="dvm.status === 'announced'" className="request-Button" @click="generate_feed(dvm.id);">Request</button> -->
<button v-if="dvm.status === 'announced' && !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">
<button v-if="(dvm.status === 'announced' && !dvm.nip88)" @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">
Request
</span>
@@ -824,6 +843,15 @@ const closeNWCModal = () => {
</span>
</button>
<button v-if="dvm.status === 'announced' && dvm.nip88 && !dvm.nip88.hasActiveSubscription" onclick='subscr.showModal()' 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">Subscription
</span>
</button>
<!--<h3 v-if="dvm.amount.toString().toLowerCase()==='free'" class="bg-nostr btn rounded-full" >{{ "Free" }}</h3> -->
@@ -832,22 +860,21 @@ const closeNWCModal = () => {
<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.nip88" class="badge text-white bg-gradient-to-br from-pink-500 to-orange-400">Subscription</p>
<!-- <p v-if="dvm.nip88 && !dvm.nip88.hasActiveSubscription" class="badge text-white bg-gradient-to-br from-pink-500 to-orange-400" onclick='subscr.showModal()' >Subscription</p> -->
<button v-if="dvm.nip88 && dvm.nip88.hasActiveSubscription" onclick='subscr.showModal()' class=" badge 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">
Subscription</span>
</button>
</div>
<div>
<div class="playeauthor-wrapper" v-if="dvm.nip88">
<button v-if="!dvm.nip88.hasActiveSubscription" onclick='subscr.showModal()' 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">Subscription
</span>
</button>
<button v-if="dvm.nip88.hasActiveSubscription" onclick='subscr.showModal()' 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">
Active Subscription</span>
</button>
<dialog id="nwc_modal" class="modal">
<div class="modal-box rounded-3xl inner shadow-lg p-6 flex flex-col items-center transition-all duration-1000 bg-base-600/60 ">
<div class="modal-box rounded-2xl inner shadow-lg p-6 flex flex-col items-center transition-all duration-1000 bg-base-600/60 ">
<h3 class="font-bold text-lg">Connect with Nostr Wallet Connect</h3>
<br>
<div class="flex">
@@ -892,7 +919,6 @@ const closeNWCModal = () => {
</button>
<p style="margin-top: 20px;" v-if="nwcalby.startsWith('nostr')">Connected to Alby Wallet.</p>
</div>
</div>
<div class="collapse bg-base-200">
<input type="radio" name="my-accordion-1" />
@@ -911,7 +937,7 @@ const closeNWCModal = () => {
<li class="step">Wallet Connections</li>
<li class="step">Add Connection</li><li class="step">copy the connection string.</li>
</ul>
<textarea class="nwc-Input" style="width: 400px; margin-left: 10px; margin-top: 10px" name="Text1" type="password" placeholder="nostr+walletconnect://..." cols="40" rows="5" v-model="nwcmutiny"></textarea>
<textarea class="nwc-Input" style="width: auto; margin-left: 10px; margin-top: 10px" name="Text1" type="password" placeholder="nostr+walletconnect://..." cols="40" rows="5" v-model="nwcmutiny"></textarea>
</div>
</div>
<div class="collapse bg-base-200">
@@ -926,7 +952,7 @@ const closeNWCModal = () => {
</div>
<div class="collapse-content">
<textarea class="nwc-Input" style="width: 400px; margin-left: 10px; margin-top: 10px" name="Text1" type="password" placeholder="nostr+walletconnect://..." cols="40" rows="5" v-model="nwc"></textarea>
<textarea class="nwc-Input" style="width: auto; margin-left: 10px; margin-top: 10px" name="Text1" type="password" placeholder="nostr+walletconnect://..." cols="40" rows="5" v-model="nwc"></textarea>
</div>
</div>
@@ -953,36 +979,54 @@ 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">Manage your Subscription</h3>
<img style="flex: content; width: 300px" :src="dvm.nip88.image"></img>
<div class="glass" className="card-body">
<img style="flex: content; width: 300px" class="w-full" :src="dvm.nip88.image"></img>
<div class="grid grid-cols-1 gap-6">
<br>
<div className="card-body rounded-2xl bg-black/10 ring-2 ring-white">
<h3 className="card-title">{{dvm.nip88.title}}</h3>
<br>
<h3 style="text-align: left">{{dvm.nip88.description}}</h3>
<br>
<h3 className="card-title">Perks:</h3>
<div v-for="perk in dvm.nip88.perks">
<p style="text-align: left">{{perk}}</p>
<p style="text-align: left">- {{perk}}</p>
</div>
<br>
<h3 v-if="dvm.nip88.hasActiveSubscription && !dvm.nip88.expires ">Subscription renewing at
</div>
<div v-if="dvm.nip88.hasActiveSubscription" className="card-body rounded-2xl bg-black/10 ring-2 ring-black">
<h3 className="card-title" 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()}} GMT</h3>
<h3 v-if="dvm.nip88.hasActiveSubscription && dvm.nip88.expires ">Subscription expires on
<h3 className="card-title" 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()}} 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>
<h3 v-if="dvm.nip88.hasActiveSubscription && dvm.nip88.expires"> Changed your mind? Resubscribe anytime!</h3>
<h3 v-if="dvm.nip88.hasActiveSubscription && dvm.nip88.expires"> The current subscription will then continue with a new Nostr Wallet Connect string</h3>
</div>
<div v-if="!dvm.nip88.hasActiveSubscription || dvm.nip88.expires" v-for="amount_item in dvm.nip88.amounts">
<br>
<div class="grid grid-cols-1 gap-6">
<div class="card card-compact rounded-box bg-black/30 border-black">
<div class="card-body !text-base">
<div class="card-title text-base-100-content font-bold">
<h3 >Subscribe and pay {{amount_item.cadence}}</h3>
<div class="modal-action">
<form method="dialog">
<div class="modal-action" style="margin-right: 5px; margin-left: auto">
<form method="dialog" >
<!-- if there is a button in form, it will close the modal -->
<button className="sub-Button" @click="set_subscription_props(amount_item.amount, amount_item.cadence, dvm)" onclick='nwc_modal.showModal();'>{{ amount_item.amount/1000 }} Sats</button>
</form>
</div>
</div>
</div>
</div>
</div>
@@ -1006,7 +1050,7 @@ const closeNWCModal = () => {
</dialog>
</div>
<p v-if="dvm.amount.toString()===''" ></p>
<p v-if="dvm.subscription ==='' && !isNaN(parseInt(dvm.amount)) && dvm.status !=='subscription-required' && dvm.status !=='subscription-success'" class="badge bg-amber" ><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>
</div>
@@ -1063,6 +1107,13 @@ const closeNWCModal = () => {
width: 350px;
height: 48px;
}
.nwc-Input {
@apply bg-base-200 dark:bg-base-200 dark:text-white focus:ring-white border border-white px-3 py-1.5 text-sm leading-4 text-accent-content transition-colors duration-300 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
}
.d-Input {

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,