more adjustments

This commit is contained in:
Believethehype
2024-06-07 23:45:26 +02:00
parent 8d1ab44b24
commit 8daaba0f7e
17 changed files with 269 additions and 224 deletions

View File

@@ -1,17 +1,19 @@
import asyncio
import json import json
import time import time
from pathlib import Path from pathlib import Path
from threading import Thread from threading import Thread
import dotenv import dotenv
from nostr_sdk import Keys, Client, NostrSigner, Tag, EventBuilder, Filter, HandleNotification, Timestamp, nip04_decrypt from nostr_sdk import Keys, Client, NostrSigner, Tag, EventBuilder, Filter, HandleNotification, Timestamp, \
nip04_decrypt, Event
from nostr_dvm.utils.dvmconfig import DVMConfig from nostr_dvm.utils.dvmconfig import DVMConfig
from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key
from nostr_dvm.utils.definitions import EventDefinitions from nostr_dvm.utils.definitions import EventDefinitions
def nostr_client_test_llm(prompt): async def nostr_client_test_llm(prompt):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
iTag = Tag.parse(["i", prompt, "text"]) iTag = Tag.parse(["i", prompt, "text"])
@@ -28,13 +30,13 @@ def nostr_client_test_llm(prompt):
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) await send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client(): async def nostr_client():
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
sk = keys.secret_key() sk = keys.secret_key()
pk = keys.public_key() pk = keys.public_key()
@@ -42,28 +44,28 @@ def nostr_client():
client = Client(keys) client = Client(keys)
dvmconfig = DVMConfig() dvmconfig = DVMConfig()
for relay in dvmconfig.RELAY_LIST: for relay in dvmconfig.RELAY_LIST:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
dm_zap_filter = Filter().pubkey(pk).kinds([EventDefinitions.KIND_DM, dm_zap_filter = Filter().pubkey(pk).kinds([EventDefinitions.KIND_DM,
EventDefinitions.KIND_ZAP]).since( EventDefinitions.KIND_ZAP]).since(
Timestamp.now()) # events to us specific Timestamp.now()) # events to us specific
dvm_filter = (Filter().kinds([EventDefinitions.KIND_NIP90_RESULT_GENERATE_TEXT, dvm_filter = (Filter().kinds([EventDefinitions.KIND_NIP90_RESULT_GENERATE_TEXT,
EventDefinitions.KIND_FEEDBACK]).since(Timestamp.now())) # public events EventDefinitions.KIND_FEEDBACK]).since(Timestamp.now())) # public events
client.subscribe([dm_zap_filter, dvm_filter]) await client.subscribe([dm_zap_filter, dvm_filter])
nostr_client_test_llm("Tell me a joke about a purple Ostrich!") await nostr_client_test_llm("Tell me a joke about a purple Ostrich!")
print("Sending Job Request") print("Sending Job Request")
#nostr_client_test_image_private("a beautiful ostrich watching the sunset") #nostr_client_test_image_private("a beautiful ostrich watching the sunset")
class NotificationHandler(HandleNotification): class NotificationHandler(HandleNotification):
def handle(self, relay_url, event): def handle(self, relay_url, subscription_id, event: Event):
print(f"Received new event from {relay_url}: {event.as_json()}") print(f"Received new event from {relay_url}: {event.as_json()}")
if event.kind() == 7000: if event.kind() == 7000:
print("[Nostr Client]: " + event.as_json()) print("[Nostr Client]: " + event.as_json())
elif 6000 < event.kind() < 6999: elif 6000 < event.kind().as_u64() < 6999:
print("[Nostr Client]: " + event.as_json()) print("[Nostr Client]: " + event.as_json())
print("[Nostr Client]: " + event.content()) print("[Nostr Client]: " + event.content())
@@ -75,12 +77,12 @@ def nostr_client():
print("[Nostr Client]: " + f"Received new zap:") print("[Nostr Client]: " + f"Received new zap:")
print(event.as_json()) print(event.as_json())
def handle_msg(self, relay_url, msg): async def handle_msg(self, relay_url, msg):
return return
client.handle_notifications(NotificationHandler()) asyncio.create_task(client.handle_notifications(NotificationHandler()))
while True: while True:
time.sleep(5.0) await asyncio.sleep(5.0)
if __name__ == '__main__': if __name__ == '__main__':
@@ -92,5 +94,5 @@ if __name__ == '__main__':
else: else:
raise FileNotFoundError(f'.env file not found at {env_path} ') raise FileNotFoundError(f'.env file not found at {env_path} ')
nostr_dvm_thread = Thread(target=nostr_client()) asyncio.run(nostr_client())
nostr_dvm_thread.start()

View File

@@ -1,3 +1,4 @@
import asyncio
import json import json
import time import time
from pathlib import Path from pathlib import Path
@@ -5,7 +6,7 @@ from threading import Thread
import dotenv import dotenv
from nostr_sdk import Keys, Client, Tag, EventBuilder, Filter, HandleNotification, Timestamp, nip04_decrypt, \ from nostr_sdk import Keys, Client, Tag, EventBuilder, Filter, HandleNotification, Timestamp, nip04_decrypt, \
NostrSigner NostrSigner, Event
from nostr_dvm.utils.dvmconfig import DVMConfig from nostr_dvm.utils.dvmconfig import DVMConfig
from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key
@@ -39,7 +40,7 @@ def nostr_client_test_tts(prompt):
send_event(event, client=client, dvm_config=config) send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client(): async def nostr_client():
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
sk = keys.secret_key() sk = keys.secret_key()
pk = keys.public_key() pk = keys.public_key()
@@ -49,15 +50,15 @@ def nostr_client():
dvmconfig = DVMConfig() dvmconfig = DVMConfig()
for relay in dvmconfig.RELAY_LIST: for relay in dvmconfig.RELAY_LIST:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
dm_zap_filter = Filter().pubkey(pk).kinds([EventDefinitions.KIND_DM, dm_zap_filter = Filter().pubkey(pk).kinds([EventDefinitions.KIND_DM,
EventDefinitions.KIND_ZAP]).since( EventDefinitions.KIND_ZAP]).since(
Timestamp.now()) # events to us specific Timestamp.now()) # events to us specific
dvm_filter = (Filter().kinds([EventDefinitions.KIND_NIP90_RESULT_TEXT_TO_SPEECH, dvm_filter = (Filter().kinds([EventDefinitions.KIND_NIP90_RESULT_TEXT_TO_SPEECH,
EventDefinitions.KIND_FEEDBACK]).since(Timestamp.now())) # public events EventDefinitions.KIND_FEEDBACK]).since(Timestamp.now())) # public events
client.subscribe([dm_zap_filter, dvm_filter]) await client.subscribe([dm_zap_filter, dvm_filter])
nostr_client_test_tts("Hello, this is a test. Mic check one, two.") nostr_client_test_tts("Hello, this is a test. Mic check one, two.")
@@ -66,11 +67,11 @@ def nostr_client():
#nostr_client_test_image_private("a beautiful ostrich watching the sunset") #nostr_client_test_image_private("a beautiful ostrich watching the sunset")
class NotificationHandler(HandleNotification): class NotificationHandler(HandleNotification):
def handle(self, relay_url, event): def handle(self, relay_url, subscription_id, event: Event):
print(f"Received new event from {relay_url}: {event.as_json()}") print(f"Received new event from {relay_url}: {event.as_json()}")
if event.kind() == 7000: if event.kind() == 7000:
print("[Nostr Client]: " + event.as_json()) print("[Nostr Client]: " + event.as_json())
elif 6000 < event.kind() < 6999: elif 6000 < event.kind().as_u64() < 6999:
print("[Nostr Client]: " + event.as_json()) print("[Nostr Client]: " + event.as_json())
print("[Nostr Client]: " + event.content()) print("[Nostr Client]: " + event.content())
@@ -82,12 +83,12 @@ def nostr_client():
print("[Nostr Client]: " + f"Received new zap:") print("[Nostr Client]: " + f"Received new zap:")
print(event.as_json()) print(event.as_json())
def handle_msg(self, relay_url, msg): async def handle_msg(self, relay_url, msg):
return return
client.handle_notifications(NotificationHandler()) asyncio.create_task(client.handle_notifications(NotificationHandler()))
while True: while True:
time.sleep(5.0) await asyncio.sleep(5.0)
if __name__ == '__main__': if __name__ == '__main__':
@@ -99,5 +100,4 @@ if __name__ == '__main__':
else: else:
raise FileNotFoundError(f'.env file not found at {env_path} ') raise FileNotFoundError(f'.env file not found at {env_path} ')
nostr_dvm_thread = Thread(target=nostr_client()) asyncio.run(nostr_client())
nostr_dvm_thread.start()

View File

@@ -1,3 +1,4 @@
import asyncio
import json import json
import time import time
from datetime import timedelta from datetime import timedelta
@@ -6,14 +7,14 @@ from threading import Thread
import dotenv import dotenv
from nostr_sdk import Keys, Client, Tag, EventBuilder, Filter, HandleNotification, Timestamp, nip04_decrypt, \ from nostr_sdk import Keys, Client, Tag, EventBuilder, Filter, HandleNotification, Timestamp, nip04_decrypt, \
NostrSigner, Options NostrSigner, Options, Event
from nostr_dvm.utils.dvmconfig import DVMConfig from nostr_dvm.utils.dvmconfig import DVMConfig
from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key
from nostr_dvm.utils.definitions import EventDefinitions from nostr_dvm.utils.definitions import EventDefinitions
def nostr_client_test(prompt): async def nostr_client_test(prompt):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
iTag = Tag.parse(["i", prompt, "text"]) iTag = Tag.parse(["i", prompt, "text"])
@@ -32,13 +33,13 @@ def nostr_client_test(prompt):
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)
client = Client.with_opts(signer,opts) client = Client.with_opts(signer,opts)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) await send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client(): async def nostr_client():
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
sk = keys.secret_key() sk = keys.secret_key()
pk = keys.public_key() pk = keys.public_key()
@@ -48,28 +49,28 @@ def nostr_client():
dvmconfig = DVMConfig() dvmconfig = DVMConfig()
for relay in dvmconfig.RELAY_LIST: for relay in dvmconfig.RELAY_LIST:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
dm_zap_filter = Filter().pubkey(pk).kinds([EventDefinitions.KIND_DM, dm_zap_filter = Filter().pubkey(pk).kinds([EventDefinitions.KIND_DM,
EventDefinitions.KIND_ZAP]).since( EventDefinitions.KIND_ZAP]).since(
Timestamp.now()) # events to us specific Timestamp.now()) # events to us specific
dvm_filter = (Filter().kinds([EventDefinitions.KIND_NIP90_RESULT_GENERATE_TEXT, dvm_filter = (Filter().kinds([EventDefinitions.KIND_NIP90_RESULT_GENERATE_TEXT,
EventDefinitions.KIND_FEEDBACK]).since(Timestamp.now())) # public events EventDefinitions.KIND_FEEDBACK]).since(Timestamp.now())) # public events
client.subscribe([dm_zap_filter, dvm_filter]) await client.subscribe([dm_zap_filter, dvm_filter])
#nostr_client_test("What has Pablo been up to?") #nostr_client_test("What has Pablo been up to?")
nostr_client_test("What is Gigi talking about recently?") await nostr_client_test("What is Gigi talking about recently?")
print("Sending Job Request") print("Sending Job Request")
class NotificationHandler(HandleNotification): class NotificationHandler(HandleNotification):
def handle(self, relay_url, event): def handle(self, relay_url, subscription_id, event: Event):
print(f"Received new event from {relay_url}: {event.as_json()}") print(f"Received new event from {relay_url}: {event.as_json()}")
if event.kind() == 7000: if event.kind() == 7000:
print("[Nostr Client]: " + event.as_json()) print("[Nostr Client]: " + event.as_json())
elif 6000 < event.kind() < 6999: elif 6000 < event.kind().as_u64() < 6999:
print("[Nostr Client " + event.author().to_bech32() + "]: " + event.as_json()) print("[Nostr Client " + event.author().to_bech32() + "]: " + event.as_json())
print("[Nostr Client " + event.author().to_bech32() + "]: " + event.content()) print("[Nostr Client " + event.author().to_bech32() + "]: " + event.content())
@@ -85,9 +86,10 @@ def nostr_client():
def handle_msg(self, relay_url, msg): def handle_msg(self, relay_url, msg):
return return
client.handle_notifications(NotificationHandler()) asyncio.create_task(client.handle_notifications(NotificationHandler()))
while True: while True:
time.sleep(1) await asyncio.sleep(1)
if __name__ == '__main__': if __name__ == '__main__':
@@ -99,5 +101,4 @@ if __name__ == '__main__':
else: else:
raise FileNotFoundError(f'.env file not found at {env_path} ') raise FileNotFoundError(f'.env file not found at {env_path} ')
nostr_dvm_thread = Thread(target=nostr_client()) asyncio.run(nostr_client())
nostr_dvm_thread.start()

View File

@@ -1,3 +1,4 @@
import asyncio
import io import io
import json import json
import os import os
@@ -32,6 +33,7 @@ def send_request_to_server(request_form, address):
def send_file_to_server(filepath, address): def send_file_to_server(filepath, address):
result = ""
print("Sending file to Server") print("Sending file to Server")
url = ('http://' + address + '/upload') url = ('http://' + address + '/upload')
try: try:
@@ -72,7 +74,8 @@ def check_server_status(jobID, address) -> str | pd.DataFrame:
if log != "": if log != "":
print(log) print(log)
# WAITING = 0, RUNNING = 1, FINISHED = 2, ERROR = 3 # WAITING = 0, RUNNING = 1, FINISHED = 2, ERROR = 3
time.sleep(1.0) asyncio.sleep(1.0)
if status == 2: if status == 2:
try: try:

View File

@@ -150,7 +150,7 @@ class Bot:
index = int(split[0]) - 1 index = int(split[0]) - 1
# if user sends index info, e.g. 1 info, we fetch the nip89 information and reply with it. # if user sends index info, e.g. 1 info, we fetch the nip89 information and reply with it.
if len(split) > 1 and split[1].lower() == "info": if len(split) > 1 and split[1].lower() == "info":
answer_nip89(nostr_event, index, giftwrap, sender) await answer_nip89(nostr_event, index, giftwrap, sender)
# otherwise we probably have to do some work, so build an event from input and send it to the DVM # otherwise we probably have to do some work, so build an event from input and send it to the DVM
else: else:
task = self.dvm_config.SUPPORTED_DVMS[index].TASK task = self.dvm_config.SUPPORTED_DVMS[index].TASK
@@ -198,7 +198,7 @@ class Bot:
self.job_list.append(entry) self.job_list.append(entry)
# send the event to the DVM # send the event to the DVM
send_event(nip90request, client=self.client, dvm_config=self.dvm_config) await send_event(nip90request, client=self.client, dvm_config=self.dvm_config)
# print(nip90request.as_json()) # print(nip90request.as_json())
@@ -220,7 +220,7 @@ class Bot:
"sat).\n Not all DVMs might " "sat).\n Not all DVMs might "
"accept Cashu tokens.") "accept Cashu tokens.")
if giftwrap: if giftwrap:
self.client.send_sealed_msg(PublicKey.parse(sender), message, None) await self.client.send_private_msg(PublicKey.parse(sender), message, None)
else: else:
evt = EventBuilder.encrypted_direct_msg(self.keys, PublicKey.parse(sender), evt = EventBuilder.encrypted_direct_msg(self.keys, PublicKey.parse(sender),
message,None).to_event(self.keys) message,None).to_event(self.keys)
@@ -232,32 +232,32 @@ class Bot:
self.client) self.client)
print(cashu_message) print(cashu_message)
if cashu_message == "success": if cashu_message == "success":
update_user_balance(self.dvm_config.DB, sender, total_amount, client=self.client, await update_user_balance(self.dvm_config.DB, sender, total_amount, client=self.client,
config=self.dvm_config) config=self.dvm_config)
else: else:
time.sleep(2.0) time.sleep(2.0)
message = "Error: " + cashu_message + ". Token has not been redeemed." message = "Error: " + cashu_message + ". Token has not been redeemed."
if giftwrap: if giftwrap:
self.client.send_sealed_msg(PublicKey.parse(sender), message, None) await self.client.send_private_msg(PublicKey.parse(sender), message, None)
else: else:
evt = EventBuilder.encrypted_direct_msg(self.keys, PublicKey.from_hex(sender), message, evt = EventBuilder.encrypted_direct_msg(self.keys, PublicKey.from_hex(sender), message,
None).to_event(self.keys) None).to_event(self.keys)
send_event(evt, client=self.client, dvm_config=self.dvm_config) await send_event(evt, client=self.client, dvm_config=self.dvm_config)
elif decrypted_text.lower().startswith("what's the second best"): elif decrypted_text.lower().startswith("what's the second best"):
time.sleep(3.0) time.sleep(3.0)
message = "No, there is no second best.\n\nhttps://cdn.nostr.build/p/mYLv.mp4" message = "No, there is no second best.\n\nhttps://cdn.nostr.build/p/mYLv.mp4"
if giftwrap: if giftwrap:
self.client.send_sealed_msg(PublicKey.parse(sender), message, None) await self.client.send_private_msg(PublicKey.parse(sender), message, None)
else: else:
evt = EventBuilder.encrypted_direct_msg(self.keys, PublicKey.parse(sender), evt = await EventBuilder.encrypted_direct_msg(self.keys, PublicKey.parse(sender),
message, message,
nostr_event.id()).to_event(self.keys) nostr_event.id()).to_event(self.keys)
send_event(evt, client=self.client, dvm_config=self.dvm_config) await send_event(evt, client=self.client, dvm_config=self.dvm_config)
else: else:
# Build an overview of known DVMs and send it to the user # Build an overview of known DVMs and send it to the user
answer_overview(nostr_event, giftwrap, sender) await answer_overview(nostr_event, giftwrap, sender)
except Exception as e: except Exception as e:
print("Error in bot " + str(e)) print("Error in bot " + str(e))
@@ -314,14 +314,14 @@ class Bot:
client=self.client, config=self.dvm_config) client=self.client, config=self.dvm_config)
time.sleep(2.0) time.sleep(2.0)
if entry["giftwrap"]: if entry["giftwrap"]:
self.client.send_sealed_msg(PublicKey.parse(entry["npub"]), content, None) await self.client.send_private_msg(PublicKey.parse(entry["npub"]), content, None)
else: else:
reply_event = EventBuilder.encrypted_direct_msg(self.keys, reply_event = EventBuilder.encrypted_direct_msg(self.keys,
PublicKey.from_hex(entry['npub']), PublicKey.from_hex(entry['npub']),
content, content,
None).to_event(self.keys) None).to_event(self.keys)
send_event(reply_event, client=self.client, dvm_config=dvm_config) await send_event(reply_event, client=self.client, dvm_config=dvm_config)
print(status + ": " + content) print(status + ": " + content)
print( print(
"[" + self.NAME + "] Received reaction from " + nostr_event.author().to_hex() + " message to orignal sender " + user.name) "[" + self.NAME + "] Received reaction from " + nostr_event.author().to_hex() + " message to orignal sender " + user.name)
@@ -346,7 +346,7 @@ class Bot:
message = "Paid " + str(amount) + " Sats from balance to DVM. New balance is " + str(balance) + " Sats.\n" message = "Paid " + str(amount) + " Sats from balance to DVM. New balance is " + str(balance) + " Sats.\n"
if entry["giftwrap"]: if entry["giftwrap"]:
self.client.send_sealed_msg(PublicKey.parse(entry["npub"]), message, None) await self.client.send_private_msg(PublicKey.parse(entry["npub"]), message, None)
else: else:
evt = EventBuilder.encrypted_direct_msg(self.keys, evt = EventBuilder.encrypted_direct_msg(self.keys,
PublicKey.parse(entry["npub"]), PublicKey.parse(entry["npub"]),
@@ -437,7 +437,7 @@ class Bot:
print("[" + self.NAME + "] Received results, message to orignal sender " + user.name) print("[" + self.NAME + "] Received results, message to orignal sender " + user.name)
time.sleep(1.0) time.sleep(1.0)
if entry["giftwrap"]: if entry["giftwrap"]:
self.client.send_sealed_msg(PublicKey.parse(user.npub), content, None) await self.client.send_private_msg(PublicKey.parse(user.npub), content, None)
else: else:
reply_event = EventBuilder.encrypted_direct_msg(self.keys, reply_event = EventBuilder.encrypted_direct_msg(self.keys,
PublicKey.parse(user.npub), PublicKey.parse(user.npub),
@@ -482,7 +482,7 @@ class Bot:
print("[" + self.NAME + "] Note Zap received for Bot balance: " + str( print("[" + self.NAME + "] Note Zap received for Bot balance: " + str(
invoice_amount) + " Sats from " + str( invoice_amount) + " Sats from " + str(
user.name)) user.name))
update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client, await update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client,
config=self.dvm_config) config=self.dvm_config)
# a regular note # a regular note
@@ -490,13 +490,13 @@ class Bot:
print("[" + self.NAME + "] Profile Zap received for Bot balance: " + str( print("[" + self.NAME + "] Profile Zap received for Bot balance: " + str(
invoice_amount) + " Sats from " + str( invoice_amount) + " Sats from " + str(
user.name)) user.name))
update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client, await update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client,
config=self.dvm_config) config=self.dvm_config)
except Exception as e: except Exception as e:
print("[" + self.NAME + "] Error during content decryption:" + str(e)) print("[" + self.NAME + "] Error during content decryption:" + str(e))
def answer_overview(nostr_event, giftwrap, sender): async def answer_overview(nostr_event, giftwrap, sender):
message = "DVMs that I support:\n\n" message = "DVMs that I support:\n\n"
index = 1 index = 1
for p in self.dvm_config.SUPPORTED_DVMS: for p in self.dvm_config.SUPPORTED_DVMS:
@@ -512,13 +512,13 @@ class Bot:
text = message + "\nSelect an Index and provide an input (e.g. \"2 A purple ostrich\")\nType \"index info\" to learn more about each DVM. (e.g. \"2 info\")\n\n Type \"balance\" to see your current balance" text = message + "\nSelect an Index and provide an input (e.g. \"2 A purple ostrich\")\nType \"index info\" to learn more about each DVM. (e.g. \"2 info\")\n\n Type \"balance\" to see your current balance"
if giftwrap: if giftwrap:
self.client.send_sealed_msg(PublicKey.parse(sender), text, None) await self.client.send_private_msg(PublicKey.parse(sender), text, None)
else: else:
evt = EventBuilder.encrypted_direct_msg(self.keys, PublicKey.parse(sender), evt = EventBuilder.encrypted_direct_msg(self.keys, PublicKey.parse(sender),
text, text,
nostr_event.id()).to_event(self.keys) nostr_event.id()).to_event(self.keys)
send_event(evt, client=self.client, dvm_config=dvm_config) await send_event(evt, client=self.client, dvm_config=dvm_config)
def answer_blacklisted(nostr_event, giftwrap, sender): def answer_blacklisted(nostr_event, giftwrap, sender):
message = "Your are currently blocked from this service." message = "Your are currently blocked from this service."
@@ -530,18 +530,18 @@ class Bot:
message, None).to_event(self.keys) message, None).to_event(self.keys)
send_event(evt, client=self.client, dvm_config=dvm_config) send_event(evt, client=self.client, dvm_config=dvm_config)
def answer_nip89(nostr_event, index, giftwrap, sender): async def answer_nip89(nostr_event, index, giftwrap, sender):
info = print_dvm_info(self.client, index) info = print_dvm_info(self.client, index)
if info is None: if info is None:
info = "No NIP89 Info found for " + self.dvm_config.SUPPORTED_DVMS[index].NAME info = "No NIP89 Info found for " + self.dvm_config.SUPPORTED_DVMS[index].NAME
time.sleep(2.0) time.sleep(2.0)
if giftwrap: if giftwrap:
self.client.send_sealed_msg(PublicKey.parse(sender), info, None) await self.client.send_private_msg(PublicKey.parse(sender), info, None)
else: else:
evt = EventBuilder.encrypted_direct_msg(self.keys, nostr_event.author(), evt = EventBuilder.encrypted_direct_msg(self.keys, nostr_event.author(),
info, None).to_event(self.keys) info, None).to_event(self.keys)
send_event(evt, client=self.client, dvm_config=dvm_config) await send_event(evt, client=self.client, dvm_config=dvm_config)
def build_params(decrypted_text, author, index): def build_params(decrypted_text, author, index):
tags = [] tags = []
@@ -699,11 +699,11 @@ class Bot:
return None return None
await self.client.handle_notifications(NotificationHandler()) asyncio.create_task(self.client.handle_notifications(NotificationHandler()))
try: try:
while True: while True:
time.sleep(1.0) await asyncio.sleep(1.0)
except KeyboardInterrupt: except KeyboardInterrupt:
print('Stay weird!') print('Stay weird!')
os.kill(os.getpid(), signal.SIGTERM) os.kill(os.getpid(), signal.SIGTERM)

View File

@@ -2,6 +2,7 @@ import asyncio
import json import json
import os import os
import subprocess import subprocess
import threading
from datetime import timedelta from datetime import timedelta
from sys import platform from sys import platform
@@ -36,6 +37,8 @@ class DVM:
jobs_on_hold_list: list jobs_on_hold_list: list
def __init__(self, dvm_config, admin_config=None): def __init__(self, dvm_config, admin_config=None):
asyncio.run(self.run_dvm(dvm_config, admin_config)) asyncio.run(self.run_dvm(dvm_config, admin_config))
async def run_dvm(self, dvm_config, admin_config): async def run_dvm(self, dvm_config, admin_config):
@@ -73,14 +76,13 @@ class DVM:
await admin_make_database_updates(adminconfig=self.admin_config, dvmconfig=self.dvm_config, client=self.client) await admin_make_database_updates(adminconfig=self.admin_config, dvmconfig=self.dvm_config, client=self.client)
await self.client.subscribe([dvm_filter, zap_filter], None) await self.client.subscribe([dvm_filter, zap_filter], None)
class NotificationHandler(HandleNotification): class NotificationHandler(HandleNotification):
client = self.client client = self.client
dvm_config = self.dvm_config dvm_config = self.dvm_config
keys = self.keys keys = self.keys
async def handle(self, relay_url, subscription_id, nostr_event: Event): async def handle(self, relay_url, subscription_id, nostr_event: Event):
print(nostr_event.as_json())
if EventDefinitions.KIND_NIP90_EXTRACT_TEXT.as_u64() <= nostr_event.kind().as_u64() <= EventDefinitions.KIND_NIP90_GENERIC.as_u64(): if EventDefinitions.KIND_NIP90_EXTRACT_TEXT.as_u64() <= nostr_event.kind().as_u64() <= EventDefinitions.KIND_NIP90_GENERIC.as_u64():
await handle_nip90_job_event(nostr_event) await handle_nip90_job_event(nostr_event)
elif nostr_event.kind().as_u64() == EventDefinitions.KIND_ZAP.as_u64(): elif nostr_event.kind().as_u64() == EventDefinitions.KIND_ZAP.as_u64():
@@ -118,7 +120,7 @@ class DVM:
if task_supported: if task_supported:
# fetch or add user contacting the DVM from/to local database # fetch or add user contacting the DVM from/to local database
user = await get_or_add_user(self.dvm_config.DB, nip90_event.author().to_hex(), client=self.client, user = await get_or_add_user(self.dvm_config.DB, nip90_event.author().to_hex(), client=self.client,
config=self.dvm_config, skip_meta=False) config=self.dvm_config, skip_meta=False)
# if user is blacklisted for some reason, send an error reaction and return # if user is blacklisted for some reason, send an error reaction and return
if user.isblacklisted: if user.isblacklisted:
await send_job_status_reaction(nip90_event, "error", client=self.client, dvm_config=self.dvm_config) await send_job_status_reaction(nip90_event, "error", client=self.client, dvm_config=self.dvm_config)
@@ -135,7 +137,7 @@ class DVM:
# If this is a subscription DVM and the Task is directed to us, check for active subscription # 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: if dvm_config.NIP88 is not None and p_tag_str == self.dvm_config.PUBLIC_KEY:
await send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, await send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client,
"Checking Subscription Status, please wait..", self.dvm_config) "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 # 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( print("User Subscription: " + str(user.subscribed) + " Current time: " + str(
Timestamp.now().as_secs())) Timestamp.now().as_secs()))
@@ -144,28 +146,30 @@ class DVM:
print("User subscribed until: " + str(Timestamp.from_secs(user.subscribed).to_human_datetime())) print("User subscribed until: " + str(Timestamp.from_secs(user.subscribed).to_human_datetime()))
user_has_active_subscription = True user_has_active_subscription = True
await send_job_status_reaction(nip90_event, "subscription-required", True, amount, await send_job_status_reaction(nip90_event, "subscription-required", True, amount,
self.client, "User subscripton active until " + self.client, "User subscripton active until " +
Timestamp.from_secs(int(user.subscribed)).to_human_datetime().replace( Timestamp.from_secs(
"Z", " ").replace("T", " ") + " GMT", self.dvm_config) 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 # otherwise we check for an active subscription by checking recipie events
else: else:
print("[" + self.dvm_config.NIP89.NAME + "] Checking Subscription status") print("[" + self.dvm_config.NIP89.NAME + "] Checking Subscription status")
await send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, await 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", "I Don't have information about subscription status, checking on the Nostr. This might take a few seconds",
self.dvm_config) self.dvm_config)
subscription_status = nip88_has_active_subscription(PublicKey.parse(user.npub), subscription_status = nip88_has_active_subscription(PublicKey.parse(user.npub),
self.dvm_config.NIP88.DTAG, self.client, self.dvm_config.NIP88.DTAG, self.client,
self.dvm_config.PUBLIC_KEY) self.dvm_config.PUBLIC_KEY)
if subscription_status["isActive"]: if subscription_status["isActive"]:
await send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, await send_job_status_reaction(nip90_event, "subscription-required", True, amount,
"User subscripton active until " + Timestamp.from_secs(int( self.client,
subscription_status[ "User subscripton active until " + Timestamp.from_secs(int(
"validUntil"])).to_human_datetime().replace("Z", subscription_status[
" ").replace( "validUntil"])).to_human_datetime().replace("Z",
"T", " ") + " GMT", " ").replace(
self.dvm_config) "T", " ") + " GMT",
self.dvm_config)
print("Checked Recipe: User subscribed until: " + str( print("Checked Recipe: User subscribed until: " + str(
Timestamp.from_secs(int(subscription_status["validUntil"])).to_human_datetime())) Timestamp.from_secs(int(subscription_status["validUntil"])).to_human_datetime()))
user_has_active_subscription = True user_has_active_subscription = True
@@ -174,9 +178,10 @@ class DVM:
self.client, self.dvm_config) self.client, self.dvm_config)
else: else:
print("No active subscription found") print("No active subscription found")
await send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, await send_job_status_reaction(nip90_event, "subscription-required", True, amount,
"No active subscription found. Manage your subscription at: " + self.dvm_config.SUBSCRIPTION_MANAGEMENT, self.client,
self.dvm_config) "No active subscription found. Manage your subscription at: " + self.dvm_config.SUBSCRIPTION_MANAGEMENT,
self.dvm_config)
for dvm in self.dvm_config.SUPPORTED_DVMS: 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: if dvm.TASK == task and dvm.FIX_COST == 0 and dvm.PER_UNIT_COST == 0 and dvm_config.NIP88 is None:
@@ -185,12 +190,12 @@ class DVM:
cashu_redeemed = False cashu_redeemed = False
if cashu != "": if cashu != "":
print(cashu) print(cashu)
cashu_redeemed, cashu_message, redeem_amount, fees = await redeem_cashu(cashu, self.dvm_config, cashu_redeemed, cashu_message, redeem_amount, fees = await redeem_cashu(cashu, self.dvm_config,
self.client, int(amount)) self.client, int(amount))
print(cashu_message) print(cashu_message)
if cashu_message != "success": if cashu_message != "success":
await send_job_status_reaction(nip90_event, "error", False, amount, self.client, cashu_message, await send_job_status_reaction(nip90_event, "error", False, amount, self.client, cashu_message,
self.dvm_config) self.dvm_config)
return return
# if user is whitelisted or task is free, just do the job # if user is whitelisted or task is free, just do the job
if (user.iswhitelisted or task_is_free or cashu_redeemed) and ( if (user.iswhitelisted or task_is_free or cashu_redeemed) and (
@@ -202,8 +207,8 @@ class DVM:
if dvm_config.SEND_FEEDBACK_EVENTS: if dvm_config.SEND_FEEDBACK_EVENTS:
await send_job_status_reaction(nip90_event, "processing", True, 0, await send_job_status_reaction(nip90_event, "processing", True, 0,
content=self.dvm_config.CUSTOM_PROCESSING_MESSAGE, content=self.dvm_config.CUSTOM_PROCESSING_MESSAGE,
client=self.client, dvm_config=self.dvm_config, user=user) client=self.client, dvm_config=self.dvm_config, user=user)
# when we reimburse users on error make sure to not send anything if it was free # when we reimburse users on error make sure to not send anything if it was free
if user.iswhitelisted or task_is_free: if user.iswhitelisted or task_is_free:
@@ -230,8 +235,8 @@ class DVM:
". Starting processing.. Balance remains at: " + str(user.balance)) ". Starting processing.. Balance remains at: " + str(user.balance))
await send_job_status_reaction(nip90_event, "processing", True, 0, await send_job_status_reaction(nip90_event, "processing", True, 0,
content=self.dvm_config.CUSTOM_PROCESSING_MESSAGE, content=self.dvm_config.CUSTOM_PROCESSING_MESSAGE,
client=self.client, dvm_config=self.dvm_config) client=self.client, dvm_config=self.dvm_config)
await do_work(nip90_event, amount) await do_work(nip90_event, amount)
@@ -243,8 +248,8 @@ class DVM:
"[" + self.dvm_config.NIP89.NAME + "] Hinting user for Subscription: " + "[" + self.dvm_config.NIP89.NAME + "] Hinting user for Subscription: " +
nip90_event.id().to_hex()) nip90_event.id().to_hex())
await send_job_status_reaction(nip90_event, "subscription-required", await send_job_status_reaction(nip90_event, "subscription-required",
False, 0, client=self.client, False, 0, client=self.client,
dvm_config=self.dvm_config) dvm_config=self.dvm_config)
else: else:
bid = 0 bid = 0
for tag in nip90_event.tags(): for tag in nip90_event.tags():
@@ -258,15 +263,16 @@ class DVM:
bid_offer = int(bid / 1000) bid_offer = int(bid / 1000)
if bid_offer >= int(amount): if bid_offer >= int(amount):
await send_job_status_reaction(nip90_event, "payment-required", False, await send_job_status_reaction(nip90_event, "payment-required", False,
int(amount), # bid_offer int(amount), # bid_offer
client=self.client, dvm_config=self.dvm_config) client=self.client, dvm_config=self.dvm_config)
else: # If there is no bid, just request server rate from user else: # If there is no bid, just request server rate from user
print( print(
"[" + self.dvm_config.NIP89.NAME + "] Requesting payment for Event: " + "[" + self.dvm_config.NIP89.NAME + "] Requesting payment for Event: " +
nip90_event.id().to_hex()) nip90_event.id().to_hex())
await send_job_status_reaction(nip90_event, "payment-required", await send_job_status_reaction(nip90_event, "payment-required",
False, int(amount), client=self.client, dvm_config=self.dvm_config) False, int(amount), client=self.client,
dvm_config=self.dvm_config)
@@ -282,7 +288,8 @@ class DVM:
self.keys, self.keys,
self.dvm_config.NIP89.NAME, self.dvm_config.NIP89.NAME,
self.client, self.dvm_config) self.client, self.dvm_config)
user = await get_or_add_user(db=self.dvm_config.DB, npub=sender, client=self.client, config=self.dvm_config) user = await get_or_add_user(db=self.dvm_config.DB, npub=sender, client=self.client,
config=self.dvm_config)
if zapped_event is not None: if zapped_event is not None:
if zapped_event.kind() == EventDefinitions.KIND_FEEDBACK: if zapped_event.kind() == EventDefinitions.KIND_FEEDBACK:
@@ -310,7 +317,7 @@ class DVM:
print(status) print(status)
if job_event.kind() == EventDefinitions.KIND_NIP88_SUBSCRIBE_EVENT: if job_event.kind() == EventDefinitions.KIND_NIP88_SUBSCRIBE_EVENT:
await send_job_status_reaction(job_event, "subscription-success", client=self.client, await send_job_status_reaction(job_event, "subscription-success", client=self.client,
dvm_config=self.dvm_config, user=user) dvm_config=self.dvm_config, user=user)
@@ -323,8 +330,8 @@ class DVM:
if amount <= invoice_amount: if amount <= invoice_amount:
print("[" + self.dvm_config.NIP89.NAME + "] Payment-request fulfilled...") print("[" + self.dvm_config.NIP89.NAME + "] Payment-request fulfilled...")
await send_job_status_reaction(job_event, "processing", client=self.client, await send_job_status_reaction(job_event, "processing", client=self.client,
content=self.dvm_config.CUSTOM_PROCESSING_MESSAGE, content=self.dvm_config.CUSTOM_PROCESSING_MESSAGE,
dvm_config=self.dvm_config, user=user) dvm_config=self.dvm_config, user=user)
indices = [i for i, x in enumerate(self.job_list) if indices = [i for i, x in enumerate(self.job_list) if
x.event == job_event] x.event == job_event]
index = -1 index = -1
@@ -345,8 +352,8 @@ class DVM:
else: else:
await send_job_status_reaction(job_event, "payment-rejected", await send_job_status_reaction(job_event, "payment-rejected",
False, invoice_amount, client=self.client, False, invoice_amount, client=self.client,
dvm_config=self.dvm_config) dvm_config=self.dvm_config)
print("[" + self.dvm_config.NIP89.NAME + "] Invoice was not paid sufficiently") print("[" + self.dvm_config.NIP89.NAME + "] Invoice was not paid sufficiently")
elif zapped_event.kind() == EventDefinitions.KIND_NIP88_SUBSCRIBE_EVENT: elif zapped_event.kind() == EventDefinitions.KIND_NIP88_SUBSCRIBE_EVENT:
print("new subscription, doing nothing") print("new subscription, doing nothing")
@@ -392,7 +399,7 @@ class DVM:
job_ = RequiredJobToWatch(event=nevent, timestamp=Timestamp.now().as_secs()) job_ = RequiredJobToWatch(event=nevent, timestamp=Timestamp.now().as_secs())
self.jobs_on_hold_list.append(job_) self.jobs_on_hold_list.append(job_)
await send_job_status_reaction(nevent, "chain-scheduled", True, 0, await send_job_status_reaction(nevent, "chain-scheduled", True, 0,
client=client, dvm_config=dvmconfig) client=client, dvm_config=dvmconfig)
return False return False
else: else:
@@ -409,12 +416,12 @@ class DVM:
if self.dvm_config.SHOW_RESULT_BEFORE_PAYMENT and not is_paid: if self.dvm_config.SHOW_RESULT_BEFORE_PAYMENT and not is_paid:
await send_nostr_reply_event(data, original_event.as_json()) await send_nostr_reply_event(data, original_event.as_json())
await send_job_status_reaction(original_event, "success", amount, await send_job_status_reaction(original_event, "success", amount,
dvm_config=self.dvm_config, dvm_config=self.dvm_config,
) # or payment-required, or both? ) # or payment-required, or both?
elif not self.dvm_config.SHOW_RESULT_BEFORE_PAYMENT and not is_paid: elif not self.dvm_config.SHOW_RESULT_BEFORE_PAYMENT and not is_paid:
await send_job_status_reaction(original_event, "success", amount, await send_job_status_reaction(original_event, "success", amount,
dvm_config=self.dvm_config, dvm_config=self.dvm_config,
) # or payment-required, or both? ) # or payment-required, or both?
if self.dvm_config.SHOW_RESULT_BEFORE_PAYMENT and is_paid: if self.dvm_config.SHOW_RESULT_BEFORE_PAYMENT and is_paid:
self.job_list.remove(x) self.job_list.remove(x)
@@ -434,12 +441,12 @@ class DVM:
# Zapping back by error in post-processing is a risk for the DVM because work has been done, # Zapping back by error in post-processing is a risk for the DVM because work has been done,
# but maybe something with parsing/uploading failed. Try to avoid errors here as good as possible # but maybe something with parsing/uploading failed. Try to avoid errors here as good as possible
await send_job_status_reaction(original_event, "error", await send_job_status_reaction(original_event, "error",
content="Error in Post-processing: " + str(e), content="Error in Post-processing: " + str(e),
dvm_config=self.dvm_config, dvm_config=self.dvm_config,
) )
if amount > 0 and self.dvm_config.LNBITS_ADMIN_KEY != "": if amount > 0 and self.dvm_config.LNBITS_ADMIN_KEY != "":
user = await get_or_add_user(self.dvm_config.DB, original_event.author().to_hex(), user = await get_or_add_user(self.dvm_config.DB, original_event.author().to_hex(),
client=self.client, config=self.dvm_config) client=self.client, config=self.dvm_config)
print(user.lud16 + " " + str(amount)) print(user.lud16 + " " + str(amount))
bolt11 = zaprequest(user.lud16, amount, "Couldn't finish job, returning sats", bolt11 = zaprequest(user.lud16, amount, "Couldn't finish job, returning sats",
original_event, "", original_event, "",
@@ -498,8 +505,8 @@ class DVM:
original_event.kind().as_u64() + 1000) + " Job Response event sent: " + reply_event.as_json() + bcolors.ENDC) original_event.kind().as_u64() + 1000) + " Job Response event sent: " + reply_event.as_json() + bcolors.ENDC)
async def send_job_status_reaction(original_event, status, is_paid=True, amount=0, client=None, async def send_job_status_reaction(original_event, status, is_paid=True, amount=0, client=None,
content=None, content=None,
dvm_config=None, user=None): dvm_config=None, user=None):
task = get_task(original_event, client=client, dvm_config=dvm_config) task = get_task(original_event, client=client, dvm_config=dvm_config)
alt_description, reaction = build_status_reaction(status, task, amount, content, dvm_config) alt_description, reaction = build_status_reaction(status, task, amount, content, dvm_config)
@@ -654,18 +661,18 @@ class DVM:
print(bcolors.RED + "[" + self.dvm_config.NIP89.NAME + "] Error: " + str( print(bcolors.RED + "[" + self.dvm_config.NIP89.NAME + "] Error: " + str(
e) + bcolors.ENDC) e) + bcolors.ENDC)
await send_job_status_reaction(job_event, "error", content=str(e), await send_job_status_reaction(job_event, "error", content=str(e),
dvm_config=self.dvm_config) dvm_config=self.dvm_config)
except Exception as e: except Exception as e:
print( print(
bcolors.RED + "[" + self.dvm_config.NIP89.NAME + "] Error: " + str(e) + bcolors.ENDC) bcolors.RED + "[" + self.dvm_config.NIP89.NAME + "] Error: " + str(e) + bcolors.ENDC)
# we could send the exception here to the user, but maybe that's not a good idea after all. # we could send the exception here to the user, but maybe that's not a good idea after all.
await send_job_status_reaction(job_event, "error", content=result, await send_job_status_reaction(job_event, "error", content=result,
dvm_config=self.dvm_config) dvm_config=self.dvm_config)
# Zapping back the user on error # Zapping back the user on error
if amount > 0 and self.dvm_config.LNBITS_ADMIN_KEY != "": if amount > 0 and self.dvm_config.LNBITS_ADMIN_KEY != "":
user = await get_or_add_user(self.dvm_config.DB, job_event.author().to_hex(), user = await get_or_add_user(self.dvm_config.DB, job_event.author().to_hex(),
client=self.client, config=self.dvm_config) client=self.client, config=self.dvm_config)
print(user.lud16 + " " + str(amount)) print(user.lud16 + " " + str(amount))
bolt11 = zaprequest(user.lud16, amount, "Couldn't finish job, returning sats", job_event, bolt11 = zaprequest(user.lud16, amount, "Couldn't finish job, returning sats", job_event,
PublicKey.parse(user.npub), PublicKey.parse(user.npub),
@@ -680,15 +687,16 @@ class DVM:
return return
await self.client.handle_notifications(NotificationHandler()) #await self.client.handle_notifications(NotificationHandler)
while True: asyncio.create_task(self.client.handle_notifications(NotificationHandler()))
while True:
for dvm in self.dvm_config.SUPPORTED_DVMS: for dvm in self.dvm_config.SUPPORTED_DVMS:
scheduled_result = await dvm.schedule(self.dvm_config) await dvm.schedule(self.dvm_config)
for job in self.job_list: for job in self.job_list:
if job.bolt11 != "" and job.payment_hash != "" and not job.payment_hash is None and not job.is_paid: if job.bolt11 != "" and job.payment_hash != "" and not job.payment_hash is None and not job.is_paid:
ispaid = check_bolt11_ln_bits_is_paid(job.payment_hash, self.dvm_config) ispaid = check_bolt11_ln_bits_is_paid(job.payment_hash, se.dvm_config)
if ispaid and job.is_paid is False: if ispaid and job.is_paid is False:
print("is paid") print("is paid")
job.is_paid = True job.is_paid = True
@@ -696,9 +704,9 @@ class DVM:
job.is_paid = True job.is_paid = True
await send_job_status_reaction(job.event, "processing", True, 0, await send_job_status_reaction(job.event, "processing", True, 0,
content=self.dvm_config.CUSTOM_PROCESSING_MESSAGE, content=self.dvm_config.CUSTOM_PROCESSING_MESSAGE,
client=self.client, client=self.client,
dvm_config=self.dvm_config) dvm_config=self.dvm_config)
print("[" + self.dvm_config.NIP89.NAME + "] doing work from joblist") print("[" + self.dvm_config.NIP89.NAME + "] doing work from joblist")
await do_work(job.event, amount) await do_work(job.event, amount)
elif ispaid is None: # invoice expired elif ispaid is None: # invoice expired
@@ -708,8 +716,8 @@ class DVM:
self.job_list.remove(job) self.job_list.remove(job)
for job in self.jobs_on_hold_list: for job in self.jobs_on_hold_list:
if await check_event_has_not_unfinished_job_input(job.event, False, client=self.client, if await check_event_has_not_unfinished_job_input(job.event, False, client=se.client,
dvmconfig=self.dvm_config): dvmconfig=self.dvm_config):
await handle_nip90_job_event(nip90_event=job.event) await handle_nip90_job_event(nip90_event=job.event)
try: try:
self.jobs_on_hold_list.remove(job) self.jobs_on_hold_list.remove(job)
@@ -719,4 +727,4 @@ class DVM:
if Timestamp.now().as_secs() > job.timestamp + 60 * 20: # remove jobs to look for after 20 minutes.. if Timestamp.now().as_secs() > job.timestamp + 60 * 20: # remove jobs to look for after 20 minutes..
self.jobs_on_hold_list.remove(job) self.jobs_on_hold_list.remove(job)
time.sleep(1.0) await asyncio.sleep(1)

View File

@@ -71,7 +71,7 @@ class DVMTaskInterface:
self.admin_config = admin_config self.admin_config = admin_config
asyncio.run(self.init_dvm(name, dvm_config, nip89config, nip88config, asyncio.run(self.init_dvm(name, dvm_config, nip89config, nip88config,
admin_config, options)) admin_config, options))
async def init_dvm(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None, async def init_dvm(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None,
admin_config: AdminConfig = None, options=None): admin_config: AdminConfig = None, options=None):

View File

@@ -451,11 +451,11 @@ class Subscription:
except Exception as e: except Exception as e:
print(e) print(e)
await self.client.handle_notifications(NotificationHandler()) asyncio.create_task(self.client.handle_notifications(NotificationHandler()))
try: try:
while True: while True:
time.sleep(60.0) await asyncio.sleep(60.0)
await check_subscriptions() await check_subscriptions()
except KeyboardInterrupt: except KeyboardInterrupt:
print('Stay weird!') print('Stay weird!')

View File

@@ -1,3 +1,4 @@
import asyncio
import json import json
import os import os
import time import time
@@ -130,7 +131,7 @@ class AudioGenerationSonoAI(DVMTaskInterface):
print(f"{data[1]['id']} ==> {data[1]['video_url']}") print(f"{data[1]['id']} ==> {data[1]['video_url']}")
break break
# sleep 5s # sleep 5s
time.sleep(5) asyncio.sleep(5.0)
response1 = self.get_clip(data[0]['id']) response1 = self.get_clip(data[0]['id'])
print(response1['video_url']) print(response1['video_url'])

View File

@@ -3,7 +3,8 @@ import json
import os import os
from datetime import timedelta from datetime import timedelta
from nostr_sdk import Client, Timestamp, PublicKey, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ from nostr_sdk import Client, Timestamp, PublicKey, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \
ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Event, EventId, Kind ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Event, EventId, Kind, \
RelayLimits
from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv
from nostr_dvm.utils import definitions from nostr_dvm.utils import definitions
@@ -28,7 +29,7 @@ class DicoverContentDBUpdateScheduler(DVMTaskInterface):
FIX_COST: float = 0 FIX_COST: float = 0
dvm_config: DVMConfig dvm_config: DVMConfig
request_form = None request_form = None
last_schedule: int last_schedule: int = 0
min_reactions = 2 min_reactions = 2
db_since = 10 * 3600 db_since = 10 * 3600
db_name = "db/nostr_default_recent_notes.db" db_name = "db/nostr_default_recent_notes.db"
@@ -51,16 +52,6 @@ class DicoverContentDBUpdateScheduler(DVMTaskInterface):
dvm_config.SCRIPT = os.path.abspath(__file__) dvm_config.SCRIPT = os.path.abspath(__file__)
if self.options.get("personalized"):
self.personalized = bool(self.options.get("personalized"))
self.last_schedule = Timestamp.now().as_secs()
if self.options.get("search_list"):
self.search_list = self.options.get("search_list")
# print(self.search_list)
if self.options.get("avoid_list"):
self.avoid_list = self.options.get("avoid_list")
if self.options.get("must_list"):
self.must_list = self.options.get("must_list")
if self.options.get("db_name"): if self.options.get("db_name"):
self.db_name = self.options.get("db_name") self.db_name = self.options.get("db_name")
if self.options.get("db_since"): if self.options.get("db_since"):
@@ -130,7 +121,8 @@ class DicoverContentDBUpdateScheduler(DVMTaskInterface):
return 1 return 1
async def sync_db(self): async def sync_db(self):
opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) relaylimits = RelayLimits.disable()
opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))).relay_limits(relaylimits)
sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY)
keys = Keys.parse(sk.to_hex()) keys = Keys.parse(sk.to_hex())
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)

View File

@@ -168,7 +168,7 @@ def list_db(db):
print(e) print(e)
def update_user_balance(db, npub, additional_sats, client, config, giftwrap=False): async def update_user_balance(db, npub, additional_sats, client, config, giftwrap=False):
user = get_from_sql_table(db, npub) user = get_from_sql_table(db, npub)
if user is None: if user is None:
name, nip05, lud16 = fetch_user_metadata(npub, client) name, nip05, lud16 = fetch_user_metadata(npub, client)
@@ -192,11 +192,11 @@ def update_user_balance(db, npub, additional_sats, client, config, giftwrap=Fals
new_balance) + " Sats.") new_balance) + " Sats.")
if giftwrap: if giftwrap:
client.send_sealed_msg(PublicKey.parse(npub), message, None) await client.send_private_msg(PublicKey.parse(npub), message, None)
else: else:
evt = EventBuilder.encrypted_direct_msg(keys, PublicKey.parse(npub), message, evt = EventBuilder.encrypted_direct_msg(keys, PublicKey.parse(npub), message,
None).to_event(keys) None).to_event(keys)
send_event(evt, client=client, dvm_config=config) await send_event(evt, client=client, dvm_config=config)
def update_user_subscription(npub, subscribed_until, client, dvm_config): def update_user_subscription(npub, subscribed_until, client, dvm_config):

View File

@@ -31,14 +31,19 @@ use_logger = True
AVOID_PAID_OUTBOX_RELAY_LIST = ["wss://nostrelay.yeghro.site", "wss://nostr.wine", "wss://filter.nostr.wine" AVOID_PAID_OUTBOX_RELAY_LIST = ["wss://nostrelay.yeghro.site", "wss://nostr.wine", "wss://filter.nostr.wine"
"wss://nostr21.com", "wss://nostr.bitcoiner.social", "wss://nostr.orangepill.dev", "wss://nostr21.com", "wss://nostr.bitcoiner.social", "wss://nostr.orangepill.dev",
"wss://relay.lnpay.me", "wss://relay.snort.social", "wss://relay.minds.com/nostr/v1/ws", "wss://relay.lnpay.me", "wss://relay.snort.social", "wss://relay.minds.com/nostr/v1/ws",
"wss://nostr-pub.semisol.dev", "wss://mostr.pub", "wss://minds.com", "wss://nostr-pub.semisol.dev", "wss://mostr.pub", "wss://relay.mostr.pub", "wss://minds.com",
"wss://yabu.me", "wss://relay.yozora.world", "wss://filter.nostr.wine/?global=all", "wss://eden.nostr.land", "wss://yabu.me", "wss://relay.yozora.world", "wss://filter.nostr.wine/?global=all", "wss://eden.nostr.land",
"wss://relay.orangepill.ovh", "wss://nostr.jcloud.es", "wss://af.purplerelay.com", "wss://za.purplerelay.com", "wss://relay.orangepill.ovh", "wss://nostr.jcloud.es", "wss://af.purplerelay.com", "wss://za.purplerelay.com",
"wss://relay.nostrich.land", "wss://relay.nostrplebs.com", "wss://relay.nostrich.land", "wss://relay.nostrich.land", "wss://relay.nostrplebs.com", "wss://relay.nostrich.land",
"wss://rss.nos.social", "wss://atlas.nostr.land", "wss://puravida.nostr.land", "wss://nostr.inosta.cc", "wss://rss.nos.social", "wss://atlas.nostr.land", "wss://puravida.nostr.land", "wss://nostr.inosta.cc",
"wss://relay.orangepill.dev", "wss://no.str.cr", "wss://nostr.milou.lol", "wss://relay.nostr.com.au", "wss://relay.orangepill.dev", "wss://no.str.cr", "wss://nostr.milou.lol", "wss://relay.nostr.com.au",
"wss://puravida.nostr.land", "wss://atlas.nostr.land", "wss://nostr-pub.wellorder.net", "wss://eelay.current.fyi", "wss://puravida.nostr.land", "wss://atlas.nostr.land", "wss://nostr-pub.wellorder.net", "wss://eelay.current.fyi",
"wss://nostr.thesamecat.io", "wss://nostr.plebchain.org", "wss://relay.noswhere.com" "wss://nostr.thesamecat.io", "wss://nostr.plebchain.org", "wss://relay.noswhere.com", "wss://nostr.uselessshit.co",
"wss://bitcoiner.social", "wss://relay.stoner.com", "wss://nostr.l00p.org", "wss://relay.nostr.ro", "wss://nostr.kollider.xyz",
"wss://relay.valera.co", "wss://relay.austrich.net", "wss://relay.nostrich.de", "wss://nostr.azte.co", "wss://nostr-relay.schnitzel.world",
"wss://relay.nostriches.org", "wss://happytavern.co", "wss://onlynotes.lol", "wss://offchain.pub", "wss://purplepag.es", "wss://relay.plebstr.com"
"wss://poster.place/relay", "wss://relayable.org"
] ]
@@ -47,7 +52,7 @@ AVOID_PAID_OUTBOX_RELAY_LIST = ["wss://nostrelay.yeghro.site", "wss://nostr.wine
#print("GitHash " + git_hash) #print("GitHash " + git_hash)
if use_logger: if use_logger:
init_logger(LogLevel.DEBUG) init_logger(LogLevel.INFO)
def build_db_scheduler(name, identifier, admin_config, options, image, description, update_rate=600, cost=0, def build_db_scheduler(name, identifier, admin_config, options, image, description, update_rate=600, cost=0,
@@ -540,6 +545,26 @@ def playground():
update_db=update_db) update_db=update_db)
discovery_global.run() discovery_global.run()
# discovery_test_sub = content_discovery_currently_popular.build_example_subscription("Currently Popular Notes DVM (with Subscriptions)", "discovery_content_test", admin_config)
# discovery_test_sub.run()
# Subscription Manager DVM
# subscription_config = DVMConfig()
# subscription_config.PRIVATE_KEY = check_and_set_private_key("dvm_subscription")
# npub = Keys.parse(subscription_config.PRIVATE_KEY).public_key().to_bech32()
# invoice_key, admin_key, wallet_id, user_id, lnaddress = check_and_set_ln_bits_keys("dvm_subscription", npub)
# subscription_config.LNBITS_INVOICE_KEY = invoice_key
# subscription_config.LNBITS_ADMIN_KEY = admin_key # The dvm might pay failed jobs back
# subscription_config.LNBITS_URL = os.getenv("LNBITS_HOST")
# sub_admin_config = AdminConfig()
# sub_admin_config.USERNPUBS = ["7782f93c5762538e1f7ccc5af83cd8018a528b9cd965048386ca1b75335f24c6"] #Add npubs of services that can contact the subscription handler
# currently there is none, but add this once subscriptions are live.
# x = threading.Thread(target=Subscription, args=(Subscription(subscription_config, sub_admin_config),))
# x.start()
# keep_alive()
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -1,4 +1,5 @@
import asyncio import asyncio
import json
from datetime import timedelta from datetime import timedelta
from nostr_sdk import Options, SecretKey, NostrSigner, Keys, Client, RelayOptions, Alphabet, SingleLetterTag, Filter, \ from nostr_sdk import Options, SecretKey, NostrSigner, Keys, Client, RelayOptions, Alphabet, SingleLetterTag, Filter, \
@@ -21,36 +22,36 @@ async def main():
ropts = RelayOptions().ping(False) ropts = RelayOptions().ping(False)
await cli.add_relay_with_opts(options["relay"], ropts) await cli.add_relay_with_opts(options["relay"], ropts)
await cli.connect() await cli.connect()
userkeys = [] ltags = ["#e", "pub.ditto.trends"]
itags = [str(SingleLetterTag.lowercase(Alphabet.E))]
ltags = ["pub.ditto.trends"]
authors = [PublicKey.parse("db0e60d10b9555a39050c258d460c5c461f6d18f467aa9f62de1a728b8a891a4")] authors = [PublicKey.parse("db0e60d10b9555a39050c258d460c5c461f6d18f467aa9f62de1a728b8a891a4")]
notes_filter = Filter().kinds([Kind(1985)]).authors(authors).custom_tag(SingleLetterTag.uppercase(Alphabet.L), notes_filter = Filter().authors(authors).custom_tag(SingleLetterTag.lowercase(Alphabet.L), ltags)
ltags).custom_tag(
SingleLetterTag.uppercase(Alphabet.I), ["e"])
events = await cli.get_events_of([notes_filter], timedelta(seconds=5)) events = await cli.get_events_of([notes_filter], timedelta(seconds=10))
result_list = [] result_list = []
if len(events) > 0: if len(events) > 0:
event = events[0] event = events[0]
print(event)
result_list = [] result_list = []
for tag in event.tags(): for tag in event.tags():
print(tag.as_vec())
if tag.as_vec()[0] == "e": if tag.as_vec()[0] == "e":
e_tag = Tag.parse(["e", tag.as_vec()[1], tag.as_vec()[2]]) e_tag = Tag.parse(["e", tag.as_vec()[1], tag.as_vec()[2]])
result_list.append(e_tag.as_vec()) result_list.append(e_tag.as_vec())
print(tag.as_vec())
else: else:
print("Nothing found") print("Nothing found")
# for event in events: # for event in events:
# e_tag = Tag.parse(["e", event.id().to_hex()]) # e_tag = Tag.parse(["e", event.id().to_hex()])
# result_list.append(e_tag.as_vec()) return ""
await cli.shutdown() await cli.shutdown()
# return json.dumps(result_list) print(json.dumps(result_list))
return json.dumps(result_list)
asyncio.run(main()) asyncio.run(main())

View File

@@ -1,3 +1,4 @@
import asyncio
import json import json
import time import time
from datetime import timedelta from datetime import timedelta
@@ -85,7 +86,7 @@ def init():
if len(events) == 0: if len(events) == 0:
response = False response = False
time.sleep(1.0) asyncio.sleep(1.0)
continue continue
else: else:
if events[0].content() == "[]": if events[0].content() == "[]":

View File

@@ -5,7 +5,7 @@ from nostr_sdk import Client, NostrSigner, Keys, Event, UnsignedEvent, Filter, \
HandleNotification, Timestamp, nip04_decrypt, UnwrappedGift, init_logger, LogLevel, Kind, KindEnum HandleNotification, Timestamp, nip04_decrypt, UnwrappedGift, init_logger, LogLevel, Kind, KindEnum
async def main(): async def test():
init_logger(LogLevel.DEBUG) init_logger(LogLevel.DEBUG)
# sk = SecretKey.from_bech32("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85") # sk = SecretKey.from_bech32("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")
@@ -62,7 +62,7 @@ async def main():
print(f"Error during content NIP59 decryption: {e}") print(f"Error during content NIP59 decryption: {e}")
async def handle_msg(self, relay_url, msg): async def handle_msg(self, relay_url, msg):
None var = None
#await client.handle_notifications(NotificationHandler()) #await client.handle_notifications(NotificationHandler())
@@ -70,7 +70,17 @@ async def main():
asyncio.create_task(client.handle_notifications(NotificationHandler())) asyncio.create_task(client.handle_notifications(NotificationHandler()))
while True: while True:
print("lol.") print("lol.")
time.sleep(5) await asyncio.sleep(5)
if __name__ == '__main__':
asyncio.run(main()) async def async_input():
while True:
print("lol")
await asyncio.sleep(5)
#async def main():
# await asyncio.gather(asyncio.to_thread(async_input), test())
if __name__ == "__main__":
asyncio.run(test())

View File

@@ -1,3 +1,4 @@
import asyncio
import time import time
import requests import requests
@@ -78,7 +79,7 @@ if __name__ == '__main__':
print(f"{data[1]['id']} ==> {data[1]['video_url']}") print(f"{data[1]['id']} ==> {data[1]['video_url']}")
break break
# sleep 5s # sleep 5s
time.sleep(5) asyncio.sleep(1.0)
response1 = get_clip(data[0]['id']) response1 = get_clip(data[0]['id'])
print(response1['video_url']) print(response1['video_url'])

View File

@@ -1,3 +1,4 @@
import asyncio
import json import json
import time import time
from pathlib import Path from pathlib import Path
@@ -13,7 +14,7 @@ from nostr_dvm.utils.definitions import EventDefinitions
# TODO HINT: Best use this path with a previously whitelisted privkey, as zapping events is not implemented in the lib/code # TODO HINT: Best use this path with a previously whitelisted privkey, as zapping events is not implemented in the lib/code
def nostr_client_test_translation(input, kind, lang, sats, satsmax): async def nostr_client_test_translation(input, kind, lang, sats, satsmax):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
if kind == "text": if kind == "text":
iTag = Tag.parse(["i", input, "text"]) iTag = Tag.parse(["i", input, "text"])
@@ -35,14 +36,14 @@ def nostr_client_test_translation(input, kind, lang, sats, satsmax):
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) await send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client_test_search_profile(input): async def nostr_client_test_search_profile(input):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
iTag = Tag.parse(["i", input, "text"]) iTag = Tag.parse(["i", input, "text"])
@@ -60,14 +61,14 @@ def nostr_client_test_search_profile(input):
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) await send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client_test_image(prompt): async def nostr_client_test_image(prompt):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
iTag = Tag.parse(["i", prompt, "text"]) iTag = Tag.parse(["i", prompt, "text"])
@@ -88,14 +89,14 @@ def nostr_client_test_image(prompt):
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) await send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client_test_censor_filter(users): async def nostr_client_test_censor_filter(users):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", "wss://relayable.org", relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", "wss://relayable.org",
@@ -115,14 +116,14 @@ def nostr_client_test_censor_filter(users):
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) await send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client_test_inactive_filter(user): async def nostr_client_test_inactive_filter(user):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz",
@@ -142,15 +143,15 @@ def nostr_client_test_inactive_filter(user):
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
ropts = RelayOptions().ping(False) ropts = RelayOptions().ping(False)
client.add_relay_with_opts("wss://nostr.band", ropts) await client.add_relay_with_opts("wss://nostr.band", ropts)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client_test_tts(prompt): async def nostr_client_test_tts(prompt):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
iTag = Tag.parse(["i", prompt, "text"]) iTag = Tag.parse(["i", prompt, "text"])
@@ -169,14 +170,14 @@ def nostr_client_test_tts(prompt):
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) await send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client_test_disovery(user, ptag): async def nostr_client_test_disovery(user, ptag):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz",
@@ -196,16 +197,16 @@ def nostr_client_test_disovery(user, ptag):
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
ropts = RelayOptions().ping(False) ropts = RelayOptions().ping(False)
client.add_relay_with_opts("wss://nostr.band", ropts) await client.add_relay_with_opts("wss://nostr.band", ropts)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(event, client=client, dvm_config=config) await send_event(event, client=client, dvm_config=config)
return event.as_json() return event.as_json()
def nostr_client_test_image_private(prompt, cashutoken): async def nostr_client_test_image_private(prompt, cashutoken):
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
receiver_keys = Keys.parse(check_and_set_private_key("replicate_sdxl")) receiver_keys = Keys.parse(check_and_set_private_key("replicate_sdxl"))
@@ -235,14 +236,14 @@ def nostr_client_test_image_private(prompt, cashutoken):
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)
client = Client(signer) client = Client(signer)
for relay in relay_list: for relay in relay_list:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
config = DVMConfig config = DVMConfig
send_event(nip90request, client=client, dvm_config=config) await send_event(nip90request, client=client, dvm_config=config)
return nip90request.as_json() return nip90request.as_json()
def nostr_client(): async def nostr_client():
keys = Keys.parse(check_and_set_private_key("test_client")) keys = Keys.parse(check_and_set_private_key("test_client"))
sk = keys.secret_key() sk = keys.secret_key()
pk = keys.public_key() pk = keys.public_key()
@@ -252,8 +253,8 @@ def nostr_client():
dvmconfig = DVMConfig() dvmconfig = DVMConfig()
for relay in dvmconfig.RELAY_LIST: for relay in dvmconfig.RELAY_LIST:
client.add_relay(relay) await client.add_relay(relay)
client.connect() await client.connect()
dm_zap_filter = Filter().pubkey(pk).kinds([EventDefinitions.KIND_DM, dm_zap_filter = Filter().pubkey(pk).kinds([EventDefinitions.KIND_DM,
EventDefinitions.KIND_ZAP]).since( EventDefinitions.KIND_ZAP]).since(
@@ -265,24 +266,24 @@ def nostr_client():
if kind not in kinds: if kind not in kinds:
kinds.append(kind) kinds.append(kind)
dvm_filter = (Filter().kinds(kinds).since(Timestamp.now())) dvm_filter = (Filter().kinds(kinds).since(Timestamp.now()))
client.subscribe([dm_zap_filter, dvm_filter], None) await client.subscribe([dm_zap_filter, dvm_filter], None)
# nostr_client_test_translation("This is the result of the DVM in spanish", "text", "es", 20, 20) # await nostr_client_test_translation("This is the result of the DVM in spanish", "text", "es", 20, 20)
# nostr_client_test_translation("note1p8cx2dz5ss5gnk7c59zjydcncx6a754c0hsyakjvnw8xwlm5hymsnc23rs", "event", "es", 20,20) # await nostr_client_test_translation("note1p8cx2dz5ss5gnk7c59zjydcncx6a754c0hsyakjvnw8xwlm5hymsnc23rs", "event", "es", 20,20)
# nostr_client_test_translation("44a0a8b395ade39d46b9d20038b3f0c8a11168e67c442e3ece95e4a1703e2beb", "event", "zh", 20, 20) # await nostr_client_test_translation("44a0a8b395ade39d46b9d20038b3f0c8a11168e67c442e3ece95e4a1703e2beb", "event", "zh", 20, 20)
# nostr_client_test_image("a beautiful purple ostrich watching the sunset") # await nostr_client_test_image("a beautiful purple ostrich watching the sunset")
# nostr_client_test_search_profile("dontbelieve") # await nostr_client_test_search_profile("dontbelieve")
wot = ["99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64"] wot = ["99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64"]
nostr_client_test_disovery("99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64", "a21592a70ef9a00695efb3f7e816e17742d251559aff154b16d063a408bcd74d") await nostr_client_test_disovery("99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64", "a21592a70ef9a00695efb3f7e816e17742d251559aff154b16d063a408bcd74d")
#nostr_client_test_censor_filter(wot) # await nostr_client_test_censor_filter(wot)
#nostr_client_test_inactive_filter("99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64") # await nostr_client_test_inactive_filter("99bb5591c9116600f845107d31f9b59e2f7c7e09a1ff802e84f1d43da557ca64")
# nostr_client_test_tts("Hello, this is a test. Mic check one, two.") # await nostr_client_test_tts("Hello, this is a test. Mic check one, two.")
# cashutoken = "cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6MSwiQyI6IjAyNWU3ODZhOGFkMmExYTg0N2YxMzNiNGRhM2VhMGIyYWRhZGFkOTRiYzA4M2E2NWJjYjFlOTgwYTE1NGIyMDA2NCIsInNlY3JldCI6InQ1WnphMTZKMGY4UElQZ2FKTEg4V3pPck5rUjhESWhGa291LzVzZFd4S0U9In0seyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6NCwiQyI6IjAyOTQxNmZmMTY2MzU5ZWY5ZDc3MDc2MGNjZmY0YzliNTMzMzVmZTA2ZGI5YjBiZDg2Njg5Y2ZiZTIzMjVhYWUwYiIsInNlY3JldCI6IlRPNHB5WE43WlZqaFRQbnBkQ1BldWhncm44UHdUdE5WRUNYWk9MTzZtQXM9In0seyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6MTYsIkMiOiIwMmRiZTA3ZjgwYmMzNzE0N2YyMDJkNTZiMGI3ZTIzZTdiNWNkYTBhNmI3Yjg3NDExZWYyOGRiZDg2NjAzNzBlMWIiLCJzZWNyZXQiOiJHYUNIdHhzeG9HM3J2WWNCc0N3V0YxbU1NVXczK0dDN1RKRnVwOHg1cURzPSJ9XSwibWludCI6Imh0dHBzOi8vbG5iaXRzLmJpdGNvaW5maXhlc3RoaXMub3JnL2Nhc2h1L2FwaS92MS9ScDlXZGdKZjlxck51a3M1eVQ2SG5rIn1dfQ==" # cashutoken = "cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6MSwiQyI6IjAyNWU3ODZhOGFkMmExYTg0N2YxMzNiNGRhM2VhMGIyYWRhZGFkOTRiYzA4M2E2NWJjYjFlOTgwYTE1NGIyMDA2NCIsInNlY3JldCI6InQ1WnphMTZKMGY4UElQZ2FKTEg4V3pPck5rUjhESWhGa291LzVzZFd4S0U9In0seyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6NCwiQyI6IjAyOTQxNmZmMTY2MzU5ZWY5ZDc3MDc2MGNjZmY0YzliNTMzMzVmZTA2ZGI5YjBiZDg2Njg5Y2ZiZTIzMjVhYWUwYiIsInNlY3JldCI6IlRPNHB5WE43WlZqaFRQbnBkQ1BldWhncm44UHdUdE5WRUNYWk9MTzZtQXM9In0seyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6MTYsIkMiOiIwMmRiZTA3ZjgwYmMzNzE0N2YyMDJkNTZiMGI3ZTIzZTdiNWNkYTBhNmI3Yjg3NDExZWYyOGRiZDg2NjAzNzBlMWIiLCJzZWNyZXQiOiJHYUNIdHhzeG9HM3J2WWNCc0N3V0YxbU1NVXczK0dDN1RKRnVwOHg1cURzPSJ9XSwibWludCI6Imh0dHBzOi8vbG5iaXRzLmJpdGNvaW5maXhlc3RoaXMub3JnL2Nhc2h1L2FwaS92MS9ScDlXZGdKZjlxck51a3M1eVQ2SG5rIn1dfQ=="
# nostr_client_test_image_private("a beautiful ostrich watching the sunset") # await nostr_client_test_image_private("a beautiful ostrich watching the sunset")
class NotificationHandler(HandleNotification): class NotificationHandler(HandleNotification):
def handle(self, relay_url, subscription_id, event: Event): async def handle(self, relay_url, subscription_id, event: Event):
print(f"Received new event from {relay_url}: {event.as_json()}") print(f"Received new event from {relay_url}: {event.as_json()}")
if event.kind().as_u64() == 7000: if event.kind().as_u64() == 7000:
print("[Nostr Client]: " + event.as_json()) print("[Nostr Client]: " + event.as_json())
@@ -301,9 +302,9 @@ def nostr_client():
def handle_msg(self, relay_url, msg): def handle_msg(self, relay_url, msg):
return return
client.handle_notifications(NotificationHandler()) await client.handle_notifications(NotificationHandler())
while True: while True:
time.sleep(5.0) await asyncio.sleep(5.0)
if __name__ == '__main__': if __name__ == '__main__':
@@ -315,5 +316,4 @@ if __name__ == '__main__':
else: else:
raise FileNotFoundError(f'.env file not found at {env_path} ') raise FileNotFoundError(f'.env file not found at {env_path} ')
nostr_dvm_thread = Thread(target=nostr_client()) asyncio.run(nostr_client())
nostr_dvm_thread.start()