diff --git a/examples/ollama_dvm/test_client.py b/examples/ollama_dvm/test_client.py index 9dea5cb..d591103 100644 --- a/examples/ollama_dvm/test_client.py +++ b/examples/ollama_dvm/test_client.py @@ -21,13 +21,12 @@ async def nostr_client_test_llm(prompt): "wss://nostr-pub.wellorder.net"]) alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task to generate TTSt"]) event = EventBuilder(EventDefinitions.KIND_NIP90_GENERATE_TEXT, str("Generate an Audio File."), - [iTag, relaysTag, alttag]).to_event(keys) + [iTag, relaysTag, alttag]).sign_with_keys(keys) relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", "wss://relayable.org", "wss://nostr-pub.wellorder.net"] - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) diff --git a/examples/tts_dvm/test_client.py b/examples/tts_dvm/test_client.py index 60df0ac..c62e001 100644 --- a/examples/tts_dvm/test_client.py +++ b/examples/tts_dvm/test_client.py @@ -25,14 +25,13 @@ async def nostr_client_test_tts(prompt): "wss://nostr-pub.wellorder.net"]) alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task to generate TTS"]) event = EventBuilder(EventDefinitions.KIND_NIP90_TEXT_TO_SPEECH, str("Generate an Audio File."), - [iTag, paramTag1, bidTag, relaysTag, alttag]).to_event(keys) + [iTag, paramTag1, bidTag, relaysTag, alttag]).sign_with_keys(keys) relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", "wss://relayable.org", "wss://nostr-pub.wellorder.net"] - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -45,8 +44,7 @@ async def nostr_client(): sk = keys.secret_key() pk = keys.public_key() print(f"Nostr Test Client public key: {pk.to_bech32()}, Hex: {pk.to_hex()} ") - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) dvmconfig = DVMConfig() for relay in dvmconfig.RELAY_LIST: diff --git a/examples/unleashed_dvm/test_client.py b/examples/unleashed_dvm/test_client.py index 6d96a49..3202d9c 100644 --- a/examples/unleashed_dvm/test_client.py +++ b/examples/unleashed_dvm/test_client.py @@ -24,14 +24,12 @@ async def nostr_client_test(prompt): "wss://nostr-pub.wellorder.net"]) alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task to generate TTS"]) event = EventBuilder(EventDefinitions.KIND_NIP90_GENERATE_TEXT, str("Answer to prompt"), - [iTag, relaysTag, alttag]).to_event(keys) + [iTag, relaysTag, alttag]).sign_with_keys(keys) relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", "wss://relayable.org", "wss://nostr-pub.wellorder.net"] - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=5))) - signer = NostrSigner.keys(keys) - client = Client.with_opts(signer,opts) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -44,8 +42,7 @@ async def nostr_client(): sk = keys.secret_key() pk = keys.public_key() print(f"Nostr Test Client public key: {pk.to_bech32()}, Hex: {pk.to_hex()} ") - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) dvmconfig = DVMConfig() for relay in dvmconfig.RELAY_LIST: diff --git a/nostr_dvm/bot.py b/nostr_dvm/bot.py index d9fe712..2e3c808 100644 --- a/nostr_dvm/bot.py +++ b/nostr_dvm/bot.py @@ -43,12 +43,8 @@ class Bot: self.keys = Keys.parse(dvm_config.PRIVATE_KEY) self.CHATBOT = False - wait_for_send = True - 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).gossip(True)) - signer = NostrSigner.keys(self.keys) - self.client = Client.with_opts(signer, opts) + opts = (Options().gossip(True)) + self.client = Client.with_opts(self.keys, opts) self.invoice_list = [] pk = self.keys.public_key() @@ -127,11 +123,11 @@ class Bot: if giftwrap: try: # Extract rumor - unwrapped_gift = UnwrappedGift.from_gift_wrap(self.keys, nostr_event) + + unwrapped_gift = await UnwrappedGift.from_gift_wrap(self.keys, nostr_event) sender = unwrapped_gift.sender().to_hex() rumor: UnsignedEvent = unwrapped_gift.rumor() - # client.send_sealed_msg(sender, f"Echo: {msg}", None) if rumor.created_at().as_secs() >= Timestamp.now().as_secs(): if rumor.kind().as_enum() == KindEnum.PRIVATE_DIRECT_MESSAGE(): print(f"Received new msg [sealed]: {decrypted_text}") @@ -198,13 +194,13 @@ class Bot: # add the encrypted params to the content nip90request = (EventBuilder(self.dvm_config.SUPPORTED_DVMS[index].KIND, encrypted_params, [p_tag, encrypted_tag]). - to_event(self.keys)) + sign_with_keys(self.keys)) else: tags.append(p_tag) nip90request = (EventBuilder(self.dvm_config.SUPPORTED_DVMS[index].KIND, "", tags). - to_event(self.keys)) + sign_with_keys(self.keys)) # remember in the job_list that we have made an event, if anybody asks for payment, # we know we actually sent the request @@ -317,7 +313,7 @@ class Bot: nip90request = (EventBuilder(Kind(kind), "", tags). - to_event(self.keys)) + sign_with_keys(self.keys)) entry = {"npub": user.npub, "event_id": nip90request.id().to_hex(), "dvm_key": self.DVM_KEY, "is_paid": False, @@ -338,7 +334,7 @@ class Bot: etag = "" ptag = "" content = nostr_event.content() - for tag in nostr_event.tags(): + for tag in nostr_event.tags().to_vec(): if tag.as_vec()[0] == "status": status = tag.as_vec()[1] if len(tag.as_vec()) > 2: @@ -362,7 +358,7 @@ class Bot: event_as_json['content'] = "" nostr_event = Event.from_json(json.dumps(event_as_json)) - for tag in nostr_event.tags(): + for tag in nostr_event.tags().to_vec(): if tag.as_vec()[0] == "status": status = tag.as_vec()[1] if len(tag.as_vec()) > 2: @@ -390,7 +386,7 @@ class Bot: "[" + self.NAME + "] Received reaction from " + nostr_event.author().to_hex() + " message to orignal sender " + user.name) elif status == "payment-required" or status == "partial": - for tag in nostr_event.tags(): + for tag in nostr_event.tags().to_vec(): if tag.as_vec()[0] == "amount": amount_msats = int(tag.as_vec()[1]) amount = int(amount_msats / 1000) @@ -469,7 +465,7 @@ class Bot: ptag = "" etag = "" is_encrypted = False - for tag in nostr_event.tags(): + for tag in nostr_event.tags().to_vec(): if tag.as_vec()[0] == "e": etag = tag.as_vec()[1] elif tag.as_vec()[0] == "p": @@ -522,7 +518,7 @@ class Bot: etag = "" if zapped_event is not None: - for tag in zapped_event.tags(): + for tag in zapped_event.tags().to_vec(): if tag.as_vec()[0] == "e": etag = tag.as_vec()[1] diff --git a/nostr_dvm/dvm.py b/nostr_dvm/dvm.py index 1158fdb..46a59bd 100644 --- a/nostr_dvm/dvm.py +++ b/nostr_dvm/dvm.py @@ -1,11 +1,10 @@ import asyncio import json import os -from datetime import timedelta from sys import platform from nostr_sdk import PublicKey, Keys, Client, Tag, Event, EventBuilder, Filter, HandleNotification, Timestamp, \ - LogLevel, Options, nip04_encrypt, NostrSigner, Kind, RelayLimits + LogLevel, Options, nip04_encrypt, Kind, RelayLimits from nostr_dvm.utils.admin_utils import admin_make_database_updates, AdminConfig from nostr_dvm.utils.backend_utils import get_amount_per_task, check_task_is_supported, get_task @@ -42,15 +41,11 @@ class DVM: self.dvm_config = dvm_config self.admin_config = admin_config self.keys = Keys.parse(dvm_config.PRIVATE_KEY) - wait_for_send = False - skip_disconnected_relays = True relaylimits = RelayLimits.disable() opts = ( - Options().wait_for_send(wait_for_send).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)) - .skip_disconnected_relays(skip_disconnected_relays).relay_limits(relaylimits)) + Options().relay_limits(relaylimits)) - signer = NostrSigner.keys(self.keys) - self.client = Client.with_opts(signer, opts) + self.client = Client.with_opts(self.keys, opts) self.job_list = [] self.jobs_on_hold_list = [] pk = self.keys.public_key() @@ -119,7 +114,7 @@ class DVM: cashu = "" p_tag_str = "" - for tag in nip90_event.tags(): + for tag in nip90_event.tags().to_vec(): if tag.as_vec()[0] == "cashu": cashu = tag.as_vec()[1] elif tag.as_vec()[0] == "p": @@ -281,7 +276,7 @@ class DVM: # dvm_config=self.dvm_config) else: bid = 0 - for tag in nip90_event.tags(): + for tag in nip90_event.tags().to_vec(): if tag.as_vec()[0] == 'bid': bid = int(tag.as_vec()[1]) @@ -321,7 +316,7 @@ class DVM: user = await get_or_add_user(db=self.dvm_config.DB, npub=sender, client=self.client, config=self.dvm_config) zapped_event = None - for tag in nut_zap_event.tags(): + for tag in nut_zap_event.tags().to_vec(): if tag.as_vec()[0] == 'e': zapped_event = await get_event_by_id(tag.as_vec()[1], client=self.client, config=self.dvm_config) @@ -332,7 +327,7 @@ class DVM: job_event = None p_tag_str = "" status = "" - for tag in zapped_event.tags(): + for tag in zapped_event.tags().to_vec(): if tag.as_vec()[0] == 'amount': amount = int(float(tag.as_vec()[1]) / 1000) elif tag.as_vec()[0] == 'e': @@ -414,7 +409,7 @@ class DVM: job_event = None p_tag_str = "" status = "" - for tag in zapped_event.tags(): + for tag in zapped_event.tags().to_vec(): if tag.as_vec()[0] == 'amount': amount = int(float(tag.as_vec()[1]) / 1000) elif tag.as_vec()[0] == 'e': @@ -499,7 +494,7 @@ class DVM: if not task_supported: return False - for tag in nevent.tags(): + for tag in nevent.tags().to_vec(): if tag.as_vec()[0] == 'i': if len(tag.as_vec()) < 3: print("Job Event missing/malformed i tag, skipping..") @@ -587,7 +582,7 @@ class DVM: reply_tags = [request_tag, e_tag, p_tag, alt_tag, status_tag] relay_tag = None - for tag in original_event.tags(): + for tag in original_event.tags().to_vec(): if tag.as_vec()[0] == "relays": relay_tag = tag if tag.as_vec()[0] == "client": @@ -597,13 +592,13 @@ class DVM: reply_tags.append(relay_tag) encrypted = False - for tag in original_event.tags(): + for tag in original_event.tags().to_vec(): if tag.as_vec()[0] == "encrypted": encrypted = True encrypted_tag = Tag.parse(["encrypted"]) reply_tags.append(encrypted_tag) - for tag in original_event.tags(): + for tag in original_event.tags().to_vec(): if tag.as_vec()[0] == "i": i_tag = tag if not encrypted: @@ -614,7 +609,7 @@ class DVM: content = nip04_encrypt(self.keys.secret_key(), PublicKey.from_hex(original_event.author().to_hex()), content) - reply_event = EventBuilder(Kind(original_event.kind().as_u16() + 1000), str(content), reply_tags).to_event( + reply_event = EventBuilder(Kind(original_event.kind().as_u16() + 1000), str(content), reply_tags).sign_with_keys( self.keys) # send_event(reply_event, client=self.client, dvm_config=self.dvm_config) @@ -641,7 +636,7 @@ class DVM: reply_tags = [e_tag, alt_tag, status_tag] relay_tag = None - for tag in original_event.tags(): + for tag in original_event.tags().to_vec(): if tag.as_vec()[0] == "relays": relay_tag = tag break @@ -651,7 +646,7 @@ class DVM: encryption_tags = [] encrypted = False - for tag in original_event.tags(): + for tag in original_event.tags().to_vec(): if tag.as_vec()[0] == "encrypted": encrypted = True encrypted_tag = Tag.parse(["encrypted"]) @@ -730,7 +725,7 @@ class DVM: content = reaction keys = Keys.parse(dvm_config.PRIVATE_KEY) - reaction_event = EventBuilder(EventDefinitions.KIND_FEEDBACK, str(content), reply_tags).to_event(keys) + reaction_event = EventBuilder(EventDefinitions.KIND_FEEDBACK, str(content), reply_tags).sign_with_keys(keys) # send_event(reaction_event, client=self.client, dvm_config=self.dvm_config) await send_event_outbox(reaction_event, client=self.client, dvm_config=self.dvm_config) diff --git a/nostr_dvm/subscription.py b/nostr_dvm/subscription.py index 720cc5d..04316c6 100644 --- a/nostr_dvm/subscription.py +++ b/nostr_dvm/subscription.py @@ -38,13 +38,7 @@ class Subscription: self.dvm_config.NIP89 = nip89config self.admin_config = admin_config self.keys = Keys.parse(dvm_config.PRIVATE_KEY) - - 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)) - signer = NostrSigner.keys(self.keys) - self.client = Client.with_opts(signer, opts) + self.client = Client(self.keys) pk = self.keys.public_key() @@ -100,7 +94,7 @@ class Subscription: if sender == self.keys.public_key().to_hex(): return - for tag in nostr_event.tags(): + for tag in nostr_event.tags().to_vec(): if tag.as_vec()[0] == "p": recipient = tag.as_vec()[1] elif tag.as_vec()[0] == "e": @@ -156,7 +150,7 @@ class Subscription: reply_tags = encryption_tags keys = Keys.parse(dvm_config.PRIVATE_KEY) - reaction_event = EventBuilder(EventDefinitions.KIND_FEEDBACK, str(content), reply_tags).to_event(keys) + reaction_event = EventBuilder(EventDefinitions.KIND_FEEDBACK, str(content), reply_tags).sign_with_keys(keys) await send_event(reaction_event, client=self.client, dvm_config=self.dvm_config) print("[" + self.dvm_config.NIP89.NAME + "]" + ": Sent Kind " + str( EventDefinitions.KIND_FEEDBACK.as_u16()) + " Reaction: " + "success" + " " + reaction_event.as_json()) @@ -214,11 +208,10 @@ class Subscription: tags = [pTag, PTag, eTag, validTag, tierTag, alttag] event = EventBuilder(EventDefinitions.KIND_NIP88_PAYMENT_RECIPE, - message, tags).to_event(self.keys) + message, tags).sign_with_keys(self.keys) dvmconfig = DVMConfig() - signer = NostrSigner.keys(self.keys) - client = Client(signer) + client = Client(self.keys) for relay in dvmconfig.RELAY_LIST: await client.add_relay(relay) await client.connect() @@ -248,10 +241,10 @@ class Subscription: subscriptionfilter = Filter().kind(EventDefinitions.KIND_NIP88_SUBSCRIBE_EVENT).author( PublicKey.parse(subscriber)).limit(1) - evts = await self.client.get_events_of([subscriptionfilter], relay_timeout) - if len(evts) > 0: - event7001id = evts[0].id().to_hex() - print(evts[0].as_json()) + evts = await self.client.fetch_events([subscriptionfilter], relay_timeout) + if len(evts.to_vec()) > 0: + event7001id = evts.to_vec()[0].id().to_hex() + print(evts.to_vec()[0].as_json()) tier_dtag = "" recipient = "" cadence = "" @@ -260,7 +253,7 @@ class Subscription: tier = "DVM" overall_amount = 0 subscription_event_id = "" - for tag in evts[0].tags(): + for tag in evts.to_vec()[0].tags().to_vec(): if tag.as_vec()[0] == "amount": overall_amount = int(tag.as_vec()[1]) @@ -275,7 +268,7 @@ class Subscription: jsonevent = json.loads(tag.as_vec()[1]) subscription_event = Event.from_json(jsonevent) - for tag in subscription_event.tags(): + for tag in subscription_event.tags().to_vec(): if tag.as_vec()[0] == "d": tier_dtag = tag.as_vec()[1] elif tag.as_vec()[0] == "zap": @@ -285,9 +278,9 @@ class Subscription: if tier_dtag == "" or len(zaps) == 0: tierfilter = Filter().id(EventId.parse(subscription_event_id)) - evts = await self.client.get_events_of([tierfilter], relay_timeout) - if len(evts) > 0: - for tag in evts[0].tags(): + evts = await self.client.fetch_events([tierfilter], relay_timeout) + if len(evts.to_vec()) > 0: + for tag in evts[0].tags().to_vec(): if tag.as_vec()[0] == "d": tier_dtag = tag.as_vec()[0] diff --git a/nostr_dvm/tasks/advanced_search.py b/nostr_dvm/tasks/advanced_search.py index c3a19f1..dcce596 100644 --- a/nostr_dvm/tasks/advanced_search.py +++ b/nostr_dvm/tasks/advanced_search.py @@ -54,7 +54,7 @@ class AdvancedSearch(DVMTaskInterface): max_results = 100 relay = "wss://relay.nostr.band" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": @@ -88,11 +88,9 @@ class AdvancedSearch(DVMTaskInterface): from nostr_sdk import Filter options = self.set_options(request_form) - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - cli = Client.with_opts(signer, opts) + cli = Client(keys) await cli.add_relay(options["relay"]) @@ -132,12 +130,12 @@ class AdvancedSearch(DVMTaskInterface): notes_filter = Filter().kind(Kind(1)).authors(userkeys).search(options["search"]).since( search_since).until(search_until).limit(options["max_results"]) - events = await cli.get_events_of([notes_filter], relay_timeout) + events = await cli.fetch_events([notes_filter], relay_timeout) result_list = [] - if len(events) > 0: + if len(events.to_vec()) > 0: - for event in events: + for event in events.to_vec(): e_tag = Tag.parse(["e", event.id().to_hex()]) result_list.append(e_tag.as_vec()) @@ -146,7 +144,7 @@ class AdvancedSearch(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type diff --git a/nostr_dvm/tasks/advanced_search_wine.py b/nostr_dvm/tasks/advanced_search_wine.py index ec58ac4..29ac7f5 100644 --- a/nostr_dvm/tasks/advanced_search_wine.py +++ b/nostr_dvm/tasks/advanced_search_wine.py @@ -53,7 +53,7 @@ class AdvancedSearchWine(DVMTaskInterface): search = "" max_results = 100 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": @@ -129,7 +129,7 @@ class AdvancedSearchWine(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type diff --git a/nostr_dvm/tasks/audiogeneration_suno_ai.py b/nostr_dvm/tasks/audiogeneration_suno_ai.py index 6ead904..a0af881 100644 --- a/nostr_dvm/tasks/audiogeneration_suno_ai.py +++ b/nostr_dvm/tasks/audiogeneration_suno_ai.py @@ -45,7 +45,7 @@ class AudioGenerationSonoAI(DVMTaskInterface): request_form = {"jobID": event.id().to_hex() + "_" + self.NAME.replace(" ", "")} prompt = "A popular heavy metal song about a purple Ostrich, Nostr, sung by a deep-voiced male singer, slowly and melodiously. The lyrics depict hope for a better future." - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/content_discovery_currently_latest_longform.py b/nostr_dvm/tasks/content_discovery_currently_latest_longform.py index 020509c..944584a 100644 --- a/nostr_dvm/tasks/content_discovery_currently_latest_longform.py +++ b/nostr_dvm/tasks/content_discovery_currently_latest_longform.py @@ -3,7 +3,7 @@ import os from datetime import timedelta from nostr_sdk import Timestamp, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind, \ + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind, \ RelayLimits from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv @@ -79,7 +79,7 @@ class DicoverContentLatestLongForm(DVMTaskInterface): search = "" max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -107,14 +107,12 @@ class DicoverContentLatestLongForm(DVMTaskInterface): options = self.set_options(request_form) - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) # print(self.db_name) - cli = ClientBuilder().database(database).signer(signer).opts(opts).build() + cli = ClientBuilder().database(database).signer(keys).build() await cli.connect() # Negentropy reconciliation @@ -150,7 +148,7 @@ class DicoverContentLatestLongForm(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -173,13 +171,11 @@ class DicoverContentLatestLongForm(DVMTaskInterface): async def sync_db(self): try: relaylimits = RelayLimits.disable() - opts = (Options().wait_for_send(False).send_timeout( - timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))).relay_limits(relaylimits) + opts = (Options().relay_limits(relaylimits)) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).opts(opts).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -196,8 +192,8 @@ class DicoverContentLatestLongForm(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/content_discovery_currently_latest_wiki.py b/nostr_dvm/tasks/content_discovery_currently_latest_wiki.py index 3fbb9ed..53f9a40 100644 --- a/nostr_dvm/tasks/content_discovery_currently_latest_wiki.py +++ b/nostr_dvm/tasks/content_discovery_currently_latest_wiki.py @@ -3,7 +3,7 @@ import os from datetime import timedelta from nostr_sdk import Timestamp, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind, \ + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind, \ RelayLimits from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv @@ -79,7 +79,7 @@ class DicoverContentLatestWiki(DVMTaskInterface): search = "" max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -107,14 +107,12 @@ class DicoverContentLatestWiki(DVMTaskInterface): options = self.set_options(request_form) - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) # print(self.db_name) - cli = ClientBuilder().database(database).signer(signer).opts(opts).build() + cli = ClientBuilder().database(database).signer(keys).build() await cli.connect() # Negentropy reconciliation @@ -150,7 +148,7 @@ class DicoverContentLatestWiki(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -173,13 +171,11 @@ class DicoverContentLatestWiki(DVMTaskInterface): async def sync_db(self): try: relaylimits = RelayLimits.disable() - opts = (Options().wait_for_send(False).send_timeout( - timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))).relay_limits(relaylimits) + opts = (Options().relay_limits(relaylimits)) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).opts(opts).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -195,8 +191,8 @@ class DicoverContentLatestWiki(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/content_discovery_currently_popular.py b/nostr_dvm/tasks/content_discovery_currently_popular.py index 5f13335..35a86f1 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular.py @@ -4,7 +4,7 @@ import os from datetime import timedelta from nostr_sdk import Timestamp, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv from nostr_dvm.utils import definitions @@ -80,7 +80,7 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): search = "" max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -145,7 +145,7 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -169,12 +169,10 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): async def sync_db(self): try: - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -192,8 +190,8 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/content_discovery_currently_popular_by_top_zaps.py b/nostr_dvm/tasks/content_discovery_currently_popular_by_top_zaps.py index ce3b9e5..683a63a 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular_by_top_zaps.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular_by_top_zaps.py @@ -2,7 +2,7 @@ import json from datetime import timedelta from nostr_sdk import Timestamp, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv from nostr_dvm.utils import definitions @@ -79,7 +79,7 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): # default values max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -107,19 +107,8 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): ns = SimpleNamespace() options = self.set_options(request_form) - - # opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) - # sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) - # keys = Keys.parse(sk.to_hex()) - # signer = NostrSigner.keys(keys) - database = NostrDatabase.lmdb(self.db_name) - # cli = ClientBuilder().database(database).signer(signer).opts(opts).build() - # await cli.connect() - - # Negentropy reconciliation - # Query events from database timestamp_hour_ago = Timestamp.now().as_secs() - self.db_since since = Timestamp.from_secs(timestamp_hour_ago) @@ -143,7 +132,7 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): if event_author == zap.author().to_hex(): continue # Skip self zaps.. invoice_amount = 0 - for tag in zap.tags(): + for tag in zap.tags().to_vec(): if tag.as_vec()[0] == 'bolt11': # print(tag.as_vec()[1]) @@ -166,7 +155,7 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): # elif tag.as_vec()[0] == 'description': # try: # event = Event.from_json(tag.as_vec()[1]) - # for tag in event.tags(): + # for tag in event.tags().to_vec(): # if tag.as_vec()[0] == "amount": # invoice_amount = tag.as_vec()[1] # overall_amount += invoice_amount @@ -198,7 +187,7 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -224,12 +213,10 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): async def sync_db(self): try: - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -247,8 +234,8 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/content_discovery_currently_popular_followers.py b/nostr_dvm/tasks/content_discovery_currently_popular_followers.py index 9b90f08..ae84170 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular_followers.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular_followers.py @@ -2,7 +2,7 @@ import json from datetime import timedelta from nostr_sdk import Timestamp, PublicKey, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Event, Kind, \ + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Event, Kind, \ RelayLimits from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv @@ -67,7 +67,7 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): user = event.author().to_hex() max_results = 100 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -92,14 +92,13 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): options = self.set_options(request_form) relaylimits = RelayLimits.disable() opts = ( - Options().wait_for_send(True).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)).relay_limits( + Options().relay_limits( relaylimits)) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().database(database).signer(signer).opts(opts).build() + cli = ClientBuilder().database(database).signer(keys).opts(opts).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -110,7 +109,7 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): user = PublicKey.parse(options["user"]) followers_filter = Filter().author(user).kinds([Kind(3)]) - followers = await cli.get_events_of([followers_filter], relay_timeout) + followers = await cli.fetch_events([followers_filter], relay_timeout) # print(followers) # Negentropy reconciliation @@ -120,17 +119,17 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): result_list = [] - if len(followers) > 0: + if len(followers.to_vec()) > 0: newest = 0 - best_entry = followers[0] - for entry in followers: + best_entry = followers.to_vec()[0] + for entry in followers.to_vec(): if entry.created_at().as_secs() > newest: newest = entry.created_at().as_secs() best_entry = entry # print(best_entry.as_json()) followings = [] - for tag in best_entry.tags(): + for tag in best_entry.tags().to_vec(): if tag.as_vec()[0] == "p": following = PublicKey.parse(tag.as_vec()[1]) followings.append(following) @@ -167,7 +166,7 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -190,12 +189,10 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): async def sync_db(self): try: - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -213,8 +210,8 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/content_discovery_currently_popular_gallery.py b/nostr_dvm/tasks/content_discovery_currently_popular_gallery.py index 93414eb..f2d9455 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular_gallery.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular_gallery.py @@ -4,7 +4,7 @@ import os from datetime import timedelta from nostr_sdk import Timestamp, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, EventId, Kind, \ + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, EventId, Kind, \ RelayLimits from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv @@ -84,7 +84,7 @@ class DicoverContentCurrentlyPopularGallery(DVMTaskInterface): search = "" max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -133,7 +133,7 @@ class DicoverContentCurrentlyPopularGallery(DVMTaskInterface): for ge_event in ge_events: id = None - for tag in ge_event.tags(): + for tag in ge_event.tags().to_vec(): if tag.as_vec()[0] == "e": id = EventId.from_hex(tag.as_vec()[1]) ids.append(id) @@ -146,13 +146,11 @@ class DicoverContentCurrentlyPopularGallery(DVMTaskInterface): continue relaylimits = RelayLimits.disable() - opts = (Options().wait_for_send(True).send_timeout( - timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)).relay_limits(relaylimits)) + opts = (Options().relay_limits(relaylimits)) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - cli = ClientBuilder().database(databasegallery).signer(signer).opts(opts).build() + cli = ClientBuilder().database(databasegallery).signer(keys).opts(opts).build() for relay in relays: await cli.add_relay(relay) @@ -166,15 +164,15 @@ class DicoverContentCurrentlyPopularGallery(DVMTaskInterface): definitions.EventDefinitions.KIND_DELETION, definitions.EventDefinitions.KIND_NOTE]).events(ids).since(since) - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filtreactions, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filtreactions, dbopts) filter2 = Filter().ids(ids) - events = await cli.get_events_of([filter2], relay_timeout) + events = await cli.fetch_events([filter2], relay_timeout) - print(len(events)) + print(len(events.to_vec())) - for event in events: + for event in events.to_vec(): if event.created_at().as_secs() > timestamp_since: filt1 = Filter().kinds([definitions.EventDefinitions.KIND_DELETION]).event(event.id()).limit(1) deletions = await databasegallery.query([filt1]) @@ -190,7 +188,7 @@ class DicoverContentCurrentlyPopularGallery(DVMTaskInterface): if len(reactions) >= self.min_reactions: found = False for ge_event in ge_events: - for tag in ge_event.tags(): + for tag in ge_event.tags().to_vec(): if tag.as_vec()[0] == "e": if event.id().to_hex() == tag.as_vec()[1]: ns.finallist[ge_event.id().to_hex()] = len(reactions) @@ -216,7 +214,7 @@ class DicoverContentCurrentlyPopularGallery(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -240,12 +238,10 @@ class DicoverContentCurrentlyPopularGallery(DVMTaskInterface): async def sync_db(self): try: - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -262,8 +258,8 @@ class DicoverContentCurrentlyPopularGallery(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/content_discovery_currently_popular_mostr.py b/nostr_dvm/tasks/content_discovery_currently_popular_mostr.py index c9765a9..70e56df 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular_mostr.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular_mostr.py @@ -80,7 +80,7 @@ class DicoverContentCurrentlyPopularMostr(DVMTaskInterface): search = "" max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -109,11 +109,8 @@ class DicoverContentCurrentlyPopularMostr(DVMTaskInterface): ns = SimpleNamespace() options = self.set_options(request_form) - opts = ( - Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) try: @@ -121,7 +118,7 @@ class DicoverContentCurrentlyPopularMostr(DVMTaskInterface): Timestamp.now().as_secs() - self.db_since))) except Exception as e: print(e) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() timestamp_since = Timestamp.now().as_secs() - self.db_since since = Timestamp.from_secs(timestamp_since) @@ -161,7 +158,7 @@ class DicoverContentCurrentlyPopularMostr(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -185,12 +182,10 @@ class DicoverContentCurrentlyPopularMostr(DVMTaskInterface): async def sync_db(self): try: - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -216,14 +211,11 @@ class DicoverContentCurrentlyPopularMostr(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - # dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - # await cli.reconcile(filter1, dbopts) - # await cli.reconcile(filter2, dbopts) - # await cli.reconcile(filter3, dbopts) + # RECONCOILE NOT POSSIBLE ON THESE RELAYS SO WE FETCH AB BUNCH (will be stored in db) try: - events = await cli.get_events_of([filter1, filter2, filter3], relay_timeout_long) + events = await cli.fetch_events([filter1, filter2, filter3], relay_timeout_long) except Exception as e: print(e) # Do not delete profiles diff --git a/nostr_dvm/tasks/content_discovery_currently_popular_nonfollowers.py b/nostr_dvm/tasks/content_discovery_currently_popular_nonfollowers.py index 27a83c4..8b1afac 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular_nonfollowers.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular_nonfollowers.py @@ -4,7 +4,7 @@ import os from datetime import timedelta from nostr_sdk import Timestamp, PublicKey, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind, \ + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind, \ RelayLimits from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv @@ -96,7 +96,7 @@ class DicoverContentCurrentlyPopularNonFollowers(DVMTaskInterface): # default values max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -124,7 +124,7 @@ class DicoverContentCurrentlyPopularNonFollowers(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -141,15 +141,13 @@ class DicoverContentCurrentlyPopularNonFollowers(DVMTaskInterface): options = self.set_options(request_form) relaylimits = RelayLimits.disable() opts = ( - Options().wait_for_send(True).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)).relay_limits( - relaylimits)) + Options().relay_limits(relaylimits)) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) if self.database is None: self.database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().database(self.database).signer(signer).opts(opts).build() + cli = ClientBuilder().database(self.database).signer(keys).opts(opts).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -159,18 +157,18 @@ class DicoverContentCurrentlyPopularNonFollowers(DVMTaskInterface): await cli.connect() user = PublicKey.parse(options["user"]) followers_filter = Filter().author(user).kinds([Kind(3)]) - followers = await cli.get_events_of([followers_filter], relay_timeout) - if len(followers) > 0: + followers = await cli.fetch_events([followers_filter], relay_timeout) + if len(followers.to_vec()) > 0: newest = 0 - best_entry = followers[0] - for entry in followers: + best_entry = followers.to_vec()[0] + for entry in followers.to_vec(): if entry.created_at().as_secs() > newest: newest = entry.created_at().as_secs() best_entry = entry # print(best_entry.as_json()) followings = [] - for tag in best_entry.tags(): + for tag in best_entry.tags().to_vec(): if tag.as_vec()[0] == "p": following = tag.as_vec()[1] followings.append(following) @@ -227,12 +225,10 @@ class DicoverContentCurrentlyPopularNonFollowers(DVMTaskInterface): async def sync_db(self): try: - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -250,8 +246,8 @@ class DicoverContentCurrentlyPopularNonFollowers(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/content_discovery_currently_popular_topic.py b/nostr_dvm/tasks/content_discovery_currently_popular_topic.py index 2f8bc84..fdf7f12 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular_topic.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular_topic.py @@ -4,7 +4,7 @@ import os from datetime import timedelta from nostr_sdk import Timestamp, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv from nostr_dvm.utils import definitions @@ -95,7 +95,7 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): max_results = 200 user = event.author().to_hex() - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -133,7 +133,7 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -202,12 +202,10 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): async def sync_db(self): try: - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -225,8 +223,8 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/content_discovery_latest_one_per_follower.py b/nostr_dvm/tasks/content_discovery_latest_one_per_follower.py index 0b537ce..a43400f 100644 --- a/nostr_dvm/tasks/content_discovery_latest_one_per_follower.py +++ b/nostr_dvm/tasks/content_discovery_latest_one_per_follower.py @@ -48,7 +48,7 @@ class Discoverlatestperfollower(DVMTaskInterface): since_days = 30 max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'param': param = tag.as_vec()[1] if param == "user": # check for param type @@ -71,15 +71,12 @@ class Discoverlatestperfollower(DVMTaskInterface): sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) relaylimits = RelayLimits.disable() - opts = ( - Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))).relay_limits( - relaylimits) + opts = (Options().relay_limits(relaylimits)) - cli = Client.with_opts(signer, opts) + cli = Client.with_opts(keys, opts) for relay in self.dvm_config.RELAY_LIST: await cli.add_relay(relay) # ropts = RelayOptions().ping(False) @@ -91,14 +88,14 @@ class Discoverlatestperfollower(DVMTaskInterface): step = 20 followers_filter = Filter().author(PublicKey.parse(options["user"])).kind(Kind(3)) - followers = await cli.get_events_of([followers_filter], relay_timeout) + followers = await cli.fetch_events([followers_filter], relay_timeout) - if len(followers) > 0: + if len(followers.to_vec()) > 0: result_list = [] newest = 0 - best_entry = followers[0] - for entry in followers: - print(len(best_entry.tags())) + best_entry = followers.to_vec()[0] + for entry in followers.to_vec(): + print(len(best_entry.tags().to_vec())) print(best_entry.created_at().as_secs()) if entry.created_at().as_secs() > newest: newest = entry.created_at().as_secs() @@ -107,7 +104,7 @@ class Discoverlatestperfollower(DVMTaskInterface): followings = [] ns.dic = {} tagcount = 0 - for tag in best_entry.tags(): + for tag in best_entry.tags().to_vec(): tagcount += 1 if tag.as_vec()[0] == "p": following = tag.as_vec()[1] @@ -126,10 +123,7 @@ class Discoverlatestperfollower(DVMTaskInterface): from nostr_sdk import Filter keys = Keys.parse(self.dvm_config.PRIVATE_KEY) - opts = Options().wait_for_send(True).send_timeout( - timedelta(seconds=10)).skip_disconnected_relays(True) - signer = NostrSigner.keys(keys) - cli = Client.with_opts(signer, opts) + cli = Client(keys) for relay in self.dvm_config.RELAY_LIST: await cli.add_relay(relay) await cli.connect() @@ -144,8 +138,8 @@ class Discoverlatestperfollower(DVMTaskInterface): except Exception as e: print(e) - event_from_authors = await cli.get_events_of(filters, relay_timeout_long) - for author in event_from_authors: + event_from_authors = await cli.fetch_events(filters, relay_timeout_long) + for author in event_from_authors.to_vec(): if instance.dic[author.author().to_hex()] is None: instance.dic[author.author().to_hex()] = author print(str(i) + "/" + str(len(users))) @@ -191,7 +185,7 @@ class Discoverlatestperfollower(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type diff --git a/nostr_dvm/tasks/content_discovery_update_db_only.py b/nostr_dvm/tasks/content_discovery_update_db_only.py index 21796e8..dc9c4f9 100644 --- a/nostr_dvm/tasks/content_discovery_update_db_only.py +++ b/nostr_dvm/tasks/content_discovery_update_db_only.py @@ -5,7 +5,7 @@ from datetime import timedelta from itertools import islice from nostr_sdk import Timestamp, PublicKey, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind, \ + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind, \ RelayLimits, RelayFilteringMode from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv @@ -87,7 +87,7 @@ class DicoverContentDBUpdateScheduler(DVMTaskInterface): # default values max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -107,7 +107,7 @@ class DicoverContentDBUpdateScheduler(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -129,17 +129,15 @@ class DicoverContentDBUpdateScheduler(DVMTaskInterface): async def sync_db(self): try: relaylimits = RelayLimits.disable() - opts = (Options().wait_for_send(False).send_timeout( - timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))).relay_limits(relaylimits) + opts = (Options().relay_limits(relaylimits)) if self.dvm_config.WOT_FILTERING: opts = opts.filtering_mode(RelayFilteringMode.WHITELIST) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) if self.database is None: self.database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(self.database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(self.database).opts(opts).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -183,8 +181,8 @@ class DicoverContentDBUpdateScheduler(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.IDENTIFIER + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() diff --git a/nostr_dvm/tasks/convert_media.py b/nostr_dvm/tasks/convert_media.py index 298a26a..d69c15a 100644 --- a/nostr_dvm/tasks/convert_media.py +++ b/nostr_dvm/tasks/convert_media.py @@ -49,7 +49,7 @@ class MediaConverter(DVMTaskInterface): end_time = 0 # TODO parse start/end parameters - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "url": diff --git a/nostr_dvm/tasks/discovery_bot_farms.py b/nostr_dvm/tasks/discovery_bot_farms.py index 4125a75..60a199b 100644 --- a/nostr_dvm/tasks/discovery_bot_farms.py +++ b/nostr_dvm/tasks/discovery_bot_farms.py @@ -3,7 +3,7 @@ import os from datetime import timedelta from nostr_sdk import Timestamp, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, Kind + ClientBuilder, Filter, SyncOptions, SyncDirection, Kind from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv from nostr_dvm.utils.admin_utils import AdminConfig @@ -53,7 +53,7 @@ class DiscoveryBotFarms(DVMTaskInterface): search = "airdrop;just your average nostr enjoyer" # ;@nostrich.house; max_results = 500 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": @@ -74,13 +74,11 @@ class DiscoveryBotFarms(DVMTaskInterface): from nostr_sdk import Filter options = self.set_options(request_form) - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb("db/nostr_profiles.db") - cli = ClientBuilder().database(database).signer(signer).opts(opts).build() + cli = ClientBuilder().database(database).signer(keys).build() await cli.add_relay("wss://relay.damus.io") # cli.add_relay("wss://atl.purplerelay.com") @@ -116,7 +114,7 @@ class DiscoveryBotFarms(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -136,12 +134,10 @@ class DiscoveryBotFarms(DVMTaskInterface): return 1 async def sync_db(self): - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb("db/nostr_profiles.db") - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() await cli.add_relay("wss://relay.damus.io") await cli.add_relay("wss://nostr21.com") @@ -151,8 +147,8 @@ class DiscoveryBotFarms(DVMTaskInterface): # filter = Filter().author(keys.public_key()) print("Syncing Profile Database.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) print("Done Syncing Profile Database.") diff --git a/nostr_dvm/tasks/discovery_censor_wot.py b/nostr_dvm/tasks/discovery_censor_wot.py index 3cdbd1a..2bd81c8 100644 --- a/nostr_dvm/tasks/discovery_censor_wot.py +++ b/nostr_dvm/tasks/discovery_censor_wot.py @@ -46,7 +46,7 @@ class DiscoverReports(DVMTaskInterface): since_days = 90 # users.append(event.author().to_hex()) - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': users.append(tag.as_vec()[1]) elif tag.as_vec()[0] == 'param': @@ -70,12 +70,10 @@ class DiscoverReports(DVMTaskInterface): ns = SimpleNamespace() relaylimits = RelayLimits.disable() opts = ( - Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)).relay_limits( - relaylimits)) + Options().relay_limits(relaylimits)) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - cli = Client.with_opts(signer, opts) + cli = Client.with_opts(keys, opts) # cli.add_relay("wss://relay.nostr.band") for relay in self.dvm_config.RELAY_LIST: await cli.add_relay(relay) @@ -94,19 +92,19 @@ class DiscoverReports(DVMTaskInterface): # if we don't add users, e.g. by a wot, we check all our followers. if len(pubkeys) == 0: followers_filter = Filter().author(PublicKey.parse(options["sender"])).kind(Kind(3)) - followers = await cli.get_events_of([followers_filter], relay_timeout) + followers = await cli.fetch_events([followers_filter], relay_timeout) - if len(followers) > 0: + if len(followers.to_vec()) > 0: result_list = [] newest = 0 - best_entry = followers[0] - for entry in followers: - print(len(best_entry.tags())) + best_entry = followers.to_vec()[0] + for entry in followers.to_vec(): + print(len(best_entry.tags().to_vec())) print(best_entry.created_at().as_secs()) if entry.created_at().as_secs() > newest: newest = entry.created_at().as_secs() best_entry = entry - for tag in best_entry.tags(): + for tag in best_entry.tags().to_vec(): if tag.as_vec()[0] == "p": following = PublicKey.parse(tag.as_vec()[1]) pubkeys.append(following) @@ -115,20 +113,20 @@ class DiscoverReports(DVMTaskInterface): options["since_days"]) # TODO make this an option, 180 days for now since = Timestamp.from_secs(ago) kind1984_filter = Filter().authors(pubkeys).kind(Kind(1984)).since(since) - reports = await cli.get_events_of([kind1984_filter], relay_timeout) + reports = await cli.fetch_events([kind1984_filter], relay_timeout) bad_actors = [] ns.dic = {} reasons = ["spam", "illegal", "impersonation"] # init - for report in reports: - for tag in report.tags(): + for report in reports.to_vec(): + for tag in report.tags().to_vec(): if tag.as_vec()[0] == "p": ns.dic[tag.as_vec()[1]] = 0 - for report in reports: + for report in reports.to_vec(): # print(report.as_json()) - for tag in report.tags(): + for tag in report.tags().to_vec(): if tag.as_vec()[0] == "p": if len(tag.as_vec()) > 2 and tag.as_vec()[2] in reasons or len(tag.as_vec()) <= 2: ns.dic[tag.as_vec()[1]] += 1 @@ -153,7 +151,7 @@ class DiscoverReports(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type diff --git a/nostr_dvm/tasks/discovery_inactive_follows.py b/nostr_dvm/tasks/discovery_inactive_follows.py index 5983375..35e0fc1 100644 --- a/nostr_dvm/tasks/discovery_inactive_follows.py +++ b/nostr_dvm/tasks/discovery_inactive_follows.py @@ -48,7 +48,7 @@ class DiscoverInactiveFollows(DVMTaskInterface): user = event.author().to_hex() since_days = 90 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'param': param = tag.as_vec()[1] if param == "user": # check for param type @@ -70,20 +70,15 @@ class DiscoverInactiveFollows(DVMTaskInterface): sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - # relaylimits = RelayLimits().event_max_num_tags(max_num_tags=10000) # relaylimits.event_max_size(None) relaylimits = RelayLimits.disable() - opts = ( - Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))).relay_limits( - relaylimits) + opts = (Options().relay_limits(relaylimits)) - cli = Client.with_opts(signer, opts) + cli = Client.with_opts(keys, opts) for relay in self.dvm_config.RELAY_LIST: await cli.add_relay(relay) - ropts = RelayOptions().ping(False) await cli.add_relay("wss://nostr.band") await cli.connect() @@ -92,27 +87,27 @@ class DiscoverInactiveFollows(DVMTaskInterface): step = 20 followers_filter = Filter().author(PublicKey.parse(options["user"])).kind(Kind(3)) - followers = await cli.get_events_of([followers_filter], relay_timeout) + followers = await cli.fetch_events([followers_filter], relay_timeout) - if len(followers) > 0: + if len(followers.to_vec()) > 0: result_list = [] newest = 0 - best_entry = followers[0] - for entry in followers: - print(len(best_entry.tags())) + best_entry = followers.to_vec()[0] + for entry in followers.to_vec(): + print(len(best_entry.tags().to_vec())) print(best_entry.created_at().as_secs()) if entry.created_at().as_secs() > newest: newest = entry.created_at().as_secs() best_entry = entry print(best_entry.as_json()) - print(len(best_entry.tags())) + print(len(best_entry.tags().to_vec())) print(best_entry.created_at().as_secs()) print(Timestamp.now().as_secs()) followings = [] ns.dic = {} tagcount = 0 - for tag in best_entry.tags(): + for tag in best_entry.tags().to_vec(): tagcount += 1 if tag.as_vec()[0] == "p": following = tag.as_vec()[1] @@ -128,10 +123,7 @@ class DiscoverInactiveFollows(DVMTaskInterface): from nostr_sdk import Filter keys = Keys.parse(self.dvm_config.PRIVATE_KEY) - opts = Options().wait_for_send(True).send_timeout( - timedelta(seconds=5)).skip_disconnected_relays(True) - signer = NostrSigner.keys(keys) - cli = Client.with_opts(signer, opts) + cli = Client(keys) for relay in self.dvm_config.RELAY_LIST: await cli.add_relay(relay) await cli.connect() @@ -140,8 +132,8 @@ class DiscoverInactiveFollows(DVMTaskInterface): for i in range(i, i + st): filter1 = Filter().author(PublicKey.from_hex(users[i])).since(notactivesince).limit(1) filters.append(filter1) - event_from_authors = await cli.get_events_of(filters, relay_timeout_long) - for author in event_from_authors: + event_from_authors = await cli.fetch_events(filters, relay_timeout_long) + for author in event_from_authors.to_vec(): instance.dic[author.author().to_hex()] = "True" print(str(i) + "/" + str(len(users))) await cli.shutdown() @@ -179,7 +171,7 @@ class DiscoverInactiveFollows(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type diff --git a/nostr_dvm/tasks/discovery_nonfollowers.py b/nostr_dvm/tasks/discovery_nonfollowers.py index 7f7b7e6..34e42b3 100644 --- a/nostr_dvm/tasks/discovery_nonfollowers.py +++ b/nostr_dvm/tasks/discovery_nonfollowers.py @@ -46,7 +46,7 @@ class DiscoverNonFollowers(DVMTaskInterface): # default values user = event.author().to_hex() - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'param': param = tag.as_vec()[1] if param == "user": # check for param type @@ -64,17 +64,15 @@ class DiscoverNonFollowers(DVMTaskInterface): ns = SimpleNamespace() relaylimits = RelayLimits.disable() opts = ( - Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)).relay_limits( + Options().relay_limits( relaylimits)) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - cli = Client.with_opts(signer, opts) + cli = Client.with_opts(keys, opts) # cli.add_relay("wss://relay.nostr.band") for relay in self.dvm_config.RELAY_LIST: await cli.add_relay(relay) # add nostr band, too. - ropts = RelayOptions().ping(False) await cli.add_relay("wss://nostr.band") await cli.connect() @@ -83,13 +81,13 @@ class DiscoverNonFollowers(DVMTaskInterface): step = 20 followers_filter = Filter().author(PublicKey.from_hex(options["user"])).kind(Kind(3)) - followers = await cli.get_events_of([followers_filter], relay_timeout) + followers = await cli.fetch_events([followers_filter], relay_timeout) - if len(followers) > 0: + if len(followers.to_vec()) > 0: result_list = [] newest = 0 - best_entry = followers[0] - for entry in followers: + best_entry = followers.to_vec()[0] + for entry in followers.to_vec(): if entry.created_at().as_secs() > newest: newest = entry.created_at().as_secs() best_entry = entry @@ -97,7 +95,7 @@ class DiscoverNonFollowers(DVMTaskInterface): print(best_entry.as_json()) followings = [] ns.dic = {} - for tag in best_entry.tags(): + for tag in best_entry.tags().to_vec(): if tag.as_vec()[0] == "p": following = tag.as_vec()[1] followings.append(following) @@ -106,12 +104,8 @@ class DiscoverNonFollowers(DVMTaskInterface): async def scanList(users, instance, i, st): from nostr_sdk import Filter - keys = Keys.parse(self.dvm_config.PRIVATE_KEY) - opts = Options().wait_for_send(True).send_timeout( - timedelta(seconds=5)).skip_disconnected_relays(True) - signer = NostrSigner.keys(keys) - cli = Client.with_opts(signer, opts) + cli = Client(keys) for relay in self.dvm_config.RELAY_LIST: await cli.add_relay(relay) await cli.connect() @@ -120,19 +114,19 @@ class DiscoverNonFollowers(DVMTaskInterface): filters = [] filter1 = Filter().author(PublicKey.from_hex(users[i])).kind(Kind(3)) filters.append(filter1) - followers = await cli.get_events_of(filters, relay_timeout) + followers = await cli.fetch_events(filters, relay_timeout) - if len(followers) > 0: + if len(followers.to_vec()) > 0: result_list = [] newest = 0 - best_entry = followers[0] - for entry in followers: + best_entry = followers.to_vec()[0] + for entry in followers.to_vec(): if entry.created_at().as_secs() > newest: newest = entry.created_at().as_secs() best_entry = entry foundfollower = False - for tag in best_entry.tags(): + for tag in best_entry.tags().to_vec(): if tag.as_vec()[0] == "p": if len(tag.as_vec()) > 1: if tag.as_vec()[1] == options["user"]: @@ -180,7 +174,7 @@ class DiscoverNonFollowers(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type diff --git a/nostr_dvm/tasks/discovery_trending_notes_gleasonator.py b/nostr_dvm/tasks/discovery_trending_notes_gleasonator.py index 3fc22a6..75cf909 100644 --- a/nostr_dvm/tasks/discovery_trending_notes_gleasonator.py +++ b/nostr_dvm/tasks/discovery_trending_notes_gleasonator.py @@ -52,7 +52,7 @@ class TrendingNotesGleasonator(DVMTaskInterface): request_form = {"jobID": event.id().to_hex()} max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -70,11 +70,9 @@ class TrendingNotesGleasonator(DVMTaskInterface): async def process(self, request_form): options = self.set_options(request_form) - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - cli = Client.with_opts(signer, opts) + cli = Client(keys) await cli.add_relay(options["relay"]) await cli.connect() @@ -84,13 +82,13 @@ class TrendingNotesGleasonator(DVMTaskInterface): notes_filter = Filter().authors(authors).kind(Kind(1985)).custom_tag(SingleLetterTag.lowercase(Alphabet.L), ltags) - events = await cli.get_events_of([notes_filter], relay_timeout_long) + events = await cli.fetch_events([notes_filter], relay_timeout_long) result_list = [] - if len(events) > 0: - event = events[0] + if len(events.to_vec()) > 0: + event = events.to_vec()[0] print(event) - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "e": e_tag = Tag.parse(["e", tag.as_vec()[1], tag.as_vec()[2]]) result_list.append(e_tag.as_vec()) @@ -105,7 +103,7 @@ class TrendingNotesGleasonator(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type diff --git a/nostr_dvm/tasks/discovery_trending_notes_nostrband.py b/nostr_dvm/tasks/discovery_trending_notes_nostrband.py index b530d89..edc91fc 100644 --- a/nostr_dvm/tasks/discovery_trending_notes_nostrband.py +++ b/nostr_dvm/tasks/discovery_trending_notes_nostrband.py @@ -52,7 +52,7 @@ class TrendingNotesNostrBand(DVMTaskInterface): request_form = {"jobID": event.id().to_hex()} max_results = 200 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -95,7 +95,7 @@ class TrendingNotesNostrBand(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type diff --git a/nostr_dvm/tasks/generic_dvm.py b/nostr_dvm/tasks/generic_dvm.py index 047b509..f26e989 100644 --- a/nostr_dvm/tasks/generic_dvm.py +++ b/nostr_dvm/tasks/generic_dvm.py @@ -38,7 +38,7 @@ class GenericDVM(DVMTaskInterface): print(self.dvm_config.PRIVATE_KEY) prompt = "" user = event.author().to_hex() - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/imagegeneration_openai_dalle.py b/nostr_dvm/tasks/imagegeneration_openai_dalle.py index 1acf3b0..bfc6773 100644 --- a/nostr_dvm/tasks/imagegeneration_openai_dalle.py +++ b/nostr_dvm/tasks/imagegeneration_openai_dalle.py @@ -59,7 +59,7 @@ class ImageGenerationDALLE(DVMTaskInterface): model = "dall-e-3" quality = "standard" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/imagegeneration_replicate.py b/nostr_dvm/tasks/imagegeneration_replicate.py new file mode 100644 index 0000000..4a8746d --- /dev/null +++ b/nostr_dvm/tasks/imagegeneration_replicate.py @@ -0,0 +1,171 @@ +import json +import os +from io import BytesIO + +import requests +from PIL import Image +from nostr_sdk import Kind + +from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv +from nostr_dvm.utils.admin_utils import AdminConfig +from nostr_dvm.utils.definitions import EventDefinitions +from nostr_dvm.utils.dvmconfig import DVMConfig, build_default_config +from nostr_dvm.utils.nip88_utils import NIP88Config +from nostr_dvm.utils.nip89_utils import NIP89Config, check_and_set_d_tag +from nostr_dvm.utils.output_utils import upload_media_to_hoster +from nostr_dvm.utils.zap_utils import get_price_per_sat + +""" +This File contains a Module to generate an Image on replicate and receive results back. + +Accepted Inputs: Prompt (text) +Outputs: An url to an Image +Params: +""" + + +class ImageGenerationReplicate(DVMTaskInterface): + KIND: Kind = EventDefinitions.KIND_NIP90_GENERATE_IMAGE + TASK: str = "text-to-image" + FIX_COST: float = 120 + dependencies = [("nostr-dvm", "nostr-dvm"), + ("replicate", "replicate")] + + def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None, + admin_config: AdminConfig = None, + options=None, task=None): + super().__init__(name, dvm_config, nip89config, nip88config, admin_config, options, task) + if options is not None: + self.model = options["model"] + else: + self.model = None + + async def init_dvm(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None, + admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) + + + async def is_input_supported(self, tags, client=None, dvm_config=None): + for tag in tags: + if tag.as_vec()[0] == 'i': + input_value = tag.as_vec()[1] + input_type = tag.as_vec()[2] + if input_type != "text": + return False + + elif tag.as_vec()[0] == 'output': + output = tag.as_vec()[1] + if (output == "" or + not (output == "image/png" or "image/jpg" + or output == "image/png;format=url" or output == "image/jpg;format=url")): + print("Output format not supported, skipping..") + return False + + return True + + async def create_request_from_nostr_event(self, event, client=None, dvm_config=None): + request_form = {"jobID": event.id().to_hex() + "_" + self.NAME.replace(" ", "")} + prompt = "" + width = "1" + height = "1" + if self.model is None: + self.model = "stability-ai/stable-diffusion-3", + + for tag in event.tags().to_vec(): + if tag.as_vec()[0] == 'i': + input_type = tag.as_vec()[2] + if input_type == "text": + prompt = tag.as_vec()[1] + + elif tag.as_vec()[0] == 'param': + print("Param: " + tag.as_vec()[1] + ": " + tag.as_vec()[2]) + if tag.as_vec()[1] == "size": + if len(tag.as_vec()) > 3: + width = (tag.as_vec()[2]) + height = (tag.as_vec()[3]) + elif len(tag.as_vec()) == 3: + split = tag.as_vec()[2].split(":") + if len(split) > 1: + width = split[0] + height = split[1] + elif tag.as_vec()[1] == "model": + model = tag.as_vec()[2] + elif tag.as_vec()[1] == "quality": + quality = tag.as_vec()[2] + + options = { + "prompt": prompt, + "model": self.model, + "aspect_ratio": width + ":" + height, + "number": 1 + } + request_form['options'] = json.dumps(options) + + return request_form + + async def process(self, request_form): + try: + options = self.set_options(request_form) + + import replicate + #width = int(options["size"].split("x")[0]) + #height = int(options["size"].split("x")[1]) + output = replicate.run( + options["model"], + input={"prompt": options["prompt"], + "cfg": 3.5, + "steps": 28, + "prompt_upsampling": True, + "aspect_ratio": options["aspect_ratio"], + "output_format": "jpg", + "output_quality": 90, + "negative_prompt": "", + "prompt_strength": 0.85, + "safety_tolerance": 5 + } + ) + print(output[0]) + response = requests.get(output[0]) + image = Image.open(BytesIO(response.content)).convert("RGB") + image.save("./outputs/image.jpg") + result = await upload_media_to_hoster("./outputs/image.jpg") + return result + + except Exception as e: + print("Error in Module") + raise Exception(e) + + +# We build an example here that we can call by either calling this file directly from the main directory, +# or by adding it to our playground. You can call the example and adjust it to your needs or redefine it in the +# playground or elsewhere +def build_example(name, identifier, admin_config): + dvm_config = build_default_config(identifier) + admin_config.LUD16 = dvm_config.LN_ADDRESS + profit_in_sats = 10 + dvm_config.FIX_COST = int(((4.0 / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + + nip89info = { + "name": name, + "image": "https://image.nostr.build/c33ca6fc4cc038ca4adb46fdfdfda34951656f87ee364ef59095bae1495ce669.jpg", + "about": "I use Replicate to run StableDiffusion 3", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "ratio": { + "required": False, + "values": ["1:1" , "3:2", "4:5"] + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + return ImageGenerationReplicate(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + + +if __name__ == '__main__': + process_venv(ImageGenerationReplicate) diff --git a/nostr_dvm/tasks/imagegeneration_replicate_fluxpro.py b/nostr_dvm/tasks/imagegeneration_replicate_fluxpro.py new file mode 100644 index 0000000..96d817a --- /dev/null +++ b/nostr_dvm/tasks/imagegeneration_replicate_fluxpro.py @@ -0,0 +1,166 @@ +import json +import os +from io import BytesIO + +import requests +from PIL import Image +from nostr_sdk import Kind + +from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv +from nostr_dvm.utils.admin_utils import AdminConfig +from nostr_dvm.utils.definitions import EventDefinitions +from nostr_dvm.utils.dvmconfig import DVMConfig, build_default_config +from nostr_dvm.utils.nip88_utils import NIP88Config +from nostr_dvm.utils.nip89_utils import NIP89Config, check_and_set_d_tag +from nostr_dvm.utils.output_utils import upload_media_to_hoster +from nostr_dvm.utils.zap_utils import get_price_per_sat + +""" +This File contains a Module to generate an Image on replicate and receive results back. + +Accepted Inputs: Prompt (text) +Outputs: An url to an Image +Params: +""" + + +class ImageGenerationReplicateFluxPro(DVMTaskInterface): + KIND: Kind = EventDefinitions.KIND_NIP90_GENERATE_IMAGE + TASK: str = "text-to-image" + FIX_COST: float = 120 + dependencies = [("nostr-dvm", "nostr-dvm"), + ("replicate", "replicate")] + + def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None, + admin_config: AdminConfig = None, + options=None, task=None): + super().__init__(name, dvm_config, nip89config, nip88config, admin_config, options, task) + if options is not None: + self.model = options["model"] + else: + self.model = None + + async def init_dvm(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None, + admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) + + + async def is_input_supported(self, tags, client=None, dvm_config=None): + for tag in tags: + if tag.as_vec()[0] == 'i': + input_value = tag.as_vec()[1] + input_type = tag.as_vec()[2] + if input_type != "text": + return False + + elif tag.as_vec()[0] == 'output': + output = tag.as_vec()[1] + if (output == "" or + not (output == "image/png" or "image/jpg" + or output == "image/png;format=url" or output == "image/jpg;format=url")): + print("Output format not supported, skipping..") + return False + + return True + + async def create_request_from_nostr_event(self, event, client=None, dvm_config=None): + request_form = {"jobID": event.id().to_hex() + "_" + self.NAME.replace(" ", "")} + prompt = "" + width = "1024" + height = "1024" + + for tag in event.tags().to_vec(): + if tag.as_vec()[0] == 'i': + input_type = tag.as_vec()[2] + if input_type == "text": + prompt = tag.as_vec()[1] + + elif tag.as_vec()[0] == 'param': + print("Param: " + tag.as_vec()[1] + ": " + tag.as_vec()[2]) + if tag.as_vec()[1] == "size": + if len(tag.as_vec()) > 3: + width = (tag.as_vec()[2]) + height = (tag.as_vec()[3]) + elif len(tag.as_vec()) == 3: + split = tag.as_vec()[2].split(":") + if len(split) > 1: + width = split[0] + height = split[1] + elif tag.as_vec()[1] == "model": + model = tag.as_vec()[2] + elif tag.as_vec()[1] == "quality": + quality = tag.as_vec()[2] + + options = { + "prompt": prompt, + "size": width + "x" + height, + "number": 1 + } + request_form['options'] = json.dumps(options) + + return request_form + + async def process(self, request_form): + try: + options = self.set_options(request_form) + + import replicate + #width = int(options["size"].split("x")[0]) + #height = int(options["size"].split("x")[1]) + output = replicate.run( + "black-forest-labs/flux-1.1-pro", + input={"prompt": options["prompt"], + "aspect_ratio": "5:4", + "output_format": "jpg", + "output_quality": 80, + "safety_tolerance": 2, + "prompt_upsampling": True + } + ) + print(output) + response = requests.get(output) + image = Image.open(BytesIO(response.content)).convert("RGB") + image.save("./outputs/image.jpg") + result = await upload_media_to_hoster("./outputs/image.jpg") + return result + + except Exception as e: + print("Error in Module") + raise Exception(e) + +def write_text(data: str, path: str): + with open(path, 'w') as file: + file.write(data) +# We build an example here that we can call by either calling this file directly from the main directory, +# or by adding it to our playground. You can call the example and adjust it to your needs or redefine it in the +# playground or elsewhere +def build_example(name, identifier, admin_config): + dvm_config = build_default_config(identifier) + admin_config.LUD16 = dvm_config.LN_ADDRESS + profit_in_sats = 10 + dvm_config.FIX_COST = int(((4.0 / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + + nip89info = { + "name": name, + "image": "https://image.nostr.build/c33ca6fc4cc038ca4adb46fdfdfda34951656f87ee364ef59095bae1495ce669.jpg", + "about": "I use Replicate to run FluxPro", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "ratio": { + "required": False, + "values": ["1:1" , "3:2", "4:5"] + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + return ImageGenerationReplicateFluxPro(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + + +if __name__ == '__main__': + process_venv(ImageGenerationReplicateFluxPro) diff --git a/nostr_dvm/tasks/imagegeneration_replicate_recraft.py b/nostr_dvm/tasks/imagegeneration_replicate_recraft.py new file mode 100644 index 0000000..dbb285c --- /dev/null +++ b/nostr_dvm/tasks/imagegeneration_replicate_recraft.py @@ -0,0 +1,165 @@ +import json +import os +from io import BytesIO + +import requests +from PIL import Image +from nostr_sdk import Kind + +from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv +from nostr_dvm.utils.admin_utils import AdminConfig +from nostr_dvm.utils.definitions import EventDefinitions +from nostr_dvm.utils.dvmconfig import DVMConfig, build_default_config +from nostr_dvm.utils.nip88_utils import NIP88Config +from nostr_dvm.utils.nip89_utils import NIP89Config, check_and_set_d_tag +from nostr_dvm.utils.output_utils import upload_media_to_hoster +from nostr_dvm.utils.zap_utils import get_price_per_sat + +""" +This File contains a Module to generate an Image on replicate and receive results back. + +Accepted Inputs: Prompt (text) +Outputs: An url to an Image +Params: +""" + + +class ImageGenerationReplicateRecraft(DVMTaskInterface): + KIND: Kind = EventDefinitions.KIND_NIP90_GENERATE_IMAGE + TASK: str = "text-to-image" + FIX_COST: float = 120 + dependencies = [("nostr-dvm", "nostr-dvm"), + ("replicate", "replicate")] + + def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None, + admin_config: AdminConfig = None, + options=None, task=None): + super().__init__(name, dvm_config, nip89config, nip88config, admin_config, options, task) + if options is not None: + self.model = options["model"] + else: + self.model = None + + async def init_dvm(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None, + admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) + + + async def is_input_supported(self, tags, client=None, dvm_config=None): + for tag in tags: + if tag.as_vec()[0] == 'i': + input_value = tag.as_vec()[1] + input_type = tag.as_vec()[2] + if input_type != "text": + return False + + elif tag.as_vec()[0] == 'output': + output = tag.as_vec()[1] + if (output == "" or + not (output == "image/png" or "image/jpg" + or output == "image/png;format=url" or output == "image/jpg;format=url")): + print("Output format not supported, skipping..") + return False + + return True + + async def create_request_from_nostr_event(self, event, client=None, dvm_config=None): + request_form = {"jobID": event.id().to_hex() + "_" + self.NAME.replace(" ", "")} + prompt = "" + width = "1024" + height = "1024" + if self.model is None: + self.model = "stability-ai/stable-diffusion-3", + + for tag in event.tags().to_vec(): + if tag.as_vec()[0] == 'i': + input_type = tag.as_vec()[2] + if input_type == "text": + prompt = tag.as_vec()[1] + + elif tag.as_vec()[0] == 'param': + print("Param: " + tag.as_vec()[1] + ": " + tag.as_vec()[2]) + if tag.as_vec()[1] == "size": + if len(tag.as_vec()) > 3: + width = (tag.as_vec()[2]) + height = (tag.as_vec()[3]) + elif len(tag.as_vec()) == 3: + split = tag.as_vec()[2].split(":") + if len(split) > 1: + width = split[0] + height = split[1] + elif tag.as_vec()[1] == "model": + model = tag.as_vec()[2] + elif tag.as_vec()[1] == "quality": + quality = tag.as_vec()[2] + + options = { + "prompt": prompt, + "size": width + "x" + height, + "number": 1 + } + request_form['options'] = json.dumps(options) + + return request_form + + async def process(self, request_form): + try: + options = self.set_options(request_form) + + import replicate + #width = int(options["size"].split("x")[0]) + #height = int(options["size"].split("x")[1]) + output = replicate.run( + "recraft-ai/recraft-v3", + input={"prompt": options["prompt"], + "size": options["size"], + "style": "any", + } + ) + print(output) + response = requests.get(output) + image = Image.open(BytesIO(response.content)).convert("RGB") + image.save("./outputs/image.jpg") + result = await upload_media_to_hoster("./outputs/image.jpg") + return result + + except Exception as e: + print("Error in Module") + raise Exception(e) + +def write_text(data: str, path: str): + with open(path, 'w') as file: + file.write(data) +# We build an example here that we can call by either calling this file directly from the main directory, +# or by adding it to our playground. You can call the example and adjust it to your needs or redefine it in the +# playground or elsewhere +def build_example(name, identifier, admin_config): + dvm_config = build_default_config(identifier) + admin_config.LUD16 = dvm_config.LN_ADDRESS + profit_in_sats = 10 + dvm_config.FIX_COST = int(((4.0 / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + + nip89info = { + "name": name, + "image": "https://image.nostr.build/c33ca6fc4cc038ca4adb46fdfdfda34951656f87ee364ef59095bae1495ce669.jpg", + "about": "I use Replicate to run Recraft", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "ratio": { + "required": False, + "values": ["1:1" , "3:2", "4:5"] + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + return ImageGenerationReplicateRecraft(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + + +if __name__ == '__main__': + process_venv(ImageGenerationReplicateRecraft) diff --git a/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py b/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py index b827ac4..749f463 100644 --- a/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py +++ b/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py @@ -59,7 +59,7 @@ class ImageGenerationReplicateSDXL(DVMTaskInterface): width = "1024" height = "1024" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/imagegeneration_sd21_mlx.py b/nostr_dvm/tasks/imagegeneration_sd21_mlx.py index 9a1b74d..3c66dbf 100644 --- a/nostr_dvm/tasks/imagegeneration_sd21_mlx.py +++ b/nostr_dvm/tasks/imagegeneration_sd21_mlx.py @@ -63,7 +63,7 @@ class ImageGenerationMLX(DVMTaskInterface): width = "1024" height = "1024" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/imagegeneration_sd35_api.py b/nostr_dvm/tasks/imagegeneration_sd35_api.py index a77e485..981e116 100644 --- a/nostr_dvm/tasks/imagegeneration_sd35_api.py +++ b/nostr_dvm/tasks/imagegeneration_sd35_api.py @@ -81,7 +81,7 @@ class ImageGenerationSD35(DVMTaskInterface): lora_weight = "" strength = "" guidance_scale = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/imagegeneration_sdxl.py b/nostr_dvm/tasks/imagegeneration_sdxl.py index 4ad0bf8..7c7e743 100644 --- a/nostr_dvm/tasks/imagegeneration_sdxl.py +++ b/nostr_dvm/tasks/imagegeneration_sdxl.py @@ -71,7 +71,7 @@ class ImageGenerationSDXL(DVMTaskInterface): lora_weight = "" strength = "" guidance_scale = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/imagegeneration_sdxlimg2img.py b/nostr_dvm/tasks/imagegeneration_sdxlimg2img.py index 190d913..9fa5fea 100644 --- a/nostr_dvm/tasks/imagegeneration_sdxlimg2img.py +++ b/nostr_dvm/tasks/imagegeneration_sdxlimg2img.py @@ -87,7 +87,7 @@ class ImageGenerationSDXLIMG2IMG(DVMTaskInterface): guidance_scale = float(self.options['guidance_scale']) else: guidance_scale = 11.0 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/imageinterrogator.py b/nostr_dvm/tasks/imageinterrogator.py index 5c18fad..3dfcf57 100644 --- a/nostr_dvm/tasks/imageinterrogator.py +++ b/nostr_dvm/tasks/imageinterrogator.py @@ -51,7 +51,7 @@ class ImageInterrogator(DVMTaskInterface): method = "prompt" mode = "best" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "url": diff --git a/nostr_dvm/tasks/imageupscale.py b/nostr_dvm/tasks/imageupscale.py index f3dbe32..afdccad 100644 --- a/nostr_dvm/tasks/imageupscale.py +++ b/nostr_dvm/tasks/imageupscale.py @@ -50,7 +50,7 @@ class ImageUpscale(DVMTaskInterface): url = "" out_scale = 4 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "url": diff --git a/nostr_dvm/tasks/people_discovery_mywot.py b/nostr_dvm/tasks/people_discovery_mywot.py index 0629cc7..454c0be 100644 --- a/nostr_dvm/tasks/people_discovery_mywot.py +++ b/nostr_dvm/tasks/people_discovery_mywot.py @@ -2,29 +2,10 @@ import csv import json import os import time -from datetime import timedelta import networkx as nx from nostr_sdk import Timestamp, PublicKey, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind - -from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv -from nostr_dvm.utils.admin_utils import AdminConfig -from nostr_dvm.utils.definitions import EventDefinitions -from nostr_dvm.utils.dvmconfig import DVMConfig, build_default_config -from nostr_dvm.utils.nip88_utils import NIP88Config, check_and_set_d_tag_nip88, check_and_set_tiereventid_nip88 -from nostr_dvm.utils.nip89_utils import NIP89Config, check_and_set_d_tag, create_amount_tag -from nostr_dvm.utils.output_utils import post_process_list_to_users -from nostr_dvm.utils.wot_utils import build_wot_network, save_network, load_network, convert_index_to_hex -import csv -import json -import os -import time -from datetime import timedelta - -import networkx as nx -from nostr_sdk import Timestamp, PublicKey, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv from nostr_dvm.utils.admin_utils import AdminConfig @@ -102,7 +83,7 @@ class DiscoverPeopleMyWOT(DVMTaskInterface): hops = 2 dunbar = 1000 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -198,7 +179,7 @@ class DiscoverPeopleMyWOT(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -221,12 +202,10 @@ class DiscoverPeopleMyWOT(DVMTaskInterface): async def sync_db(self): - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -242,8 +221,8 @@ class DiscoverPeopleMyWOT(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() @@ -272,14 +251,14 @@ async def analyse_users(user_ids=None, dunbar=100000000): if len(followers) > 0: for follower in followers: frens = [] - if len(follower.tags()) < dunbar: - for tag in follower.tags(): + if len(follower.tags().to_vec()) < dunbar: + for tag in follower.tags().to_vec(): if tag.as_vec()[0] == "p": frens.append(tag.as_vec()[1]) allfriends.append(Friend(follower.author().to_hex(), frens)) else: print("Skipping friend: " + follower.author().to_hex() + "Following: " + str( - len(follower.tags())) + " npubs") + len(follower.tags().to_vec())) + " npubs") return allfriends else: diff --git a/nostr_dvm/tasks/people_discovery_wot.py b/nostr_dvm/tasks/people_discovery_wot.py index 9b9aa00..2ddbf29 100644 --- a/nostr_dvm/tasks/people_discovery_wot.py +++ b/nostr_dvm/tasks/people_discovery_wot.py @@ -7,7 +7,7 @@ from datetime import timedelta import networkx as nx import pandas as pd from nostr_sdk import Timestamp, PublicKey, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, init_logger, LogLevel, Kind + ClientBuilder, Filter, SyncOptions, SyncDirection, init_logger, LogLevel, Kind from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv from nostr_dvm.utils.admin_utils import AdminConfig @@ -84,7 +84,7 @@ class DiscoverPeopleWOT(DVMTaskInterface): hops = 2 dunbar = 1000 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] elif tag.as_vec()[0] == 'param': @@ -185,7 +185,7 @@ class DiscoverPeopleWOT(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -207,13 +207,10 @@ class DiscoverPeopleWOT(DVMTaskInterface): return 1 async def sync_db(self): - - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_LONG_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() for relay in self.dvm_config.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) @@ -229,8 +226,8 @@ class DiscoverPeopleWOT(DVMTaskInterface): if self.dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: print("[" + self.dvm_config.NIP89.NAME + "] Syncing notes of the last " + str( self.db_since) + " seconds.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) await cli.database().delete(Filter().until(Timestamp.from_secs( Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. await cli.shutdown() @@ -259,14 +256,14 @@ async def analyse_users(user_ids=None, dunbar=100000000): if len(followers) > 0: for follower in followers: frens = [] - if len(follower.tags()) < dunbar: - for tag in follower.tags(): + if len(follower.tags().to_vec()) < dunbar: + for tag in follower.tags().to_vec(): if tag.as_vec()[0] == "p": frens.append(tag.as_vec()[1]) allfriends.append(Friend(follower.author().to_hex(), frens)) else: print("Skipping friend: " + follower.author().to_hex() + "Following: " + str( - len(follower.tags())) + " npubs") + len(follower.tags().to_vec())) + " npubs") return allfriends else: diff --git a/nostr_dvm/tasks/search_users.py b/nostr_dvm/tasks/search_users.py index 71d5080..2217b41 100644 --- a/nostr_dvm/tasks/search_users.py +++ b/nostr_dvm/tasks/search_users.py @@ -3,7 +3,7 @@ import os from datetime import timedelta from nostr_sdk import Timestamp, Tag, Keys, Options, SecretKey, NostrSigner, NostrDatabase, \ - ClientBuilder, Filter, NegentropyOptions, NegentropyDirection, Kind + ClientBuilder, Filter, SyncOptions, SyncDirection, Kind from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface, process_venv from nostr_dvm.utils.admin_utils import AdminConfig @@ -57,7 +57,7 @@ class SearchUser(DVMTaskInterface): search = "" max_results = 100 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": @@ -78,13 +78,10 @@ class SearchUser(DVMTaskInterface): from nostr_sdk import Filter options = self.set_options(request_form) - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().database(database).signer(signer).opts(opts).build() + cli = ClientBuilder().database(database).signer(keys).build() await cli.add_relay(self.relay) # cli.add_relay("wss://atl.purplerelay.com") @@ -120,7 +117,7 @@ class SearchUser(DVMTaskInterface): async def post_process(self, result, event): """Overwrite the interface function to return a social client readable format, if requested""" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'output': format = tag.as_vec()[1] if format == "text/plain": # check for output type @@ -140,12 +137,10 @@ class SearchUser(DVMTaskInterface): return 1 async def sync_db(self): - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb(self.db_name) - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() await cli.add_relay(self.relay) await cli.connect() @@ -154,8 +149,8 @@ class SearchUser(DVMTaskInterface): # filter = Filter().author(keys.public_key()) print("Syncing Profile Database.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) print("Done Syncing Profile Database.") await cli.shutdown() diff --git a/nostr_dvm/tasks/summarization_duckduck_ai.py b/nostr_dvm/tasks/summarization_duckduck_ai.py index 8f3e828..74b6b1b 100644 --- a/nostr_dvm/tasks/summarization_duckduck_ai.py +++ b/nostr_dvm/tasks/summarization_duckduck_ai.py @@ -48,7 +48,7 @@ class SummarizationDuckDuck(DVMTaskInterface): collect_events = [] nostr_mode = True - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/summarization_huggingchat.py b/nostr_dvm/tasks/summarization_huggingchat.py index 0734500..8aea328 100644 --- a/nostr_dvm/tasks/summarization_huggingchat.py +++ b/nostr_dvm/tasks/summarization_huggingchat.py @@ -46,7 +46,7 @@ class TextSummarizationHuggingChat(DVMTaskInterface): prompt = "" collect_events = [] - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/summarization_unleashed_chat.py b/nostr_dvm/tasks/summarization_unleashed_chat.py index ae044cf..fffb175 100644 --- a/nostr_dvm/tasks/summarization_unleashed_chat.py +++ b/nostr_dvm/tasks/summarization_unleashed_chat.py @@ -48,7 +48,7 @@ class SummarizationUnleashedChat(DVMTaskInterface): collect_events = [] nostr_mode = True - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/textextraction_google.py b/nostr_dvm/tasks/textextraction_google.py index deab4e9..04be3cb 100644 --- a/nostr_dvm/tasks/textextraction_google.py +++ b/nostr_dvm/tasks/textextraction_google.py @@ -59,7 +59,7 @@ class SpeechToTextGoogle(DVMTaskInterface): media_format = "audio/wav" language = "en-US" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "url": diff --git a/nostr_dvm/tasks/textextraction_pdf.py b/nostr_dvm/tasks/textextraction_pdf.py index 56cc59d..2f15b54 100644 --- a/nostr_dvm/tasks/textextraction_pdf.py +++ b/nostr_dvm/tasks/textextraction_pdf.py @@ -49,7 +49,7 @@ class TextExtractionPDF(DVMTaskInterface): input_content = "" url = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] input_content = tag.as_vec()[1] diff --git a/nostr_dvm/tasks/textextraction_whisperx.py b/nostr_dvm/tasks/textextraction_whisperx.py index efe2b09..910bd37 100644 --- a/nostr_dvm/tasks/textextraction_whisperx.py +++ b/nostr_dvm/tasks/textextraction_whisperx.py @@ -68,7 +68,7 @@ class SpeechToTextWhisperX(DVMTaskInterface): end_time = 0 media_format = "audio/mp3" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "url": diff --git a/nostr_dvm/tasks/textgeneration_huggingchat.py b/nostr_dvm/tasks/textgeneration_huggingchat.py index aa94df5..163a944 100644 --- a/nostr_dvm/tasks/textgeneration_huggingchat.py +++ b/nostr_dvm/tasks/textgeneration_huggingchat.py @@ -43,7 +43,7 @@ class TextGenerationHuggingChat(DVMTaskInterface): request_form = {"jobID": event.id().to_hex() + "_" + self.NAME.replace(" ", "")} prompt = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/textgeneration_llmlite.py b/nostr_dvm/tasks/textgeneration_llmlite.py index cb19a18..ce33766 100644 --- a/nostr_dvm/tasks/textgeneration_llmlite.py +++ b/nostr_dvm/tasks/textgeneration_llmlite.py @@ -51,7 +51,7 @@ class TextGenerationLLMLite(DVMTaskInterface): else: server = "http://localhost:11434" # default ollama server. This will only be used for ollama models. - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/textgeneration_unleashed_chat.py b/nostr_dvm/tasks/textgeneration_unleashed_chat.py index f213067..bb27229 100644 --- a/nostr_dvm/tasks/textgeneration_unleashed_chat.py +++ b/nostr_dvm/tasks/textgeneration_unleashed_chat.py @@ -44,7 +44,7 @@ class TextGenerationUnleashedChat(DVMTaskInterface): prompt = "" nostr_mode = True - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "text": diff --git a/nostr_dvm/tasks/texttospeech.py b/nostr_dvm/tasks/texttospeech.py index b3bd5e1..b90393a 100644 --- a/nostr_dvm/tasks/texttospeech.py +++ b/nostr_dvm/tasks/texttospeech.py @@ -70,7 +70,7 @@ class TextToSpeech(DVMTaskInterface): language = "en" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "event": diff --git a/nostr_dvm/tasks/translation_google.py b/nostr_dvm/tasks/translation_google.py index 6831008..da112f0 100644 --- a/nostr_dvm/tasks/translation_google.py +++ b/nostr_dvm/tasks/translation_google.py @@ -47,7 +47,7 @@ class TranslationGoogle(DVMTaskInterface): text = "" translation_lang = "en" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "event": diff --git a/nostr_dvm/tasks/translation_libretranslate.py b/nostr_dvm/tasks/translation_libretranslate.py index 762ddf4..e2fc33a 100644 --- a/nostr_dvm/tasks/translation_libretranslate.py +++ b/nostr_dvm/tasks/translation_libretranslate.py @@ -48,7 +48,7 @@ class TranslationLibre(DVMTaskInterface): text = "" translation_lang = "en" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "event": diff --git a/nostr_dvm/tasks/videogeneration_replicate_svd.py b/nostr_dvm/tasks/videogeneration_replicate_svd.py index 4d515b1..92cb235 100644 --- a/nostr_dvm/tasks/videogeneration_replicate_svd.py +++ b/nostr_dvm/tasks/videogeneration_replicate_svd.py @@ -58,7 +58,7 @@ class VideoGenerationReplicateSVD(DVMTaskInterface): motion_bucket_id = 127 # Increase overall motion in the generated video cond_aug = 0.02 # Amount of noise to add to input image - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "url": diff --git a/nostr_dvm/tasks/videogeneration_svd.py b/nostr_dvm/tasks/videogeneration_svd.py index 65c940e..ce60455 100644 --- a/nostr_dvm/tasks/videogeneration_svd.py +++ b/nostr_dvm/tasks/videogeneration_svd.py @@ -47,7 +47,7 @@ class VideoGenerationSVD(DVMTaskInterface): frames = 7 # 25 model = "stabilityai/stable-video-diffusion-img2vid-xt" # ,stabilityai/stable-video-diffusion-img2vid - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_type = tag.as_vec()[2] if input_type == "url": diff --git a/nostr_dvm/utils/backend_utils.py b/nostr_dvm/utils/backend_utils.py index aed4c71..7a93ccc 100644 --- a/nostr_dvm/utils/backend_utils.py +++ b/nostr_dvm/utils/backend_utils.py @@ -13,13 +13,13 @@ from nostr_dvm.utils.nostr_utils import get_event_by_id, get_referenced_event_by async def get_task(event, client, dvm_config): try: if event.kind() == EventDefinitions.KIND_NIP90_GENERIC: # use this for events that have no id yet, inclufr j tag - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'j': return tag.as_vec()[1] else: return "unknown job: " + event.as_json() elif event.kind() == EventDefinitions.KIND_DM: # dm - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'j': return tag.as_vec()[1] else: @@ -27,7 +27,7 @@ async def get_task(event, client, dvm_config): # This looks a bit more complicated, but we do several tasks for text-extraction in the future elif event.kind() == EventDefinitions.KIND_NIP90_EXTRACT_TEXT: - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "i": if tag.as_vec()[2] == "url": file_type = check_url_is_readable(tag.as_vec()[1]) @@ -44,7 +44,7 @@ async def get_task(event, client, dvm_config): evt = await get_event_by_id(tag.as_vec()[1], client=client, config=dvm_config) if evt is not None: if evt.kind() == 1063: - for tg in evt.tags(): + for tg in evt.tags().to_vec(): if tg.as_vec()[0] == 'url': file_type = check_url_is_readable(tg.as_vec()[1]) if file_type == "pdf": @@ -60,7 +60,7 @@ async def get_task(event, client, dvm_config): elif event.kind() == EventDefinitions.KIND_NIP90_GENERATE_IMAGE: has_image_tag = False has_text_tag = False - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "i": if tag.as_vec()[2] == "url": file_type = check_url_is_readable(tag.as_vec()[1]) @@ -130,7 +130,7 @@ async def check_task_is_supported(event: Event, client, config=None): try: dvm_config = config # Check for generic issues, event maformed, referenced event not found etc.. - if not is_input_supported_generic(event.tags(), client, dvm_config): + if not is_input_supported_generic(event.tags().to_vec(), client, dvm_config): return False, "" # See if current dvm supports the task @@ -140,7 +140,7 @@ async def check_task_is_supported(event: Event, client, config=None): # See if current dvm can handle input for given task for dvm in dvm_config.SUPPORTED_DVMS: if dvm.TASK == task: - if not await dvm.is_input_supported(event.tags(), client, config): + if not await dvm.is_input_supported(event.tags().to_vec(), client, config): return False, task return True, task diff --git a/nostr_dvm/utils/database_utils.py b/nostr_dvm/utils/database_utils.py index a04c093..a9abad0 100644 --- a/nostr_dvm/utils/database_utils.py +++ b/nostr_dvm/utils/database_utils.py @@ -252,12 +252,12 @@ async def fetch_user_metadata(npub, client): pk = PublicKey.parse(npub) print(f"\nGetting profile metadata for {pk.to_bech32()}...") profile_filter = Filter().kind(Kind(0)).author(pk).limit(1) - events = await client.get_events_of([profile_filter], relay_timeout) - if len(events) > 0: - latest_entry = events[0] + events = await client.fetch_events([profile_filter], relay_timeout) + if len(events.to_vec()) > 0: + latest_entry = events.to_vec()[0] latest_time = 0 try: - for entry in events: + for entry in events.to_vec(): if entry.created_at().as_secs() > latest_time: latest_time = entry.created_at().as_secs() latest_entry = entry diff --git a/nostr_dvm/utils/definitions.py b/nostr_dvm/utils/definitions.py index bf15e44..388ba61 100644 --- a/nostr_dvm/utils/definitions.py +++ b/nostr_dvm/utils/definitions.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from datetime import timedelta -from nostr_sdk import Event, Kind, EventSource +from nostr_sdk import Event, Kind class EventDefinitions: @@ -106,5 +106,5 @@ class InvoiceToWatch: expires: int -relay_timeout = EventSource.relays(timedelta(seconds=5)) -relay_timeout_long = EventSource.relays(timedelta(seconds=10)) +relay_timeout = timedelta(seconds=5) +relay_timeout_long = timedelta(seconds=10) diff --git a/nostr_dvm/utils/external_dvm_utils.py b/nostr_dvm/utils/external_dvm_utils.py index 0d30baf..6cdc961 100644 --- a/nostr_dvm/utils/external_dvm_utils.py +++ b/nostr_dvm/utils/external_dvm_utils.py @@ -11,11 +11,8 @@ from nostr_dvm.utils.output_utils import PostProcessFunctionType async def build_client(config): - opts = (Options().wait_for_send(True).send_timeout(timedelta(seconds=config.RELAY_TIMEOUT)) - .skip_disconnected_relays(True)) keys = Keys.parse(config.PRIVATE_KEY) - signer = NostrSigner.keys(keys) - client = Client.with_opts(signer, opts) + client = Client(keys) for relay in config.RELAY_LIST: await client.add_relay(relay) diff --git a/nostr_dvm/utils/gallery_utils.py b/nostr_dvm/utils/gallery_utils.py index a62b00b..8147431 100644 --- a/nostr_dvm/utils/gallery_utils.py +++ b/nostr_dvm/utils/gallery_utils.py @@ -7,8 +7,8 @@ from nostr_dvm.utils.print_utils import bcolors async def gallery_announce_list(tags, dvm_config, client): keys = Keys.parse(dvm_config.NIP89.PK) content = "" - event = EventBuilder(Kind(10011), content, tags).to_event(keys) - eventid = await send_event(event, client=client, dvm_config=dvm_config, blastr=True) + event = EventBuilder(Kind(10011), content, tags).sign_with_keys(keys) + eventid = await send_event(event, client=client, dvm_config=dvm_config) print( bcolors.BLUE + "[" + dvm_config.NIP89.NAME + "] Announced Gallery for " + dvm_config.NIP89.NAME + " (EventID: " + str( diff --git a/nostr_dvm/utils/mediasource_utils.py b/nostr_dvm/utils/mediasource_utils.py index f8157f1..7d63100 100644 --- a/nostr_dvm/utils/mediasource_utils.py +++ b/nostr_dvm/utils/mediasource_utils.py @@ -18,7 +18,7 @@ async def input_data_file_duration(event, dvm_config, client, start=0, end=0): input_value = "" input_type = "" count = 0 - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'i': input_value = tag.as_vec()[1] input_type = tag.as_vec()[2] @@ -132,7 +132,7 @@ def check_nip94_event_for_media(evt, input_value, input_type): input_type = "text" input_value = evt.content() if evt.kind() == 1063: - for tag in evt.tags(): + for tag in evt.tags().to_vec(): if tag.as_vec()[0] == 'url': input_type = "url" input_value = tag.as_vec()[1] diff --git a/nostr_dvm/utils/nip65_utils.py b/nostr_dvm/utils/nip65_utils.py index 8761d78..8797651 100644 --- a/nostr_dvm/utils/nip65_utils.py +++ b/nostr_dvm/utils/nip65_utils.py @@ -15,7 +15,7 @@ async def announce_dm_relays(dvm_config, client): keys = Keys.parse(dvm_config.NIP89.PK) content = "" - event = EventBuilder(Kind(10050), content, tags).to_event(keys) + event = EventBuilder(Kind(10050), content, tags).sign_with_keys(keys) eventid = await send_event(event, client=client, dvm_config=dvm_config) if (eventid is not None): print( @@ -39,7 +39,7 @@ async def nip65_announce_relays(dvm_config, client): keys = Keys.parse(dvm_config.NIP89.PK) content = "" - event = EventBuilder(EventDefinitions.KIND_RELAY_ANNOUNCEMENT, content, tags).to_event(keys) + event = EventBuilder(EventDefinitions.KIND_RELAY_ANNOUNCEMENT, content, tags).sign_with_keys(keys) eventid = await send_event(event, client=client, dvm_config=dvm_config) if (eventid is not None): print( diff --git a/nostr_dvm/utils/nip88_utils.py b/nostr_dvm/utils/nip88_utils.py index f2b556b..199dda2 100644 --- a/nostr_dvm/utils/nip88_utils.py +++ b/nostr_dvm/utils/nip88_utils.py @@ -36,14 +36,14 @@ def nip88_create_d_tag(name, pubkey, image): async def fetch_nip88_parameters_for_deletion(keys, eventid, client, dvmconfig): idfilter = Filter().id(EventId.from_hex(eventid)).limit(1) - nip88events = await client.get_events_of([idfilter], relay_timeout) + nip88events = await client.fetch_events([idfilter], relay_timeout) d_tag = "" - if len(nip88events) == 0: + if len(nip88events.to_vec()) == 0: print("Event not found. Potentially gone.") - for event in nip88events: + for event in nip88events.to_vec(): print(event.as_json()) - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "d": d_tag = tag.as_vec()[1] if d_tag == "": @@ -59,14 +59,14 @@ async def fetch_nip88_parameters_for_deletion(keys, eventid, client, dvmconfig): async def fetch_nip88_event(keys, eventid, client, dvmconfig): idfilter = Filter().id(EventId.parse(eventid)).limit(1) - nip88events = await client.get_events_of([idfilter], relay_timeout) + nip88events = await client.fetch_events([idfilter], relay_timeout) d_tag = "" - if len(nip88events) == 0: + if len(nip88events.to_vec()) == 0: print("Event not found. Potentially gone.") - for event in nip88events: + for event in nip88events.to_vec(): - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "d": d_tag = tag.as_vec()[1] if d_tag == "": @@ -83,7 +83,7 @@ async def nip88_delete_announcement(eid: str, keys: Keys, dtag: str, client: Cli e_tag = Tag.parse(["e", eid]) a_tag = Tag.parse( ["a", str(EventDefinitions.KIND_NIP88_TIER_EVENT) + ":" + keys.public_key().to_hex() + ":" + dtag]) - event = EventBuilder(Kind(5), "", [e_tag, a_tag]).to_event(keys) + event = EventBuilder(Kind(5), "", [e_tag, a_tag]).sign_with_keys(keys) await send_event(event, client, config) @@ -99,11 +99,11 @@ async def nip88_has_active_subscription(user: PublicKey, tiereventdtag, 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 = await client.get_events_of([subscriptionfilter], relay_timeout) - if len(evts) > 0: - print(evts[0].as_json()) + evts = await client.fetch_events([subscriptionfilter], relay_timeout) + if len(evts.to_vec()) > 0: + print(evts.to_vec()[0].as_json()) matchesdtag = False - for tag in evts[0].tags(): + for tag in evts.to_vec()[0].tags().to_vec(): if tag.as_vec()[0] == "valid": subscription_status["validUntil"] = int(tag.as_vec()[2]) elif tag.as_vec()[0] == "e": @@ -120,9 +120,9 @@ async def nip88_has_active_subscription(user: PublicKey, tiereventdtag, client: 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 = await client.get_events_of([cancel_filter], relay_timeout) - if len(cancel_events) > 0: - if cancel_events[0].created_at().as_secs() > evts[0].created_at().as_secs(): + cancel_events = await client.fetch_events([cancel_filter], relay_timeout) + if len(cancel_events.to_vec()) > 0: + if cancel_events.to_vec()[0].created_at().as_secs() > evts[0].created_at().as_secs(): subscription_status["expires"] = True return subscription_status @@ -176,7 +176,7 @@ async def nip88_announce_tier(dvm_config, client): keys = Keys.parse(dvm_config.NIP89.PK) content = dvm_config.NIP88.CONTENT - event = EventBuilder(EventDefinitions.KIND_NIP88_TIER_EVENT, content, tags).to_event(keys) + event = EventBuilder(EventDefinitions.KIND_NIP88_TIER_EVENT, content, tags).sign_with_keys(keys) annotier_id = await send_event(event, client=client, dvm_config=dvm_config) if dvm_config.NIP89 is not None: diff --git a/nostr_dvm/utils/nip89_utils.py b/nostr_dvm/utils/nip89_utils.py index c7caf4f..3234c47 100644 --- a/nostr_dvm/utils/nip89_utils.py +++ b/nostr_dvm/utils/nip89_utils.py @@ -29,7 +29,7 @@ async def nip89_announce_tasks(dvm_config, client): d_tag = Tag.parse(["d", dvm_config.NIP89.DTAG]) keys = Keys.parse(dvm_config.NIP89.PK) content = dvm_config.NIP89.CONTENT - event = EventBuilder(EventDefinitions.KIND_ANNOUNCEMENT, content, [k_tag, d_tag]).to_event(keys) + event = EventBuilder(EventDefinitions.KIND_ANNOUNCEMENT, content, [k_tag, d_tag]).sign_with_keys(keys) eventid = await send_event(event, client=client, dvm_config=dvm_config) print( @@ -38,14 +38,14 @@ async def nip89_announce_tasks(dvm_config, client): async def fetch_nip89_parameters_for_deletion(keys, eventid, client, dvmconfig, pow=False): idfilter = Filter().id(EventId.from_hex(eventid)).limit(1) - nip89events = await client.get_events_of([idfilter], relay_timeout) + nip89events = await client.fetch_events([idfilter], relay_timeout) d_tag = "" - if len(nip89events) == 0: + if len(nip89events.to_vec()) == 0: print("Event not found. Potentially gone.") - for event in nip89events: + for event in nip89events.to_vec(): print(event.as_json()) - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "d": d_tag = tag.as_vec()[1] if d_tag == "": @@ -65,7 +65,7 @@ async def nip89_delete_announcement(eid: str, keys: Keys, dtag: str, client: Cli e_tag = Tag.parse(["e", eid]) a_tag = Tag.parse( ["a", str(EventDefinitions.KIND_ANNOUNCEMENT.as_u16()) + ":" + keys.public_key().to_hex() + ":" + dtag]) - event = EventBuilder(Kind(5), "", [e_tag, a_tag]).to_event(keys) + event = EventBuilder(Kind(5), "", [e_tag, a_tag]).sign_with_keys(keys) print(f"POW event: {event.as_json()}") await send_event(event, client, config) @@ -74,7 +74,7 @@ async def nip89_delete_announcement_pow(eid: str, keys: Keys, dtag: str, client: e_tag = Tag.parse(["e", eid]) a_tag = Tag.parse( ["a", str(EventDefinitions.KIND_ANNOUNCEMENT.as_u16()) + ":" + keys.public_key().to_hex() + ":" + dtag]) - event = EventBuilder(Kind(5), "", [e_tag, a_tag]).pow(28).to_event(keys) + event = EventBuilder(Kind(5), "", [e_tag, a_tag]).pow(28).sign_with_keys(keys) print(f"POW event: {event.as_json()}") await send_event(event, client, config) @@ -85,8 +85,8 @@ async def nip89_fetch_all_dvms(client): ktags.append(str(i)) filter = Filter().kind(EventDefinitions.KIND_ANNOUNCEMENT).custom_tag(SingleLetterTag.lowercase(Alphabet.K), ktags) - events = await client.get_events_of([filter], relay_timeout) - for event in events: + events = await client.fetch_events([filter], relay_timeout) + for event in events.to_vec(): print(event.as_json()) @@ -94,10 +94,10 @@ async def nip89_fetch_events_pubkey(client, pubkey, kind): ktags = [str(kind.as_u16())] nip89filter = (Filter().kind(EventDefinitions.KIND_ANNOUNCEMENT).author(PublicKey.parse(pubkey)). custom_tag(SingleLetterTag.lowercase(Alphabet.K), ktags)) - events = await client.get_events_of([nip89filter], relay_timeout) + events = await client.fetch_events([nip89filter], relay_timeout) dvms = {} - for event in events: + for event in events.to_vec(): if dvms.get(event.author().to_hex()): if dvms.get(event.author().to_hex()).created_at().as_secs() < event.created_at().as_secs(): dvms[event.author().to_hex()] = event diff --git a/nostr_dvm/utils/nip98_utils.py b/nostr_dvm/utils/nip98_utils.py index a66bfdd..d1f3cf3 100644 --- a/nostr_dvm/utils/nip98_utils.py +++ b/nostr_dvm/utils/nip98_utils.py @@ -17,7 +17,8 @@ async def generate_nip98_header(pkeys_hex, url="", kind="POST", filepath=""): if kind == "POST": payloadtag = Tag.parse(["payload", sha256sum(filepath)]) tags.append(payloadtag) - event = EventBuilder(Kind(27235), "", tags).to_event(keys) + eb = EventBuilder(Kind(27235), "", tags) + event = eb.sign_with_keys(keys) encoded_nip98_event = base64.b64encode(event.as_json().encode('utf-8')).decode('utf-8') diff --git a/nostr_dvm/utils/nostr_utils.py b/nostr_dvm/utils/nostr_utils.py index a96ab37..3facd90 100644 --- a/nostr_dvm/utils/nostr_utils.py +++ b/nostr_dvm/utils/nostr_utils.py @@ -17,16 +17,16 @@ async def get_event_by_id(event_id_str: str, client: Client, config=None) -> Eve if len(split) == 3: pk = PublicKey.from_hex(split[1]) id_filter = Filter().author(pk).custom_tag(SingleLetterTag.lowercase(Alphabet.D), [split[2]]) - events = await client.get_events_of([id_filter], relay_timeout) + events = await client.fetch_events([id_filter], relay_timeout) else: event_id = EventId.parse(event_id_str) id_filter = Filter().id(event_id).limit(1) - events = await client.get_events_of([id_filter], relay_timeout) + events = await client.fetch_events([id_filter], relay_timeout) - if len(events) > 0: - return events[0] + if len(events.to_vec()) > 0: + return events.to_vec()[0] else: print("Event not found") return None @@ -34,8 +34,8 @@ async def get_event_by_id(event_id_str: str, client: Client, config=None) -> Eve async def get_events_async(client, filter, timeout): source_l = EventSource.relays(timedelta(seconds=timeout)) - events = await client.get_events_of([filter], source_l) - return events + events = await client.fetch_events([filter], source_l) + return events.to_vec() async def get_events_by_ids(event_ids, client: Client, config=None) -> List | None: @@ -46,7 +46,7 @@ async def get_events_by_ids(event_ids, client: Client, config=None) -> List | No if len(split) == 3: pk = PublicKey.from_hex(split[1]) id_filter = Filter().author(pk).custom_tag(SingleLetterTag.lowercase(Alphabet.D), [split[2]]) - events = await client.get_events_of([id_filter], relay_timeout) + events = await client.fetch_events([id_filter], relay_timeout) else: if str(event_id).startswith('note'): event_id = EventId.from_bech32(event_id) @@ -62,10 +62,10 @@ async def get_events_by_ids(event_ids, client: Client, config=None) -> List | No search_ids.append(event_id) id_filter = Filter().ids(search_ids) - events = await client.get_events_of([id_filter], relay_timeout) + events = await client.fetch_events([id_filter], relay_timeout) - if len(events) > 0: - return events + if len(events.to_vec()) > 0: + return events.to_vec() else: return None @@ -73,9 +73,9 @@ async def get_events_by_ids(event_ids, client: Client, config=None) -> List | No async def get_events_by_id(event_ids: list, client: Client, config=None) -> list[Event] | None: id_filter = Filter().ids(event_ids) # events = asyncio.run(get_events_async(client, id_filter, config.RELAY_TIMEOUT)) - events = await client.get_events_of([id_filter], relay_timeout) - if len(events) > 0: - return events + events = await client.fetch_events([id_filter], relay_timeout) + if len(events.to_vec()) > 0: + return events.to_vec() else: return None @@ -98,29 +98,29 @@ async def get_referenced_event_by_id(event_id, client, dvm_config, kinds) -> Eve job_id_filter = Filter().kinds(kinds).event(event_id).limit(1) else: job_id_filter = Filter().event(event_id).limit(1) - events = await client.get_events_of([job_id_filter], relay_timeout) + events = await client.fetch_events([job_id_filter], relay_timeout) - if len(events) > 0: - return events[0] + if len(events.to_vec()) > 0: + return events.to_vec()[0] else: return None async def get_inbox_relays(event_to_send: Event, client: Client, dvm_config): ptags = [] - for tag in event_to_send.tags(): + for tag in event_to_send.tags().to_vec(): if tag.as_vec()[0] == 'p': ptag = PublicKey.parse(tag.as_vec()[1]) ptags.append(ptag) filter = Filter().kinds([EventDefinitions.KIND_RELAY_ANNOUNCEMENT]).authors(ptags) - events = await client.get_events_of([filter], relay_timeout) - if len(events) == 0: + events = await client.fetch_events([filter], relay_timeout) + if len(events.to_vec()) == 0: return [] else: - nip65event = events[0] + nip65event = events.to_vec()[0] relays = [] - for tag in nip65event.tags(): + for tag in nip65event.tags().to_vec(): if ((tag.as_vec()[0] == 'r' and len(tag.as_vec()) == 2) or ((tag.as_vec()[0] == 'r' and len(tag.as_vec()) == 3) and tag.as_vec()[2] == "read")): rtag = tag.as_vec()[1] @@ -132,19 +132,19 @@ async def get_inbox_relays(event_to_send: Event, client: Client, dvm_config): async def get_dm_relays(event_to_send: Event, client: Client, dvm_config): ptags = [] - for tag in event_to_send.tags(): + for tag in event_to_send.tags().to_vec(): if tag.as_vec()[0] == 'p': ptag = PublicKey.parse(tag.as_vec()[1]) ptags.append(ptag) filter = Filter().kinds([Kind(10050)]).authors(ptags) - events = await client.get_events_of([filter], relay_timeout) - if len(events) == 0: + events = await client.fetch_events([filter], relay_timeout) + if len(events.to_vec()) == 0: return [] else: - nip65event = events[0] + nip65event = events.to_vec()[0] relays = [] - for tag in nip65event.tags(): + for tag in nip65event.tags().to_vec(): if ((tag.as_vec()[0] == 'r' and len(tag.as_vec()) == 2) or ((tag.as_vec()[0] == 'r' and len(tag.as_vec()) == 3) and tag.as_vec()[2] == "read")): rtag = tag.as_vec()[1] @@ -156,7 +156,7 @@ async def get_dm_relays(event_to_send: Event, client: Client, dvm_config): async def get_main_relays(event_to_send: Event, client: Client, dvm_config): ptags = [] - for tag in event_to_send.tags(): + for tag in event_to_send.tags().to_vec(): if tag.as_vec()[0] == 'p': ptag = PublicKey.parse(tag.as_vec()[1]) ptags.append(ptag) @@ -167,11 +167,11 @@ async def get_main_relays(event_to_send: Event, client: Client, dvm_config): await client.connect() filter = Filter().kinds([EventDefinitions.KIND_FOLLOW_LIST]).authors(ptags) - events = await client.get_events_of([filter], relay_timeout) - if len(events) == 0: + events = await client.fetch_events([filter], relay_timeout) + if len(events.to_vec()) == 0: return [] else: - followlist = events[0] + followlist = events.to_vec()[0] try: content = json.loads(followlist.content()) relays = [] @@ -186,7 +186,7 @@ async def send_event_outbox(event: Event, client, dvm_config) -> EventId: # 1. OK, Let's overcomplicate things. # 2. If our event has a relays tag, we just send the event to these relay in the classical way. relays = [] - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'relays': for index, param in enumerate(tag.as_vec()): if index != 0: @@ -215,13 +215,11 @@ async def send_event_outbox(event: Event, client, dvm_config) -> EventId: connection = Connection().embedded_tor().target(ConnectionTarget.ONION) # connection = Connection().addr("127.0.0.1:9050").target(ConnectionTarget.ONION) opts = (( - Options().wait_for_send(False).send_timeout(timedelta(seconds=5)).relay_limits( - relaylimits)).connection(connection).connection_timeout(timedelta(seconds=30))) + Options().relay_limits(relaylimits)).connection(connection).connection_timeout(timedelta(seconds=30))) sk = SecretKey.from_hex(dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - outboxclient = Client.with_opts(signer, opts) + outboxclient = Client.with_opts(keys, opts) print("[" + dvm_config.NIP89.NAME + "] Receiver Inbox relays: " + str(relays)) for relay in relays[:5]: @@ -265,7 +263,7 @@ async def send_event_outbox(event: Event, client, dvm_config) -> EventId: async def send_event(event: Event, client: Client, dvm_config): try: relays = [] - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'relays': for index, param in enumerate(tag.as_vec()): if index != 0: @@ -301,7 +299,7 @@ def check_and_decrypt_tags(event, dvm_config): is_encrypted = False p = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'encrypted': is_encrypted = True elif tag.as_vec()[0] == 'p': @@ -333,7 +331,7 @@ def check_and_decrypt_own_tags(event, dvm_config): try: is_encrypted = False p = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == 'encrypted': is_encrypted = True elif tag.as_vec()[0] == 'p': @@ -363,11 +361,7 @@ def check_and_decrypt_own_tags(event, dvm_config): async def update_profile_lnaddress(private_key, dvm_config, lud16="", ): keys = Keys.parse(private_key) - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=5)) - .skip_disconnected_relays(True)) - - signer = NostrSigner.keys(keys) - client = Client.with_opts(signer, opts) + client = Client(keys) for relay in dvm_config.RELAY_LIST: await client.add_relay(relay) await client.connect() @@ -409,10 +403,10 @@ async def update_profile(dvm_config, client, lud16=""): async def send_nip04_dm(client: Client, msg, receiver: PublicKey, dvm_config): - signer = NostrSigner.keys(Keys.parse(dvm_config.PRIVATE_KEY)) - content = await signer.nip04_encrypt(receiver, msg) + keys = Keys.parse(dvm_config.PRIVATE_KEY) + content = await keys.nip04_encrypt(receiver, msg) ptag = Tag.parse(["p", receiver.to_hex()]) - event = EventBuilder(Kind(4), content, [ptag]).to_event(Keys.parse(dvm_config.PRIVATE_KEY)) + event = EventBuilder(Kind(4), content, [ptag]).sign_with_keys(Keys.parse(dvm_config.PRIVATE_KEY)) await client.send_event(event) # relays = await get_dm_relays(event, client, dvm_config) diff --git a/nostr_dvm/utils/nut_wallet_utils.py b/nostr_dvm/utils/nut_wallet_utils.py index 9c44a53..e3f1f6b 100644 --- a/nostr_dvm/utils/nut_wallet_utils.py +++ b/nostr_dvm/utils/nut_wallet_utils.py @@ -52,13 +52,7 @@ class NutZapWallet: async def client_connect(self, relay_list): keys = Keys.parse(check_and_set_private_key("TEST_ACCOUNT_PK")) - wait_for_send = False - skip_disconnected_relays = True - opts = (Options().wait_for_send(wait_for_send).send_timeout(timedelta(seconds=5)) - .skip_disconnected_relays(skip_disconnected_relays)) - - signer = NostrSigner.keys(keys) - client = Client.with_opts(signer, opts) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -109,7 +103,7 @@ class NutZapWallet: relay_tag = Tag.parse(["relay", relay]) tags.append(relay_tag) - event = EventBuilder(EventDefinitions.KIND_NUT_WALLET, content, tags).to_event(keys) + event = EventBuilder(EventDefinitions.KIND_NUT_WALLET, content, tags).sign_with_keys(keys) send_response = await client.send_event(event) print( @@ -121,8 +115,8 @@ class NutZapWallet: nut_wallet = None wallet_filter = Filter().kind(EventDefinitions.KIND_NUT_WALLET).author(keys.public_key()) - # relay_timeout = EventSource.relays(timedelta(seconds=10)) - wallets = await client.get_events_of([wallet_filter], relay_timeout_long) + wallets_struct = await client.fetch_events([wallet_filter], relay_timeout_long) + wallets = wallets_struct.to_vec() if len(wallets) > 0: @@ -133,7 +127,7 @@ class NutZapWallet: for wallet_event in wallets: isdeleted = False - for tag in wallet_event.tags(): + for tag in wallet_event.tags().to_vec(): if tag.as_vec()[0] == "deleted": isdeleted = True break @@ -175,7 +169,7 @@ class NutZapWallet: if tag[1] not in nut_wallet.mints: nut_wallet.mints.append(tag[1]) - for tag in best_wallet.tags(): + for tag in best_wallet.tags().to_vec(): if tag.as_vec()[0] == "d": nut_wallet.d = tag.as_vec()[1] @@ -197,7 +191,8 @@ class NutZapWallet: # Now all proof events proof_filter = Filter().kind(Kind(7375)).author(keys.public_key()) # relay_timeout = EventSource.relays(timedelta(seconds=5)) - proof_events = await client.get_events_of([proof_filter], relay_timeout) + proof_events_struct = await client.fetch_events([proof_filter], relay_timeout) + proof_events = proof_events_struct.to_vec() latest_proof_sec = 0 latest_proof_event_id = EventId @@ -227,7 +222,7 @@ class NutZapWallet: except Exception as e: pass - for tag in proof_event.tags(): + for tag in proof_event.tags().to_vec(): if tag.as_vec()[0] == "mint": mint_url = tag.as_vec()[1] print("mint: " + mint_url) @@ -334,7 +329,7 @@ class NutZapWallet: p_tag = Tag.parse(["p", sender_hex]) tags.append(p_tag) - event = EventBuilder(Kind(7376), content, tags).to_event(keys) + event = EventBuilder(Kind(7376), content, tags).sign_with_keys(keys) eventid = await client.send_event(event) async def create_unspent_proof_event(self, nut_wallet: NutWallet, mint_proofs, mint_url, amount, direction, marker, @@ -358,7 +353,7 @@ class NutZapWallet: if mint.previous_event_id is not None: print( bcolors.MAGENTA + "[" + nut_wallet.name + "] Deleted previous proofs event.. : (" + mint.previous_event_id.to_hex() + ")" + bcolors.ENDC) - evt = EventBuilder.delete([mint.previous_event_id], reason="deleted").to_event( + evt = EventBuilder.delete([mint.previous_event_id], reason="deleted").sign_with_keys( keys) # .to_pow_event(keys, 28) response = await client.send_event(evt) @@ -380,7 +375,7 @@ class NutZapWallet: else: content = nip44_encrypt(keys.secret_key(), keys.public_key(), message, Nip44Version.V2) - event = EventBuilder(Kind(7375), content, tags).to_event(keys) + event = EventBuilder(Kind(7375), content, tags).sign_with_keys(keys) eventid = await client.send_event(event) await self.create_transaction_history_event(nut_wallet, amount, nut_wallet.unit, old_event_id, eventid.id, direction, marker, sender_hex, event_hex, client, keys) @@ -443,7 +438,7 @@ class NutZapWallet: pubkey = Keys.parse(nut_wallet.privkey).public_key().to_hex() tags.append(Tag.parse(["pubkey", pubkey])) - event = EventBuilder(Kind(10019), "", tags).to_event(keys) + event = EventBuilder(Kind(10019), "", tags).sign_with_keys(keys) eventid = await client.send_event(event) print( bcolors.CYAN + "[" + nut_wallet.name + "] Announced mint preferences info event (" + eventid.id.to_hex() + ")" + bcolors.ENDC) @@ -451,7 +446,8 @@ class NutZapWallet: async def fetch_mint_info_event(self, pubkey, client): mint_info_filter = Filter().kind(Kind(10019)).author(PublicKey.parse(pubkey)) # relay_timeout = EventSource.relays(timedelta(seconds=5)) - preferences = await client.get_events_of([mint_info_filter], relay_timeout) + events_struct = await client.fetch_events([mint_info_filter], relay_timeout) + preferences = events_struct.to_vec() mints = [] relays = [] pubkey = "" @@ -459,7 +455,7 @@ class NutZapWallet: if len(preferences) > 0: preference = preferences[0] - for tag in preference.tags(): + for tag in preference.tags().to_vec(): if tag.as_vec()[0] == "pubkey": pubkey = tag.as_vec()[1] elif tag.as_vec()[0] == "relay": @@ -632,7 +628,7 @@ class NutZapWallet: } tags.append(Tag.parse(["proof", json.dumps(nut_proof)])) - event = EventBuilder(Kind(9321), comment, tags).to_event(keys) + event = EventBuilder(Kind(9321), comment, tags).sign_with_keys(keys) response = await client.send_event(event) await self.update_spend_mint_proof_event(nut_wallet, proofs, mint_url, "zapped", keys.public_key().to_hex(), @@ -667,7 +663,7 @@ class NutZapWallet: unit = "sat" sender = "" event = "" - for tag in transaction.tags(): + for tag in transaction.tags().to_vec(): if tag.as_vec()[0] == "p": sender = tag.as_vec()[1] elif tag.as_vec()[0] == "e": @@ -707,7 +703,7 @@ class NutZapWallet: zapped_event = "" sender = event.author().to_hex() message = event.content() - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "proof": proof_json = json.loads(tag.as_vec()[1]) proof = Proof().from_dict(proof_json) diff --git a/nostr_dvm/utils/output_utils.py b/nostr_dvm/utils/output_utils.py index 1ebcce7..c4f2f83 100644 --- a/nostr_dvm/utils/output_utils.py +++ b/nostr_dvm/utils/output_utils.py @@ -33,7 +33,7 @@ def post_process_result(anno, original_event): has_output_tag = False output_format = "text/plain" - for tag in original_event.tags(): + for tag in original_event.tags().to_vec(): if tag.as_vec()[0] == "output": output_format = tag.as_vec()[1] has_output_tag = True @@ -170,6 +170,7 @@ async def upload_media_to_hoster(filepath: str, key_hex=None, fallback=True): limitinmb = await request_nostr_build_limit(key_hex) + if sizeinmb > limitinmb: if fallback: print("Filesize over Nostr.build limit, using paid account") @@ -217,7 +218,9 @@ async def upload_nostr_build(pkey, files, filepath): async def request_nostr_build_limit(pkey): url = 'https://nostr.build/api/v2/upload/limit' + auth = await generate_nip98_header(pkey, url, "GET") + headers = {'authorization': auth} response = requests.get(url, headers=headers) json_object = json.loads(response.text) @@ -309,7 +312,7 @@ async def send_job_status_reaction(original_event_id_hex, original_event_author_ content = reaction keys = Keys.parse(dvm_config.PRIVATE_KEY) - reaction_event = EventBuilder(EventDefinitions.KIND_FEEDBACK, str(content), reply_tags).to_event(keys) + reaction_event = EventBuilder(EventDefinitions.KIND_FEEDBACK, str(content), reply_tags).sign_with_keys(keys) await send_event_outbox(reaction_event, client=client, dvm_config=dvm_config) if dvm_config.LOGLEVEL.value >= LogLevel.DEBUG.value: diff --git a/nostr_dvm/utils/reaction_utils.py b/nostr_dvm/utils/reaction_utils.py index 7ba1736..94cd038 100644 --- a/nostr_dvm/utils/reaction_utils.py +++ b/nostr_dvm/utils/reaction_utils.py @@ -21,10 +21,9 @@ async def create_reaction(keys, title, dtag): keys = Keys.parse(keys) content = "" - event = EventBuilder(Kind(30030), content, [d_tag, title_tag] + emoji_tags).to_event(keys) + event = EventBuilder(Kind(30030), content, [d_tag, title_tag] + emoji_tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) # We add the relays we defined above and told our DVM we would want to receive events to. for relay in DVMConfig().RELAY_LIST: await client.add_relay(relay) @@ -43,10 +42,9 @@ async def delete_reaction(keys, eid: str, dtag: str): e_tag = Tag.parse(["e", eid]) a_tag = Tag.parse( ["a", "30030:" + keys.public_key().to_hex() + ":" + dtag]) - event = EventBuilder(Kind(5), "", [e_tag, a_tag]).to_event(keys) + event = EventBuilder(Kind(5), "", [e_tag, a_tag]).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) # We add the relays we defined above and told our DVM we would want to receive events to. for relay in DVMConfig().RELAY_LIST: await client.add_relay(relay) diff --git a/nostr_dvm/utils/wot_utils.py b/nostr_dvm/utils/wot_utils.py index 6aa8ab0..4c45276 100644 --- a/nostr_dvm/utils/wot_utils.py +++ b/nostr_dvm/utils/wot_utils.py @@ -37,34 +37,32 @@ async def get_following(pks, max_time_request=10, newer_than_time=None): # newer_than_time provided? If so, it only fetch events that are newer if newer_than_time is None: - filter = nostr_sdk.Filter().authors(list_pk).kind(Kind(3)) + filter = Filter().authors(list_pk).kind(Kind(3)) else: newer_than_time = round(newer_than_time) ts = nostr_sdk.Timestamp().from_secs(newer_than_time) - filter = nostr_sdk.Filter().authors(list_pk).kind(3).since(ts) + filter = Filter().authors(list_pk).kind(Kind(3)).since(ts) # fetching events - opts = (Options().wait_for_send(False).send_timeout(datetime.timedelta(seconds=5))) keys = Keys.parse(check_and_set_private_key("test_client")) - signer = NostrSigner.keys(keys) - cli = ClientBuilder().signer(signer).opts(opts).build() + cli = ClientBuilder().signer(keys).build() for relay in DVMConfig.RECONCILE_DB_RELAY_LIST: await cli.add_relay(relay) await cli.connect() - events = await cli.get_events_of([filter], relay_timeout) + events = await cli.fetch_events([filter], relay_timeout) # initializing the graph structure following = nx.DiGraph() following.add_nodes_from(pks) - if events == []: + if not events.to_vec(): return following - for event in events: + for event in events.to_vec(): author = event.author().to_hex() @@ -73,7 +71,7 @@ async def get_following(pks, max_time_request=10, newer_than_time=None): if event.verify() and author in following.nodes() and 'timestamp' not in following.nodes[author]: # updating the nodes and edges - nodes = event.public_keys() + nodes = event.tags().public_keys() # TODO # converting to hex and removing self-following nodes = [pk.to_hex() for pk in nodes if pk.to_hex() != author] @@ -194,7 +192,7 @@ def split_set(my_set, max_batch): def save_network(index_map, network_graph, name=None): - if name == None: + if name is None: # adding unix time to file name to avoid replacing an existing file name = str(round(time.time())) # filename = os.path.join('/cache/', 'index_map_' + name + '.json') @@ -583,10 +581,8 @@ async def get_metadata(npub): pk = PublicKey.parse(npub) except: return "", "", "" - opts = (Options().wait_for_send(False).send_timeout(datetime.timedelta(seconds=5))) keys = Keys.parse(check_and_set_private_key("test_client")) - signer = NostrSigner.keys(keys) - client = ClientBuilder().signer(signer).opts(opts).build() + client = ClientBuilder().signer(keys).build() await client.add_relay("wss://relay.damus.io") await client.add_relay("wss://relay.primal.net") await client.add_relay("wss://purplepag.es") @@ -594,7 +590,8 @@ async def get_metadata(npub): profile_filter = Filter().kind(Kind(0)).author(pk).limit(1) - events = await client.get_events_of([profile_filter], relay_timeout) + events_struct = await client.fetch_events([profile_filter], relay_timeout) + events = events_struct.to_vec() if len(events) > 0: try: profile = json.loads(events[0].content()) diff --git a/nostr_dvm/utils/zap_utils.py b/nostr_dvm/utils/zap_utils.py index 3cfb071..50dcf94 100644 --- a/nostr_dvm/utils/zap_utils.py +++ b/nostr_dvm/utils/zap_utils.py @@ -33,7 +33,7 @@ async def parse_zap_event_tags(zap_event, keys, name, client, config): anon = False message = "" sender = zap_event.author() - for tag in zap_event.tags(): + for tag in zap_event.tags().to_vec(): if tag.as_vec()[0] == 'bolt11': invoice_amount = parse_amount_from_bolt11_invoice(tag.as_vec()[1]) elif tag.as_vec()[0] == 'e': @@ -46,7 +46,7 @@ async def parse_zap_event_tags(zap_event, keys, name, client, config): zap_request_event = Event.from_json(tag.as_vec()[1]) sender = check_for_zapplepay(zap_request_event.author().to_hex(), zap_request_event.content()) - for z_tag in zap_request_event.tags(): + for z_tag in zap_request_event.tags().to_vec(): if z_tag.as_vec()[0] == 'anon': if len(z_tag.as_vec()) > 1: # print("[" + name + "] Private Zap received.") @@ -305,7 +305,7 @@ def zaprequest(lud16: str, amount: int, content, zapped_event, zapped_user, keys if zapped_event is not None: tags.append(e_tag) zap_request = EventBuilder(Kind(9733), content, - tags).to_event(keys).as_json() + tags).sign_with_keys(keys).as_json() keys = Keys.parse(encryption_key) if zapped_event is not None: encrypted_content = enrypt_private_zap_message(zap_request, keys.secret_key(), zapped_event.author()) @@ -317,7 +317,7 @@ def zaprequest(lud16: str, amount: int, content, zapped_event, zapped_user, keys content = "" zap_request = EventBuilder(Kind(9734), content, - tags).to_event(keys).as_json() + tags).sign_with_keys(keys).as_json() response = requests.get(callback + "?amount=" + str(int(amount) * 1000) + "&nostr=" + urllib.parse.quote_plus( zap_request) + "&lnurl=" + encoded_lnurl) diff --git a/tests/db.py b/tests/db.py index 24e3dd0..1fea844 100644 --- a/tests/db.py +++ b/tests/db.py @@ -1,5 +1,5 @@ from threading import Thread -from nostr_sdk import Keys, Filter, ClientBuilder, NostrDatabase, NegentropyOptions, init_logger, LogLevel +from nostr_sdk import Keys, Filter, ClientBuilder, NostrDatabase, SyncOptions, init_logger, LogLevel init_logger(LogLevel.INFO) keys = Keys.parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85") print(keys.public_key().to_bech32()) @@ -22,8 +22,8 @@ async def reconcile_db(): # Negentropy reconciliation f = Filter().author(keys.public_key()) - opts = NegentropyOptions() - await client.reconcile(f, opts) + opts = SyncOptions() + await client.sync(f, opts) await do_some_work() diff --git a/tests/ditto.py b/tests/ditto.py index 351d584..dd80ba2 100644 --- a/tests/ditto.py +++ b/tests/ditto.py @@ -16,10 +16,8 @@ async def main(): "relay": "wss://gleasonator.dev/relay" } - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=5))) keys = Keys.parse(check_and_set_private_key("test_client")) - signer = NostrSigner.keys(keys) - cli = Client.with_opts(signer, opts) + cli = Client(keys) await cli.add_relay(options["relay"]) await cli.connect() @@ -29,14 +27,16 @@ async def main(): authors = [PublicKey.parse("db0e60d10b9555a39050c258d460c5c461f6d18f467aa9f62de1a728b8a891a4")] notes_filter = Filter().authors(authors).custom_tag(SingleLetterTag.lowercase(Alphabet.L), ltags) - events = await cli.get_events_of([notes_filter], relay_timeout_long) + events_struct = await cli.fetch_events([notes_filter], relay_timeout_long) + events = events_struct.to_vec() + result_list = [] if len(events) > 0: event = events[0] print(event) result_list = [] - for tag in event.tags(): + for tag in event.tags().to_vec(): print(tag.as_vec()) if tag.as_vec()[0] == "e": diff --git a/tests/generic_dvm_autotopic_feed.py b/tests/generic_dvm_autotopic_feed.py index b602816..8d9af06 100644 --- a/tests/generic_dvm_autotopic_feed.py +++ b/tests/generic_dvm_autotopic_feed.py @@ -102,15 +102,11 @@ def playground(announce=False): options = dvm.set_options(request_form) sk = SecretKey.from_hex(dvm.dvm_config.PRIVATE_KEY) keys = Keys.parse(sk.to_hex()) - signer = NostrSigner.keys(keys) - relaylimits = RelayLimits.disable() - opts = ( - Options().wait_for_send(False).send_timeout(timedelta(seconds=dvm.dvm_config.RELAY_TIMEOUT))).relay_limits( - relaylimits) + opts = (Options().relay_limits(relaylimits)) - cli = Client.with_opts(signer, opts) + cli = Client.with_opts(keys, opts) for relay in dvm.dvm_config.RELAY_LIST: await cli.add_relay(relay) # ropts = RelayOptions().ping(False) @@ -122,10 +118,9 @@ def playground(announce=False): print(options["request_event_author"]) filterauth = Filter().kind(definitions.EventDefinitions.KIND_NOTE).author(author).limit(100) - evts = await cli.get_events_of([filterauth], relay_timeout) - + event_struct = await cli.fetch_events([filterauth], relay_timeout) text = "" - for event in evts: + for event in event_struct.to_vec(): text = text + event.content() + ";" diff --git a/tests/otherstuff.py b/tests/otherstuff.py new file mode 100644 index 0000000..b7d1491 --- /dev/null +++ b/tests/otherstuff.py @@ -0,0 +1,445 @@ +import asyncio +import json +import os +import threading +from pathlib import Path + +import dotenv +from nostr_sdk import Keys, LogLevel, init_logger + +from nostr_dvm.bot import Bot +from nostr_dvm.tasks.convert_media import MediaConverter +from nostr_dvm.tasks.discovery_bot_farms import DiscoveryBotFarms +from nostr_dvm.tasks.discovery_censor_wot import DiscoverReports +from nostr_dvm.tasks.discovery_inactive_follows import DiscoverInactiveFollows +from nostr_dvm.tasks.imagegeneration_openai_dalle import ImageGenerationDALLE +from nostr_dvm.tasks.imagegeneration_replicate import ImageGenerationReplicate +from nostr_dvm.tasks.imagegeneration_replicate_fluxpro import ImageGenerationReplicateFluxPro +from nostr_dvm.tasks.imagegeneration_replicate_recraft import ImageGenerationReplicateRecraft +from nostr_dvm.tasks.imagegeneration_sd35_api import ImageGenerationSD35 +from nostr_dvm.tasks.videogeneration_replicate_svd import VideoGenerationReplicateSVD +from nostr_dvm.utils.admin_utils import AdminConfig +from nostr_dvm.utils.dvmconfig import build_default_config, DVMConfig +from nostr_dvm.utils.nip89_utils import NIP89Config, check_and_set_d_tag +from nostr_dvm.utils.nostr_utils import check_and_set_private_key +from nostr_dvm.utils.zap_utils import get_price_per_sat, check_and_set_ln_bits_keys + + +# Some other DVMs to run. + +use_logger = True +log_level = LogLevel.ERROR + + +if use_logger: + init_logger(log_level) + +def build_sd35(name, identifier, announce): + dvm_config = build_default_config(identifier) + + dvm_config.NEW_USER_BALANCE = 0 + dvm_config.USE_OWN_VENV = False + dvm_config.ENABLE_NUTZAP = False + profit_in_sats = 10 + dvm_config.FIX_COST = int(((4.0 / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + nip89info = { + "name": name, + "image": "https://i.nostr.build/NOXcCIPmOZrDTK35.jpg", + "about": "I draw images using Stable diffusion ultra", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "negative_prompt": { + "required": False, + "values": [] + }, + "ratio": { + "required": False, + "values": ["1:1", "5:4", "3:2", "16:9","21:9", "9:21", "9:16", "2:3", "4:5"] + } + } + } + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, + nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + aconfig = AdminConfig() + aconfig.REBROADCAST_NIP89 = announce # We add an optional AdminConfig for this one, and tell the dvm to rebroadcast its NIP89 + aconfig.REBROADCAST_NIP65_RELAY_LIST = announce + aconfig.LUD16 = dvm_config.LN_ADDRESS + aconfig.PRIVKEY = dvm_config.PRIVATE_KEY + aconfig.MELT_ON_STARTUP = False # set this to true to melt cashu tokens to our ln address on startup + + + options= {"API_KEY": os.getenv("STABILITY_KEY")} + + + return ImageGenerationSD35(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=aconfig, options=options) + +def build_dalle(name, identifier, announce): + dvm_config = build_default_config(identifier) + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + dvm_config.NEW_USER_BALANCE = 0 + dvm_config.USE_OWN_VENV = False + profit_in_sats = 10 + dvm_config.FIX_COST = int(((4.0 / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + + + nip89info = { + "name": name, + "image": "https://image.nostr.build/22f2267ca9d4ee9d5e8a0c7818a9fa325bbbcdac5573a60a2d163e699bb69923.jpg", + "about": "I create Images bridging OpenAI's DALL·E 3", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "size": { + "required": False, + "values": ["1024:1024", "1024x1792", "1792x1024"] + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, + nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + # We add an optional AdminConfig for this one, and tell the dvm to rebroadcast its NIP89 + return ImageGenerationDALLE(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config) + +def build_svd(name, identifier, announce): + dvm_config = build_default_config(identifier) + dvm_config.USE_OWN_VENV = False + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + profit_in_sats = 10 + cost_in_cent = 4.0 + dvm_config.FIX_COST = int(((cost_in_cent / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + + nip89info = { + "name": name, + "image": "https://image.nostr.build/c33ca6fc4cc038ca4adb46fdfdfda34951656f87ee364ef59095bae1495ce669.jpg", + "about": "I use Stable Video Diffusion to create short videos", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": {} + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, + nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + # We add an optional AdminConfig for this one, and tell the dvm to rebroadcast its NIP89 + return VideoGenerationReplicateSVD(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + + +def build_media_converter(name, identifier, announce): + dvm_config = build_default_config(identifier) + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + nip89info = { + "name": name, + "image": "https://cdn.nostr.build/i/a177be1159da5aad8396a1188f686728d55647d3a7371549584daf2b5e50eec9.jpg", + "about": "I convert videos from urls to given output format.", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "media_format": { + "required": False, + "values": ["video/mp4", "audio/mp3"] + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + return MediaConverter(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + + +def build_inactive_follows_finder(name, identifier, announce): + dvm_config = build_default_config(identifier) + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + dvm_config.USE_OWN_VENV = False + dvm_config.FIX_COST = 0 + + # Add NIP89 + nip89info = { + "name": name, + "image": "https://image.nostr.build/50621bbf8082c478bc06a06684e1c443b5d37f1362ad56d679cab7328e0481db.jpg", + "about": "I discover npubs you follow, but that have been inactive on Nostr for the last 90 days", + "action": "unfollow", + "cashuAccepted": True, + "nip90Params": { + "user": { + "required": False, + "values": [], + "description": "Do the task for another user" + }, + "since_days": { + "required": False, + "values": [], + "description": "The number of days a user has not been active to be considered inactive" + + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, + nip89info["image"]) + + nip89config.CONTENT = json.dumps(nip89info) + return DiscoverInactiveFollows(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + +def build_1984(name, identifier, announce): + dvm_config = build_default_config(identifier) + dvm_config.USE_OWN_VENV = False + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + # Add NIP89 + nip89info = { + "name": name, + "image": "https://image.nostr.build/19872a2edd866258fa9eab137631efda89310d52b2c6ea8f99ef057325aa1c7b.jpg", + "about": "I show users that have been reported by either your followers or your Web of Trust. Note: Anyone can report, so you might double check and decide for yourself who to mute. Considers spam, illegal and impersonation reports. Notice: This works with NIP51 mute lists. Not all clients support the new mute list format.", + "encryptionSupported": True, + "cashuAccepted": True, + "action": "mute", # follow, unfollow, mute, unmute + "nip90Params": { + "since_days": { + "required": False, + "values": [], + "description": "The number of days a report is ago in order to be considered " + } + } + } + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + return DiscoverReports(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + +def build_botfarms(name, identifier, announce): + dvm_config = build_default_config(identifier) + dvm_config.USE_OWN_VENV = False + dvm_config.SHOWLOG = True + dvm_config.SCHEDULE_UPDATES_SECONDS = 600 # Every 10 seconds + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + # Add NIP89 + nip89info = { + "name": name, + "image": "https://image.nostr.build/981b560820bc283c58de7989b7abc6664996b487a531d852e4ef7322586a2122.jpg", + "about": "I hunt down bot farms.", + "encryptionSupported": True, + "cashuAccepted": True, + "action": "mute", # follow, unfollow, mute, unmute + "nip90Params": { + "max_results": { + "required": False, + "values": [], + "description": "The number of maximum results to return (default currently 20)" + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + options = {"relay": "wss://relay.damus.io"} + + return DiscoveryBotFarms(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config, options=options) + +def build_replicate(name, identifier, model, announce): + dvm_config = build_default_config(identifier) + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + + profit_in_sats = 10 + dvm_config.FIX_COST = int(((4.0 / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + + nip89info = { + "name": name, + "image": "https://i.nostr.build/qnoBIN4jSkfF8IHk.png", + "about": "I use Replicate to run StableDiffusion XL", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "size": { + "required": False, + "values": ["1024:1024", "1024x1792", "1792x1024"] + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + opts = {"model": model} + + return ImageGenerationReplicate(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config, options=opts) + + +def build_replicate_recraft(name, identifier, announce): + dvm_config = build_default_config(identifier) + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + + profit_in_sats = 10 + dvm_config.FIX_COST = int(((4.0 / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + + nip89info = { + "name": name, + "image": "https://i.nostr.build/jSbrXvYglXCzSeAc.jpg", + "about": "I use Replicate to run Recraft v3", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "size": { + "required": False, + "values": ["1024:1024"] + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + + return ImageGenerationReplicateRecraft(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + +def build_replicate_fluxpro(name, identifier, announce): + dvm_config = build_default_config(identifier) + admin_config = AdminConfig() + admin_config.LUD16 = dvm_config.LN_ADDRESS + admin_config.REBROADCAST_NIP89 = announce + admin_config.REBROADCAST_NIP65_RELAY_LIST = announce + + profit_in_sats = 10 + dvm_config.FIX_COST = int(((4.0 / (get_price_per_sat("USD") * 100)) + profit_in_sats)) + + nip89info = { + "name": name, + "image": "https://i.nostr.build/AQTujqzVmLxLmG16.jpg", + "about": "I use Replicate to FluxPro 1.1.", + "encryptionSupported": True, + "cashuAccepted": True, + "nip90Params": { + "size": { + "required": False, + "values": ["5:4"] + } + } + } + + nip89config = NIP89Config() + nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) + nip89config.CONTENT = json.dumps(nip89info) + + + return ImageGenerationReplicateFluxPro(name=name, dvm_config=dvm_config, nip89config=nip89config, + admin_config=admin_config) + + +def playground(announce=False): + #bot_config = DVMConfig() + bot_config = build_default_config("bot") + #bot_config.PRIVATE_KEY = check_and_set_private_key("bot") + #npub = Keys.parse(bot_config.PRIVATE_KEY).public_key().to_bech32() + #invoice_key, admin_key, wallet_id, lnaddress = check_and_set_ln_bits_keys("bot",npub) + #bot_config.LNBITS_INVOICE_KEY = invoice_key + #bot_config.LNBITS_ADMIN_KEY = admin_key # The dvm might pay failed jobs back
bot_config.LNBITS_URL = os.getenv("LNBITS_HOST") + + if os.getenv("OPENAI_API_KEY") is not None and os.getenv("OPENAI_API_KEY") != "": + dalle = build_dalle("Dall-E 3", "dalle3", announce) + bot_config.SUPPORTED_DVMS.append(dalle) + dalle.run() + if os.getenv("STABILITY_KEY") is not None and os.getenv("STABILITY_KEY") != "": + sd35 = build_sd35("Stable Diffusion Ultra", "sd35", announce) + sd35.run() + + if os.getenv("REPLICATE_API_TOKEN") is not None and os.getenv("REPLICATE_API_TOKEN") != "": + model = "stability-ai/stable-diffusion-3.5-large" + sd3replicate = build_replicate("Stable Diffusion 3.5 Large", "replicate_svd", model, announce) + bot_config.SUPPORTED_DVMS.append(sd3replicate) + sd3replicate.run() + + model = "black-forest-labs/flux-1.1-pro" + fluxreplicate = build_replicate_fluxpro("Flux 1.1. Pro", "fluxpro", announce) + bot_config.SUPPORTED_DVMS.append(fluxreplicate) + fluxreplicate.run() + + recraftreplicate = build_replicate_recraft("Recraft v3", "recraftsvg", announce) + bot_config.SUPPORTED_DVMS.append(recraftreplicate) + recraftreplicate.run() + + + media_bringer = build_media_converter("Nostr AI DVM Media Converter", "media_converter", announce) + #bot_config.SUPPORTED_DVMS.append(media_bringer) + media_bringer.run() + + + discover_inactive = build_inactive_follows_finder("Those who left", "discovery_inactive_follows", announce) + bot_config.SUPPORTED_DVMS.append(discover_inactive) + discover_inactive.run() + + + discovery_censor = build_1984("Censorship 1984", "discovery_censor", announce) + #bot_config.SUPPORTED_DVMS.append(discovery_censor) + discovery_censor.run() + + + + #discovery_bots = build_botfarms("Bot Hunter", "discovery_botfarms", announce) + #bot_config.SUPPORTED_DVMS.append(discovery_bots) + #discovery_bots.run() + + + admin_config = AdminConfig() + #admin_config.REBROADCAST_NIP65_RELAY_LIST = True + x = threading.Thread(target=Bot, args=([bot_config, admin_config])) + x.start() + + +if __name__ == '__main__': + env_path = Path('.env') + if not env_path.is_file(): + with open('.env', 'w') as f: + print("Writing new .env file") + f.write('') + if env_path.is_file(): + print(f'loading environment from {env_path.resolve()}') + dotenv.load_dotenv(env_path, verbose=True, override=True) + else: + raise FileNotFoundError(f'.env file not found at {env_path} ') + announce = False + playground(announce) + diff --git a/tests/simplebot.py b/tests/simplebot.py index 33530d2..59ffe8d 100644 --- a/tests/simplebot.py +++ b/tests/simplebot.py @@ -20,8 +20,7 @@ async def test(): pk = keys.public_key() print(f"Bot public key: {pk.to_bech32()}") - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) await client.add_relay("wss://relay.damus.io") await client.add_relay("wss://nostr.mom") diff --git a/tests/test_dvm_client.py b/tests/test_dvm_client.py index d2fcffd..2dace67 100644 --- a/tests/test_dvm_client.py +++ b/tests/test_dvm_client.py @@ -19,7 +19,7 @@ async def nostr_client_test_translation(input, kind, lang, sats, satsmax): keys = Keys.parse(check_and_set_private_key("test_client")) if kind == "text": iTag = Tag.parse(["i", input, "text"]) - elif kind == "event": + else: iTag = Tag.parse(["i", input, "event"]) paramTag1 = Tag.parse(["param", "language", lang]) @@ -28,13 +28,12 @@ async def nostr_client_test_translation(input, kind, lang, sats, satsmax): "wss://nostr-pub.wellorder.net"]) alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task to translate a given Input"]) event = EventBuilder(EventDefinitions.KIND_NIP90_TRANSLATE_TEXT, str("Translate the given input."), - [iTag, paramTag1, bidTag, relaysTag, alttag]).to_event(keys) + [iTag, paramTag1, bidTag, relaysTag, alttag]).sign_with_keys(keys) relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", "wss://relayable.org", "wss://nostr-pub.wellorder.net"] - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) @@ -50,13 +49,12 @@ async def nostr_client_test_search_profile(input): iTag = Tag.parse(["i", input, "text"]) alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task to translate a given Input"]) event = EventBuilder(EventDefinitions.KIND_NIP90_USER_SEARCH, str("Search for user"), - [iTag, alttag]).to_event(keys) + [iTag, alttag]).sign_with_keys(keys) relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", "wss://relayable.org", "wss://nostr-pub.wellorder.net"] - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) @@ -77,10 +75,9 @@ async def nostr_client_test_image(prompt): relaysTag = Tag.parse(['relays', "wss://relay.primal.net", "wss://nostr.oxtr.dev"]) alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task to generate an Image from a given Input"]) event = EventBuilder(EventDefinitions.KIND_NIP90_GENERATE_IMAGE, str("Generate an Image."), - [iTag, outTag, paramTag1, bidTag, relaysTag, alttag]).to_event(keys) + [iTag, outTag, paramTag1, bidTag, relaysTag, alttag]).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in DVMConfig().RELAY_LIST: await client.add_relay(relay) await client.connect() @@ -106,10 +103,9 @@ async def nostr_client_test_censor_filter(users): tags.append(iTag) event = EventBuilder(EventDefinitions.KIND_NIP90_PEOPLE_DISCOVERY, str("Give me bad actors"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -132,10 +128,9 @@ async def nostr_client_test_inactive_filter(user): tags = [relaysTag, alttag, paramTag, paramTag2] event = EventBuilder(EventDefinitions.KIND_NIP90_PEOPLE_DISCOVERY, str("Give me inactive users"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.add_relay("wss://nostr.band") @@ -156,13 +151,12 @@ async def nostr_client_test_tts(prompt): "wss://nostr-pub.wellorder.net"]) alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task to generate TTSt"]) event = EventBuilder(EventDefinitions.KIND_NIP90_TEXT_TO_SPEECH, str("Generate an Audio File."), - [iTag, paramTag1, bidTag, relaysTag, alttag]).to_event(keys) + [iTag, paramTag1, bidTag, relaysTag, alttag]).sign_with_keys(keys) relay_list = ["wss://relay.damus.io", "wss://blastr.f7z.xyz", "wss://relayable.org" "wss://dvms.f7z.io", ] - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -185,13 +179,12 @@ async def nostr_client_test_discovery(user, ptag): tags = [relaysTag, alttag, paramTag, pTag] event = EventBuilder(EventDefinitions.KIND_NIP90_CONTENT_DISCOVERY, str("Give me content"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) - ropts = RelayOptions().ping(False) + await client.add_relay("wss://nostr.band") await client.connect() config = DVMConfig @@ -223,13 +216,11 @@ async def nostr_client_custom_discovery(user, ptag): tags = [relaysTag, alttag, paramTag, pTag]# paramTagSearch, paramTagMust, paramTagAvoid] event = EventBuilder(EventDefinitions.KIND_NIP90_CONTENT_DISCOVERY, str("Give me content"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) - ropts = RelayOptions().ping(False) await client.connect() config = DVMConfig @@ -251,13 +242,11 @@ async def nostr_client_generic_test(ptag): tags = [relaysTag, alttag, pTag] event = EventBuilder(Kind(5050), str("Give me content"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) - ropts = RelayOptions().ping(False) await client.connect() config = DVMConfig await send_event(event, client=client, dvm_config=config) @@ -279,13 +268,11 @@ async def nostr_client_duckduck_test(ptag, query): tags = [relaysTag, alttag, pTag, iTag] event = EventBuilder(Kind(5050), str("Give me content"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) - ropts = RelayOptions().ping(False) await client.connect() config = DVMConfig await send_event(event, client=client, dvm_config=config) @@ -305,10 +292,9 @@ async def nostr_client_flux_schnell(ptag, query): tags = [relaysTag, alttag, pTag, iTag] event = EventBuilder(Kind(5100), str("Give me image"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) ropts = RelayOptions().ping(False) @@ -334,10 +320,9 @@ async def nostr_client_test_discovery_user(user, ptag): tags = [relaysTag, alttag, paramTag, pTag] event = EventBuilder(EventDefinitions.KIND_NIP90_PEOPLE_DISCOVERY, str("Give me people"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -360,10 +345,9 @@ async def nostr_client_test_discovery_gallery(user, ptag): tags = [relaysTag, alttag, paramTag, pTag] event = EventBuilder(EventDefinitions.KIND_NIP90_VISUAL_DISCOVERY, str("Give me visuals"), - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -398,10 +382,9 @@ async def nostr_client_test_image_private(prompt, cashutoken): encrypted_tag = Tag.parse(['encrypted']) nip90request = EventBuilder(EventDefinitions.KIND_NIP90_GENERATE_IMAGE, encrypted_params, - [pTag, encrypted_tag]).to_event(keys) + [pTag, encrypted_tag]).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -415,8 +398,7 @@ async def nostr_client(): sk = keys.secret_key() pk = keys.public_key() print(f"Nostr Client public key: {pk.to_bech32()}, Hex: {pk.to_hex()} ") - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) dvmconfig = DVMConfig() for relay in dvmconfig.RELAY_LIST: @@ -488,7 +470,7 @@ async def nostr_client(): print("[Nostr Client]: " + event.as_json()) amount_sats = 0 status = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "amount": amount_sats = int(int(tag.as_vec()[1]) / 1000) # millisats if tag.as_vec()[0] == "status": diff --git a/tests/test_events.py b/tests/test_events.py index 2fb752e..77fd4a4 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -17,13 +17,7 @@ from nostr_dvm.utils.nostr_utils import check_and_set_private_key async def test(): relay_list = dvmconfig.DVMConfig.RELAY_LIST keys = Keys.parse(check_and_set_private_key("test_client")) - wait_for_send = False - skip_disconnected_relays = True - opts = (Options().wait_for_send(wait_for_send).send_timeout(timedelta(seconds=5)) - .skip_disconnected_relays(skip_disconnected_relays)) - - signer = NostrSigner.keys(keys) - client = Client.with_opts(signer, opts) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) @@ -61,7 +55,8 @@ async def test_referred_events(client, event_id, kinds=None): else: job_id_filter = Filter().event(EventId.from_hex(event_id)) - events = await client.get_events_of([job_id_filter], relay_timeout) + event_struct = await client.fetch_events([job_id_filter], relay_timeout) + events = event_struct.to_vec() if len(events) > 0: for event in events: @@ -75,13 +70,8 @@ async def test_referred_events(client, event_id, kinds=None): async def test_gallery(): relay_list = dvmconfig.DVMConfig.RELAY_LIST keys = Keys.parse(check_and_set_private_key("test_client")) - wait_for_send = False - skip_disconnected_relays = True - opts = (Options().wait_for_send(wait_for_send).send_timeout(timedelta(seconds=5)) - .skip_disconnected_relays(skip_disconnected_relays)) - signer = NostrSigner.keys(keys) - client = Client.with_opts(signer, opts) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) @@ -121,7 +111,7 @@ async def test_gallery(): # await gallery_announce_list(tags, dvm_config, client) #evt = EventBuilder.delete([EventId.parse("721ac7c7d9309b6d3e6728a7274f5a1f10096b4ab17068233bcfa05cb233e84a")], - # reason="deleted").to_event(keys) + # reason="deleted").sign_with_keys(keys) #await client.send_event(evt) #key1 = Keys.parse("3e99f38a8e8c59ff3683cdc0942e26471c1aae9b225eb34dd410cb9d6dde93a6") @@ -141,7 +131,8 @@ async def test_search_by_user_since_days(client, pubkey, days, prompt): since = Timestamp.from_secs(dif) filterts = Filter().search(prompt).author(pubkey).kinds([Kind(1)]).since(since) - events = await client.get_events_of([filterts], relay_timeout) + event_struct = await client.fetch_events([filterts], relay_timeout) + events = event_struct.to_vec() if len(events) > 0: for event in events: diff --git a/tests/wot.py b/tests/wot.py index 68f2bd9..3583522 100644 --- a/tests/wot.py +++ b/tests/wot.py @@ -14,7 +14,7 @@ from nostr_dvm.utils.definitions import relay_timeout warnings.filterwarnings('ignore') from nostr_sdk import Options, Keys, NostrSigner, Filter, PublicKey, Kind, \ - NegentropyOptions, NegentropyDirection, ClientBuilder, NostrDatabase + SyncOptions, SyncDirection, ClientBuilder, NostrDatabase # init_logger(LogLevel.INFO) @@ -26,17 +26,16 @@ async def getmetadata(npub): pk = PublicKey.parse(npub) except: return "", "", "" - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=5))) keys = Keys.parse("nsec1zmzllu40a7mr7ztl78uwfwslnp0pn0pww868adl05x52d4la237s6m8qfj") - signer = NostrSigner.keys(keys) - client = ClientBuilder().signer(signer).opts(opts).build() + client = ClientBuilder().signer(keys).build() await client.add_relay("wss://relay.damus.io") await client.add_relay("wss://relay.primal.net") await client.add_relay("wss://purplepag.es") await client.connect() profile_filter = Filter().kind(Kind(0)).author(pk).limit(1) - events = await client.get_events_of([profile_filter], relay_timeout) + event_struct = await client.fetch_events([profile_filter], relay_timeout) + events = event_struct.to_vec() if len(events) > 0: try: profile = json.loads(events[0].content()) @@ -53,11 +52,9 @@ async def getmetadata(npub): async def sync_db(): - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=5))) keys = Keys.parse("nsec1zmzllu40a7mr7ztl78uwfwslnp0pn0pww868adl05x52d4la237s6m8qfj") - signer = NostrSigner.keys(keys) database = NostrDatabase.lmdb("db/nostr_followlists.db") - cli = ClientBuilder().signer(signer).database(database).opts(opts).build() + cli = ClientBuilder().signer(keys).database(database).build() await cli.add_relay("wss://relay.damus.io") # TODO ADD MORE # await cli.add_relay("wss://relay.primal.net") # TODO ADD MORE @@ -67,8 +64,8 @@ async def sync_db(): # filter = Filter().author(keys.public_key()) print("Syncing Profile Database.. this might take a while..") - dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) - await cli.reconcile(filter1, dbopts) + dbopts = SyncOptions().direction(SyncDirection.DOWN) + await cli.sync(filter1, dbopts) print("Done Syncing Profile Database.") await cli.shutdown() @@ -92,7 +89,7 @@ async def analyse_users(user_ids=None): if len(followers) > 0: for follower in followers: frens = [] - for tag in follower.tags(): + for tag in follower.tags().to_vec(): if tag.as_vec()[0] == "p": frens.append(tag.as_vec()[1]) allfriends.append(Friend(follower.author().to_hex(), frens)) diff --git a/tutorials/03_client.py b/tutorials/03_client.py index 04bb667..d8951a5 100644 --- a/tutorials/03_client.py +++ b/tutorials/03_client.py @@ -36,11 +36,10 @@ async def nostr_client_generic_test(ptag): # We now send a 5050 Request (for Text Generation) with our tags. The content is optional. event = EventBuilder(Kind(5050), "This is a test", - tags).to_event(keys) + tags).sign_with_keys(keys) # We create a signer with some random keys - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) # We add the relays we defined above and told our DVM we would want to receive events to. for relay in relay_list: await client.add_relay(relay) @@ -58,8 +57,7 @@ async def nostr_client(target_dvm_npub): sk = keys.secret_key() pk = keys.public_key() print(f"Nostr Client public key: {pk.to_bech32()}, Hex: {pk.to_hex()} ") - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) dvmconfig = DVMConfig() for relay in dvmconfig.RELAY_LIST: @@ -90,7 +88,7 @@ async def nostr_client(target_dvm_npub): print(bcolors.YELLOW + "[Nostr Client]: " + event.content() + bcolors.ENDC) amount_sats = 0 status = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "amount": amount_sats = int(int(tag.as_vec()[1]) / 1000) # millisats if tag.as_vec()[0] == "status": diff --git a/tutorials/09_nutzap_client.py b/tutorials/09_nutzap_client.py index 788ae5d..69ec6f8 100644 --- a/tutorials/09_nutzap_client.py +++ b/tutorials/09_nutzap_client.py @@ -31,10 +31,9 @@ async def nostr_client_generic_test(ptag): pTag = Tag.parse(["p", PublicKey.parse(ptag).to_hex()]) tags = [relaysTag, alttag, pTag, paramTag] event = EventBuilder(Kind(5050), "This is a test", - tags).to_event(keys) + tags).sign_with_keys(keys) - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) for relay in relay_list: await client.add_relay(relay) await client.connect() @@ -47,8 +46,7 @@ async def nostr_client(target_dvm_npub): keys = Keys.parse(check_and_set_private_key("test_client")) pk = keys.public_key() print(f"Nostr Client public key: {pk.to_bech32()}, Hex: {pk.to_hex()} ") - signer = NostrSigner.keys(keys) - client = Client(signer) + client = Client(keys) dvmconfig = DVMConfig() for relay in dvmconfig.RELAY_LIST: @@ -74,7 +72,7 @@ async def nostr_client(target_dvm_npub): print(bcolors.YELLOW + "[Nostr Client]: " + event.content() + bcolors.ENDC) amount_sats = 0 status = "" - for tag in event.tags(): + for tag in event.tags().to_vec(): if tag.as_vec()[0] == "amount": amount_sats = int(int(tag.as_vec()[1]) / 1000) # millisats if tag.as_vec()[0] == "status":