From c26db736509ff415e6c79e15d4112b59709caa3e Mon Sep 17 00:00:00 2001 From: Believethehype <1097224+believethehype@users.noreply.github.com> Date: Fri, 31 May 2024 10:27:18 +0200 Subject: [PATCH] move set_options to class, improve print messages, colored print messages --- nostr_dvm/dvm.py | 48 +++--- nostr_dvm/interfaces/dvmtaskinterface.py | 8 +- nostr_dvm/tasks/advanced_search.py | 2 +- nostr_dvm/tasks/advanced_search_wine.py | 2 +- .../content_discovery_currently_popular.py | 35 +++-- ...discovery_currently_popular_by_top_zaps.py | 14 +- ...t_discovery_currently_popular_followers.py | 13 +- ...ntent_discovery_currently_popular_topic.py | 29 +--- nostr_dvm/tasks/convert_media.py | 2 +- nostr_dvm/tasks/discovery_bot_farms.py | 2 +- nostr_dvm/tasks/discovery_censor_wot.py | 2 +- nostr_dvm/tasks/discovery_inactive_follows.py | 2 +- nostr_dvm/tasks/discovery_nonfollowers.py | 2 +- .../discovery_trending_notes_nostrband.py | 2 +- .../tasks/imagegeneration_openai_dalle.py | 2 +- .../tasks/imagegeneration_replicate_sdxl.py | 2 +- nostr_dvm/tasks/imagegeneration_sd21_mlx.py | 2 +- nostr_dvm/tasks/search_users.py | 2 +- nostr_dvm/tasks/summarization_huggingchat.py | 2 +- .../tasks/summarization_unleashed_chat.py | 2 +- nostr_dvm/tasks/textextraction_google.py | 2 +- nostr_dvm/tasks/textextraction_pdf.py | 2 +- nostr_dvm/tasks/textgeneration_huggingchat.py | 2 +- nostr_dvm/tasks/textgeneration_llmlite.py | 2 +- .../tasks/textgeneration_unleashed_chat.py | 2 +- nostr_dvm/tasks/texttospeech.py | 2 +- nostr_dvm/tasks/translation_google.py | 2 +- nostr_dvm/tasks/translation_libretranslate.py | 2 +- .../tasks/videogeneration_replicate_svd.py | 2 +- nostr_dvm/utils/nip88_utils.py | 3 +- nostr_dvm/utils/nip89_utils.py | 5 +- nostr_dvm/utils/nostr_utils.py | 3 +- nostr_dvm/utils/print.py | 15 ++ setup.py | 4 +- tests/discovery.py | 141 +++++++++--------- 35 files changed, 188 insertions(+), 176 deletions(-) create mode 100644 nostr_dvm/utils/print.py diff --git a/nostr_dvm/dvm.py b/nostr_dvm/dvm.py index 32e922b..ebff816 100644 --- a/nostr_dvm/dvm.py +++ b/nostr_dvm/dvm.py @@ -22,6 +22,7 @@ from nostr_dvm.utils.output_utils import build_status_reaction from nostr_dvm.utils.zap_utils import check_bolt11_ln_bits_is_paid, create_bolt11_ln_bits, parse_zap_event_tags, \ parse_amount_from_bolt11_invoice, zaprequest, pay_bolt11_ln_bits, create_bolt11_lud16 from nostr_dvm.utils.cashu_utils import redeem_cashu +from nostr_dvm.utils.print import bcolors class DVM: @@ -47,9 +48,10 @@ class DVM: self.job_list = [] self.jobs_on_hold_list = [] pk = self.keys.public_key() - - print("Nostr DVM public key: " + str(pk.to_bech32()) + " Hex: " + str(pk.to_hex()) + " Supported DVM tasks: " + - ', '.join(p.NAME + ":" + p.TASK for p in self.dvm_config.SUPPORTED_DVMS) + "\n") + print(bcolors.GREEN + "[" + self.dvm_config.NIP89.NAME + "] " + "Nostr DVM public key: " + str( + pk.to_bech32()) + " Hex: " + + str(pk.to_hex()) + " Supported DVM tasks: " + + ', '.join(p.NAME + ":" + p.TASK for p in self.dvm_config.SUPPORTED_DVMS) + bcolors.ENDC) for relay in self.dvm_config.RELAY_LIST: self.client.add_relay(relay) @@ -88,7 +90,7 @@ class DVM: # if event is encrypted, but we can't decrypt it (e.g. because its directed to someone else), return if nip90_event is None: return - + task_is_free = False user_has_active_subscription = False cashu = "" @@ -104,7 +106,6 @@ class DVM: print("[" + self.dvm_config.NIP89.NAME + "] No public request, also not addressed to me.") return - # check if task is supported by the current DVM task_supported, task = check_task_is_supported(nip90_event, client=self.client, config=self.dvm_config) @@ -119,17 +120,16 @@ class DVM: print("[" + self.dvm_config.NIP89.NAME + "] Request by blacklisted user, skipped") return - print("[" + self.dvm_config.NIP89.NAME + "] Received new Request: " + task + " from " + user.name) + print(bcolors.MAGENTA + "[" + self.dvm_config.NIP89.NAME + "] Received new Request: " + task + " from " + user.name + bcolors.ENDC) duration = input_data_file_duration(nip90_event, dvm_config=self.dvm_config, client=self.client) amount = get_amount_per_task(task, self.dvm_config, duration) if amount is None: return - # If this is a subscription DVM and the Task is directed to us, check for active subscription if dvm_config.NIP88 is not None and p_tag_str == self.dvm_config.PUBLIC_KEY: send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, - "Checking Subscription Status, please wait..",self.dvm_config) + "Checking Subscription Status, please wait..", self.dvm_config) # if we stored in the database that the user has an active subscription, we don't need to check it print("User Subscription: " + str(user.subscribed) + " Current time: " + str( Timestamp.now().as_secs())) @@ -139,7 +139,8 @@ class DVM: user_has_active_subscription = True send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, "User subscripton active until " + - Timestamp.from_secs(int(user.subscribed)).to_human_datetime().replace("Z", " ").replace("T", " ") + " GMT", self.dvm_config) + Timestamp.from_secs(int(user.subscribed)).to_human_datetime().replace( + "Z", " ").replace("T", " ") + " GMT", self.dvm_config) # otherwise we check for an active subscription by checking recipie events else: print("[" + self.dvm_config.NIP89.NAME + "] Checking Subscription status") @@ -153,7 +154,11 @@ class DVM: if subscription_status["isActive"]: send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, - "User subscripton active until " + Timestamp.from_secs(int(subscription_status["validUntil"])).to_human_datetime().replace("Z", " ").replace("T", " ") + " GMT", + "User subscripton active until " + Timestamp.from_secs(int( + subscription_status[ + "validUntil"])).to_human_datetime().replace("Z", + " ").replace( + "T", " ") + " GMT", self.dvm_config) print("Checked Recipe: User subscribed until: " + str( Timestamp.from_secs(int(subscription_status["validUntil"])).to_human_datetime())) @@ -349,12 +354,12 @@ class DVM: # update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client, # config=self.dvm_config) - # a regular note + # a regular note elif not anon and dvm_config.NIP88 is None: print("[" + self.dvm_config.NIP89.NAME + "] Profile Zap received for DVM balance: " + str(invoice_amount) + " Sats from " + str(user.name)) - # update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client, - # config=self.dvm_config) + # update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client, + # config=self.dvm_config) except Exception as e: print("[" + self.dvm_config.NIP89.NAME + "] Error during content decryption: " + str(e)) @@ -472,8 +477,9 @@ class DVM: self.keys) send_event(reply_event, client=self.client, dvm_config=self.dvm_config) - print("[" + self.dvm_config.NIP89.NAME + "] " + str( - original_event.kind().as_u64() + 1000) + " Job Response event sent: " + reply_event.as_json()) + + print(bcolors.GREEN + "[" + self.dvm_config.NIP89.NAME + "] " + str( + original_event.kind().as_u64() + 1000) + " Job Response event sent: " + reply_event.as_json() + bcolors.ENDC) def send_job_status_reaction(original_event, status, is_paid=True, amount=0, client=None, content=None, @@ -503,7 +509,6 @@ class DVM: else: reply_tags.append(p_tag) - if status == "success" or status == "error": # for x in self.job_list: if x.event == original_event: @@ -572,8 +577,9 @@ class DVM: keys = Keys.parse(dvm_config.PRIVATE_KEY) reaction_event = EventBuilder(EventDefinitions.KIND_FEEDBACK, str(content), reply_tags).to_event(keys) 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_u64()) + " Reaction: " + status + " " + reaction_event.as_json()) + + print(bcolors.YELLOW + "[" + self.dvm_config.NIP89.NAME + "]" + " Sent Kind " + str( + EventDefinitions.KIND_FEEDBACK.as_u64()) + " Reaction: " + status + " " + reaction_event.as_json() + bcolors.ENDC) return reaction_event.as_json() def do_work(job_event, amount): @@ -618,11 +624,13 @@ class DVM: post_processed = dvm.post_process(result, job_event) send_nostr_reply_event(post_processed, job_event.as_json()) except Exception as e: - print(e) + print(bcolors.RED + "[" + self.dvm_config.NIP89.NAME + "] Error: " + str(e) + bcolors.ENDC) send_job_status_reaction(job_event, "error", content=str(e), dvm_config=self.dvm_config) except Exception as e: - print(e) + print( + bcolors.RED + "[" + self.dvm_config.NIP89.NAME + "] Error: " + str(e) + bcolors.ENDC) + # we could send the exception here to the user, but maybe that's not a good idea after all. send_job_status_reaction(job_event, "error", content=result, dvm_config=self.dvm_config) diff --git a/nostr_dvm/interfaces/dvmtaskinterface.py b/nostr_dvm/interfaces/dvmtaskinterface.py index 0be20f6..db89544 100644 --- a/nostr_dvm/interfaces/dvmtaskinterface.py +++ b/nostr_dvm/interfaces/dvmtaskinterface.py @@ -123,13 +123,13 @@ class DVMTaskInterface: """Post-process the data and return the result Use default function, if not overwritten""" return post_process_result(result, event) - @staticmethod - def set_options(request_form): - print("Setting options...") + def set_options(self, request_form): + + print("[" + self.dvm_config.NIP89.NAME + "] " + "Setting options...") opts = [] if request_form.get("options"): opts = json.loads(request_form["options"]) - print(opts) + print("[" + self.dvm_config.NIP89.NAME + "] " + str(opts)) return dict(opts) @staticmethod diff --git a/nostr_dvm/tasks/advanced_search.py b/nostr_dvm/tasks/advanced_search.py index 5a04963..a86c8cd 100644 --- a/nostr_dvm/tasks/advanced_search.py +++ b/nostr_dvm/tasks/advanced_search.py @@ -87,7 +87,7 @@ class AdvancedSearch(DVMTaskInterface): def process(self, request_form): from nostr_sdk import Filter - options = DVMTaskInterface.set_options(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) diff --git a/nostr_dvm/tasks/advanced_search_wine.py b/nostr_dvm/tasks/advanced_search_wine.py index 076647e..f1089f9 100644 --- a/nostr_dvm/tasks/advanced_search_wine.py +++ b/nostr_dvm/tasks/advanced_search_wine.py @@ -89,7 +89,7 @@ class AdvancedSearchWine(DVMTaskInterface): def process(self, request_form): from nostr_sdk import Filter - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) userkeys = [] for user in options["users"]: tag = Tag.parse(user) diff --git a/nostr_dvm/tasks/content_discovery_currently_popular.py b/nostr_dvm/tasks/content_discovery_currently_popular.py index 2093435..79ad904 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular.py @@ -58,7 +58,6 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): if self.logger: init_logger(LogLevel.DEBUG) - if self.dvm_config.UPDATE_DATABASE: self.sync_db() @@ -76,7 +75,6 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): def create_request_from_nostr_event(self, event, client=None, dvm_config=None): self.dvm_config = dvm_config - print(self.dvm_config.PRIVATE_KEY) request_form = {"jobID": event.id().to_hex()} @@ -111,13 +109,11 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): from types import SimpleNamespace ns = SimpleNamespace() - options = DVMTaskInterface.set_options(request_form) - + options = self.set_options(request_form) database = NostrDatabase.sqlite(self.db_name) cli = ClientBuilder().database(database).build() - # Negentropy reconciliation # Query events from database timestamp_hour_ago = Timestamp.now().as_secs() - self.db_since @@ -125,6 +121,8 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).since(since) events = cli.database().query([filter1]) + print("[" + self.dvm_config.NIP89.NAME + "] Considering " + str(len(events)) + " Events") + ns.finallist = {} for event in events: if event.created_at().as_secs() > timestamp_hour_ago: @@ -138,7 +136,6 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): result_list = [] finallist_sorted = sorted(ns.finallist.items(), key=lambda x: x[1], reverse=True)[:int(options["max_results"])] for entry in finallist_sorted: - # print(EventId.parse(entry[0]).to_bech32() + "/" + EventId.parse(entry[0]).to_hex() + ": " + str(entry[1])) e_tag = Tag.parse(["e", entry[0]]) result_list.append(e_tag.as_vec()) @@ -167,7 +164,7 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): try: self.result = self.calculate_result(self.request_form) except Exception as e: - print("EXCEPTION: "+ e) + print("EXCEPTION: " + str(e)) return 1 def sync_db(self): @@ -191,21 +188,22 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface): definitions.EventDefinitions.KIND_ZAP]).since(lasthour) # Notes, reactions, zaps # filter = Filter().author(keys.public_key()) - print("[" + self.dvm_config.IDENTIFIER + "] Syncing notes of the last " + str( + 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) cli.reconcile(filter1, dbopts) - database.delete(Filter().until(Timestamp.from_secs( - Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesnt get too full. + filter_delete = Filter().until(Timestamp.from_secs(Timestamp.now().as_secs() - self.db_since)) + database.delete(filter_delete) # Clear old events so db doesn't get too full. print( - "[" + self.dvm_config.IDENTIFIER + "] Done Syncing Notes of the last " + str(self.db_since) + " seconds..") + "[" + self.dvm_config.NIP89.NAME + "] Done Syncing Notes of the last " + str(self.db_since) + " seconds..") # 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, options, cost=0, update_rate=180, processing_msg=None, update_db=True): +def build_example(name, identifier, admin_config, options, cost=0, update_rate=180, processing_msg=None, + update_db=True): dvm_config = build_default_config(identifier) dvm_config.USE_OWN_VENV = False dvm_config.SHOWLOG = True @@ -244,14 +242,15 @@ def build_example(name, identifier, admin_config, options, cost=0, update_rate= nip89config.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"]) nip89config.CONTENT = json.dumps(nip89info) - #admin_config.UPDATE_PROFILE = False - #admin_config.REBROADCAST_NIP89 = False + # admin_config.UPDATE_PROFILE = False + # admin_config.REBROADCAST_NIP89 = False return DicoverContentCurrentlyPopular(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config, options=options) -def build_example_subscription(name, identifier, admin_config, options, update_rate=180, processing_msg=None, update_db=True): +def build_example_subscription(name, identifier, admin_config, options, update_rate=180, processing_msg=None, + update_db=True): dvm_config = build_default_config(identifier) dvm_config.USE_OWN_VENV = False dvm_config.SHOWLOG = True @@ -301,9 +300,9 @@ def build_example_subscription(name, identifier, admin_config, options, update_r nip88config.PERK2DESC = "Support NostrDVM & NostrSDK development" nip88config.PAYMENT_VERIFIER_PUBKEY = "5b5c045ecdf66fb540bdf2049fe0ef7f1a566fa427a4fe50d400a011b65a3a7e" - #admin_config.UPDATE_PROFILE = False - #admin_config.REBROADCAST_NIP89 = False - #admin_config.REBROADCAST_NIP88 = False + # admin_config.UPDATE_PROFILE = False + # admin_config.REBROADCAST_NIP89 = False + # admin_config.REBROADCAST_NIP88 = False # admin_config.FETCH_NIP88 = True # admin_config.EVENTID = "" 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 a73fda5..b5b0acd 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 @@ -58,7 +58,6 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): if self.logger: init_logger(LogLevel.DEBUG) - print("UPDATEDB: " + str(self.dvm_config.UPDATE_DATABASE)) if self.dvm_config.UPDATE_DATABASE: self.sync_db() @@ -76,7 +75,6 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): def create_request_from_nostr_event(self, event, client=None, dvm_config=None): self.dvm_config = dvm_config - print(self.dvm_config.PRIVATE_KEY) request_form = {"jobID": event.id().to_hex()} @@ -110,7 +108,7 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): from types import SimpleNamespace ns = SimpleNamespace() - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) database = NostrDatabase.sqlite(self.db_name) cli = ClientBuilder().database(database).build() @@ -122,6 +120,8 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).since(since) events = cli.database().query([filter1]) + print("[" + self.dvm_config.NIP89.NAME + "] Considering " + str(len(events)) + " Events") + ns.finallist = {} for event in events: if event.created_at().as_secs() > timestamp_hour_ago: @@ -198,15 +198,15 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface): definitions.EventDefinitions.KIND_ZAP]).since(lasthour) # Notes, reactions, zaps # filter = Filter().author(keys.public_key()) - print("[" + self.dvm_config.IDENTIFIER + "] Syncing notes of the last " + str( + 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) cli.reconcile(filter1, dbopts) - database.delete(Filter().until(Timestamp.from_secs( - Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesnt get too full. + filter_delete = Filter().until(Timestamp.from_secs(Timestamp.now().as_secs() - self.db_since)) + database.delete(filter_delete) # Clear old events so db doesn't get too full. print( - "[" + self.dvm_config.IDENTIFIER + "] Done Syncing Notes of the last " + str(self.db_since) + " seconds..") + "[" + self.dvm_config.NIP89.NAME + "] Done Syncing Notes of the last " + str(self.db_since) + " seconds..") # We build an example here that we can call by either calling this file directly from the main directory, diff --git a/nostr_dvm/tasks/content_discovery_currently_popular_followers.py b/nostr_dvm/tasks/content_discovery_currently_popular_followers.py index 6f0c555..21f3775 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular_followers.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular_followers.py @@ -65,7 +65,6 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): def create_request_from_nostr_event(self, event: Event, client=None, dvm_config=None): self.dvm_config = dvm_config - print(self.dvm_config.PRIVATE_KEY) request_form = {"jobID": event.id().to_hex()} @@ -95,7 +94,7 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): from types import SimpleNamespace ns = SimpleNamespace() - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) relaylimits = RelayLimits.disable() opts = ( @@ -143,6 +142,7 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).authors(followings).since(since) events = cli.database().query([filter1]) + print("[" + self.dvm_config.NIP89.NAME + "] Considering " + str(len(events)) + " Events") ns.finallist = {} for event in events: @@ -207,15 +207,14 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface): definitions.EventDefinitions.KIND_ZAP]).since(lasthour) # Notes, reactions, zaps # filter = Filter().author(keys.public_key()) - print("[" + self.dvm_config.IDENTIFIER + "] Syncing notes of the last " + str( + 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) cli.reconcile(filter1, dbopts) - database.delete(Filter().until(Timestamp.from_secs( - Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesnt get too full. - + filter_delete = Filter().until(Timestamp.from_secs(Timestamp.now().as_secs() - self.db_since)) + database.delete(filter_delete) # Clear old events so db doesn't get too full. print( - "[" + self.dvm_config.IDENTIFIER + "] Done Syncing Notes of the last " + str(self.db_since) + " seconds..") + "[" + self.dvm_config.NIP89.NAME + "] Done Syncing Notes of the last " + str(self.db_since) + " seconds..") # We build an example here that we can call by either calling this file directly from the main directory, diff --git a/nostr_dvm/tasks/content_discovery_currently_popular_topic.py b/nostr_dvm/tasks/content_discovery_currently_popular_topic.py index 9a348c7..16aaada 100644 --- a/nostr_dvm/tasks/content_discovery_currently_popular_topic.py +++ b/nostr_dvm/tasks/content_discovery_currently_popular_topic.py @@ -89,8 +89,6 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): def create_request_from_nostr_event(self, event, client=None, dvm_config=None): self.dvm_config = dvm_config - print(self.dvm_config.PRIVATE_KEY) - request_form = {"jobID": event.id().to_hex()} # default values @@ -135,28 +133,18 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): from types import SimpleNamespace ns = SimpleNamespace() - options = DVMTaskInterface.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) + options = self.set_options(request_form) database = NostrDatabase.sqlite(self.db_name) cli = ClientBuilder().database(database).build() - - # cli.add_relay("wss://relay.damus.io") - # cli.connect() - - # Negentropy reconciliation - # Query events from database timestamp_since = Timestamp.now().as_secs() - self.db_since since = Timestamp.from_secs(timestamp_since) filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).since(since) events = cli.database().query([filter1]) - print(len(events)) + print("[" + self.dvm_config.NIP89.NAME + "] Considering " + str(len(events)) + " Events") + ns.final_list = {} for event in events: @@ -197,7 +185,7 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): return 1 def sync_db(self): - opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT))) + opts = (Options().wait_for_send(True).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) @@ -207,7 +195,6 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): cli.add_relay("wss://relay.damus.io") cli.add_relay("wss://nostr.oxtr.dev") cli.add_relay("wss://nostr21.com") - cli.connect() timestamp_since = Timestamp.now().as_secs() - self.db_since @@ -217,15 +204,15 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface): EventDefinitions.KIND_LONGFORM]).since(since) # Notes, reactions, zaps # filter = Filter().author(keys.public_key()) - print("[" + self.dvm_config.IDENTIFIER + "] Syncing notes of the last " + str( + 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) cli.reconcile(filter1, dbopts) - database.delete(Filter().until(Timestamp.from_secs( - Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. + filter_delete = Filter().until(Timestamp.from_secs(Timestamp.now().as_secs() - self.db_since)) + database.delete(filter_delete) # Clear old events so db doesn't get too full. print( - "[" + self.dvm_config.IDENTIFIER + "] Done Syncing Notes of the last " + str(self.db_since) + " seconds..") + "[" + self.dvm_config.NIP89.NAME + "] Done Syncing Notes of the last " + str(self.db_since) + " seconds..") # We build an example here that we can call by either calling this file directly from the main directory, diff --git a/nostr_dvm/tasks/convert_media.py b/nostr_dvm/tasks/convert_media.py index 9671756..f4c3b2e 100644 --- a/nostr_dvm/tasks/convert_media.py +++ b/nostr_dvm/tasks/convert_media.py @@ -73,7 +73,7 @@ class MediaConverter(DVMTaskInterface): return request_form def process(self, request_form): - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) url = upload_media_to_hoster(options["filepath"]) return url diff --git a/nostr_dvm/tasks/discovery_bot_farms.py b/nostr_dvm/tasks/discovery_bot_farms.py index 7bd62bc..133e641 100644 --- a/nostr_dvm/tasks/discovery_bot_farms.py +++ b/nostr_dvm/tasks/discovery_bot_farms.py @@ -77,7 +77,7 @@ class DiscoveryBotFarms(DVMTaskInterface): def process(self, request_form): from nostr_sdk import Filter - options = DVMTaskInterface.set_options(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) diff --git a/nostr_dvm/tasks/discovery_censor_wot.py b/nostr_dvm/tasks/discovery_censor_wot.py index a4c975d..d51d78a 100644 --- a/nostr_dvm/tasks/discovery_censor_wot.py +++ b/nostr_dvm/tasks/discovery_censor_wot.py @@ -89,7 +89,7 @@ class DiscoverReports(DVMTaskInterface): cli.connect() - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) step = 20 pubkeys = [] diff --git a/nostr_dvm/tasks/discovery_inactive_follows.py b/nostr_dvm/tasks/discovery_inactive_follows.py index 6ab55bc..93a3293 100644 --- a/nostr_dvm/tasks/discovery_inactive_follows.py +++ b/nostr_dvm/tasks/discovery_inactive_follows.py @@ -88,7 +88,7 @@ class DiscoverInactiveFollows(DVMTaskInterface): cli.connect() - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) step = 20 followers_filter = Filter().author(PublicKey.parse(options["user"])).kind(Kind(3)) diff --git a/nostr_dvm/tasks/discovery_nonfollowers.py b/nostr_dvm/tasks/discovery_nonfollowers.py index df0bb84..a0a4abf 100644 --- a/nostr_dvm/tasks/discovery_nonfollowers.py +++ b/nostr_dvm/tasks/discovery_nonfollowers.py @@ -78,7 +78,7 @@ class DiscoverNonFollowers(DVMTaskInterface): cli.connect() - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) step = 20 followers_filter = Filter().author(PublicKey.from_hex(options["user"])).kind(Kind(3)) diff --git a/nostr_dvm/tasks/discovery_trending_notes_nostrband.py b/nostr_dvm/tasks/discovery_trending_notes_nostrband.py index 7958df3..9c1c85e 100644 --- a/nostr_dvm/tasks/discovery_trending_notes_nostrband.py +++ b/nostr_dvm/tasks/discovery_trending_notes_nostrband.py @@ -68,7 +68,7 @@ class TrendingNotesNostrBand(DVMTaskInterface): return request_form def process(self, request_form): - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) import requests diff --git a/nostr_dvm/tasks/imagegeneration_openai_dalle.py b/nostr_dvm/tasks/imagegeneration_openai_dalle.py index 9ac9a95..00f31fd 100644 --- a/nostr_dvm/tasks/imagegeneration_openai_dalle.py +++ b/nostr_dvm/tasks/imagegeneration_openai_dalle.py @@ -96,7 +96,7 @@ class ImageGenerationDALLE(DVMTaskInterface): def process(self, request_form): try: - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) from openai import OpenAI client = OpenAI() diff --git a/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py b/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py index 3077fd6..41a18be 100644 --- a/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py +++ b/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py @@ -93,7 +93,7 @@ class ImageGenerationReplicateSDXL(DVMTaskInterface): def process(self, request_form): try: - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) import replicate width = int(options["size"].split("x")[0]) diff --git a/nostr_dvm/tasks/imagegeneration_sd21_mlx.py b/nostr_dvm/tasks/imagegeneration_sd21_mlx.py index e49fe79..8c8e160 100644 --- a/nostr_dvm/tasks/imagegeneration_sd21_mlx.py +++ b/nostr_dvm/tasks/imagegeneration_sd21_mlx.py @@ -99,7 +99,7 @@ class ImageGenerationMLX(DVMTaskInterface): try: import mlx.core as mx from nostr_dvm.backends.mlx.modules.stable_diffusion import StableDiffusion - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) sd = StableDiffusion() cfg_weight = 7.5 diff --git a/nostr_dvm/tasks/search_users.py b/nostr_dvm/tasks/search_users.py index 5d3ee76..b4b39cf 100644 --- a/nostr_dvm/tasks/search_users.py +++ b/nostr_dvm/tasks/search_users.py @@ -78,7 +78,7 @@ class SearchUser(DVMTaskInterface): def process(self, request_form): from nostr_sdk import Filter - options = DVMTaskInterface.set_options(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) diff --git a/nostr_dvm/tasks/summarization_huggingchat.py b/nostr_dvm/tasks/summarization_huggingchat.py index 00585e2..718cd9e 100644 --- a/nostr_dvm/tasks/summarization_huggingchat.py +++ b/nostr_dvm/tasks/summarization_huggingchat.py @@ -104,7 +104,7 @@ class TextSummarizationHuggingChat(DVMTaskInterface): cookies = sign.login() sign.saveCookiesToDir(cookie_path_dir) - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) try: chatbot = hugchat.ChatBot(cookies=cookies.get_dict()) # or cookie_path="usercookies/.json" diff --git a/nostr_dvm/tasks/summarization_unleashed_chat.py b/nostr_dvm/tasks/summarization_unleashed_chat.py index e9e5345..b6c2861 100644 --- a/nostr_dvm/tasks/summarization_unleashed_chat.py +++ b/nostr_dvm/tasks/summarization_unleashed_chat.py @@ -97,7 +97,7 @@ class SummarizationUnleashedChat(DVMTaskInterface): from openai import OpenAI temp_open_ai_api_key = os.environ["OPENAI_API_KEY"] os.environ["OPENAI_API_KEY"] = os.getenv("UNLEASHED_API_KEY") - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) try: client = OpenAI( diff --git a/nostr_dvm/tasks/textextraction_google.py b/nostr_dvm/tasks/textextraction_google.py index e737288..b36f466 100644 --- a/nostr_dvm/tasks/textextraction_google.py +++ b/nostr_dvm/tasks/textextraction_google.py @@ -112,7 +112,7 @@ class SpeechToTextGoogle(DVMTaskInterface): api_key = self.options['api_key'] else: api_key = None - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) # Speech recognition instance asr = sr.Recognizer() with sr.AudioFile(options["filepath"]) as source: diff --git a/nostr_dvm/tasks/textextraction_pdf.py b/nostr_dvm/tasks/textextraction_pdf.py index 5a830dd..4ffde17 100644 --- a/nostr_dvm/tasks/textextraction_pdf.py +++ b/nostr_dvm/tasks/textextraction_pdf.py @@ -74,7 +74,7 @@ class TextExtractionPDF(DVMTaskInterface): from pathlib import Path import requests - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) try: file_path = Path('temp.pdf') diff --git a/nostr_dvm/tasks/textgeneration_huggingchat.py b/nostr_dvm/tasks/textgeneration_huggingchat.py index 0776f85..c7c5702 100644 --- a/nostr_dvm/tasks/textgeneration_huggingchat.py +++ b/nostr_dvm/tasks/textgeneration_huggingchat.py @@ -71,7 +71,7 @@ class TextGenerationHuggingChat(DVMTaskInterface): sign.saveCookiesToDir(cookie_path_dir) - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) try: chatbot = hugchat.ChatBot(cookies=cookies.get_dict()) # or cookie_path="usercookies/.json" diff --git a/nostr_dvm/tasks/textgeneration_llmlite.py b/nostr_dvm/tasks/textgeneration_llmlite.py index e6ff667..9f202fb 100644 --- a/nostr_dvm/tasks/textgeneration_llmlite.py +++ b/nostr_dvm/tasks/textgeneration_llmlite.py @@ -71,7 +71,7 @@ class TextGenerationLLMLite(DVMTaskInterface): def process(self, request_form): from litellm import completion - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) try: if options["model"].startswith("ollama"): diff --git a/nostr_dvm/tasks/textgeneration_unleashed_chat.py b/nostr_dvm/tasks/textgeneration_unleashed_chat.py index 8cee96e..2d3b958 100644 --- a/nostr_dvm/tasks/textgeneration_unleashed_chat.py +++ b/nostr_dvm/tasks/textgeneration_unleashed_chat.py @@ -64,7 +64,7 @@ class TextGenerationUnleashedChat(DVMTaskInterface): from openai import OpenAI temp_open_ai_api_key = os.environ["OPENAI_API_KEY"] os.environ["OPENAI_API_KEY"] = os.getenv("UNLEASHED_API_KEY") - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) try: client = OpenAI( diff --git a/nostr_dvm/tasks/texttospeech.py b/nostr_dvm/tasks/texttospeech.py index e5e22d2..3e5132c 100644 --- a/nostr_dvm/tasks/texttospeech.py +++ b/nostr_dvm/tasks/texttospeech.py @@ -106,7 +106,7 @@ class TextToSpeech(DVMTaskInterface): def process(self, request_form): import torch from TTS.api import TTS - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) device = "cuda" if torch.cuda.is_available() else "cpu" # else "mps" if torch.backends.mps.is_available() \ diff --git a/nostr_dvm/tasks/translation_google.py b/nostr_dvm/tasks/translation_google.py index e37764b..1c00fec 100644 --- a/nostr_dvm/tasks/translation_google.py +++ b/nostr_dvm/tasks/translation_google.py @@ -80,7 +80,7 @@ class TranslationGoogle(DVMTaskInterface): def process(self, request_form): from translatepy.translators.google import GoogleTranslate - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) gtranslate = GoogleTranslate() length = len(options["text"]) diff --git a/nostr_dvm/tasks/translation_libretranslate.py b/nostr_dvm/tasks/translation_libretranslate.py index 65d42d3..19e8229 100644 --- a/nostr_dvm/tasks/translation_libretranslate.py +++ b/nostr_dvm/tasks/translation_libretranslate.py @@ -78,7 +78,7 @@ class TranslationLibre(DVMTaskInterface): return request_form def process(self, request_form): - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) request = { "q": options["text"], "source": "auto", diff --git a/nostr_dvm/tasks/videogeneration_replicate_svd.py b/nostr_dvm/tasks/videogeneration_replicate_svd.py index 5624958..fecc8bd 100644 --- a/nostr_dvm/tasks/videogeneration_replicate_svd.py +++ b/nostr_dvm/tasks/videogeneration_replicate_svd.py @@ -81,7 +81,7 @@ class VideoGenerationReplicateSVD(DVMTaskInterface): def process(self, request_form): try: - options = DVMTaskInterface.set_options(request_form) + options = self.set_options(request_form) print(options["url"]) response = requests.get(options["url"]) image = Image.open(BytesIO(response.content)).convert("RGB") diff --git a/nostr_dvm/utils/nip88_utils.py b/nostr_dvm/utils/nip88_utils.py index 6628803..3483db2 100644 --- a/nostr_dvm/utils/nip88_utils.py +++ b/nostr_dvm/utils/nip88_utils.py @@ -177,7 +177,8 @@ def nip88_announce_tier(dvm_config, client): event = EventBuilder(EventDefinitions.KIND_NIP88_TIER_EVENT, content, tags).to_event(keys) annotier_id = send_event(event, client=client, dvm_config=dvm_config) - print("Announced NIP 88 Tier for " + dvm_config.NIP89.NAME) + print("[" + dvm_config.NAME + "] Announced NIP 88 Tier for " + dvm_config.NIP89.NAME) + return annotier_id # Relay and payment-verification diff --git a/nostr_dvm/utils/nip89_utils.py b/nostr_dvm/utils/nip89_utils.py index a81999b..c478110 100644 --- a/nostr_dvm/utils/nip89_utils.py +++ b/nostr_dvm/utils/nip89_utils.py @@ -8,6 +8,7 @@ from nostr_sdk import Tag, Keys, EventBuilder, Filter, Alphabet, PublicKey, Clie from nostr_dvm.utils.definitions import EventDefinitions from nostr_dvm.utils.nostr_utils import send_event +from nostr_dvm.utils.print import bcolors class NIP89Config: @@ -31,7 +32,9 @@ def nip89_announce_tasks(dvm_config, client): content = dvm_config.NIP89.CONTENT event = EventBuilder(EventDefinitions.KIND_ANNOUNCEMENT, content, [k_tag, d_tag]).to_event(keys) send_event(event, client=client, dvm_config=dvm_config) - print("Announced NIP 89 for " + dvm_config.NIP89.NAME) + + print(bcolors.BLUE + "[" + dvm_config.NIP89.NAME + "] Announced NIP 89 for " + dvm_config.NIP89.NAME + bcolors.ENDC) + def fetch_nip89_parameters_for_deletion(keys, eventid, client, dvmconfig, pow=False): diff --git a/nostr_dvm/utils/nostr_utils.py b/nostr_dvm/utils/nostr_utils.py index b3304b4..47f2b6d 100644 --- a/nostr_dvm/utils/nostr_utils.py +++ b/nostr_dvm/utils/nostr_utils.py @@ -211,8 +211,7 @@ def update_profile(dvm_config, client, lud16=""): .set_lud16(lud16) \ .set_nip05(lud16) # .set_banner("https://example.com/banner.png") \ - - print(f"Setting profile metadata for {keys.public_key().to_bech32()}...") + print("[" + dvm_config.NIP89.NAME + "] Setting profile metadata for " + keys.public_key().to_bech32() + "...") print(metadata.as_json()) client.set_metadata(metadata) diff --git a/nostr_dvm/utils/print.py b/nostr_dvm/utils/print.py new file mode 100644 index 0000000..9087344 --- /dev/null +++ b/nostr_dvm/utils/print.py @@ -0,0 +1,15 @@ +class bcolors: + HEADER = '\033[95m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + RED = '\033[91m' + GREEN = '\033[92m' + BLUE = '\033[94m' + CYAN = '\033[96m' + WHITE = '\033[97m' + YELLOW = '\033[93m' + MAGENTA = '\033[95m' + GREY = '\033[90m' + BLACK = '\033[90m' + DEFAULT = '\033[99m' \ No newline at end of file diff --git a/setup.py b/setup.py index 879c84c..9f072cc 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -VERSION = '0.5.1' +VERSION = '0.5.2' DESCRIPTION = 'A framework to build and run Nostr NIP90 Data Vending Machines' LONG_DESCRIPTION = ('A framework to build and run Nostr NIP90 Data Vending Machines. See the github repository for more information') @@ -13,7 +13,7 @@ setup( description=DESCRIPTION, long_description=LONG_DESCRIPTION, packages=find_packages(include=['nostr_dvm', 'nostr_dvm.*']), -#nostr-sdk==0.13.0a2.dev0 + install_requires=["nostr-sdk==0.12.0", "bech32", "pycryptodome==3.20.0", diff --git a/tests/discovery.py b/tests/discovery.py index 4267a38..8af0dbf 100644 --- a/tests/discovery.py +++ b/tests/discovery.py @@ -231,76 +231,6 @@ def playground(): custom_processing_msg=custom_processing_msg) trending_nb.run() - # Popular top zapped - admin_config_top_zaps = AdminConfig() - admin_config_top_zaps.REBROADCAST_NIP89 = rebbroadcast_NIP89 - admin_config_top_zaps.UPDATE_PROFILE = False - custom_processing_msg = ["Looking for most zapped notes", "Let's see which notes people currently zap..", - "Let's find valuable notes. #value4value"] - update_db = False - - options_top_zapped = { - "db_name": "db/nostr_recent_notes.db", - "db_since": 60 * 60 * 4, # 4h since gmt, - } - cost = 0 - image = "https://image.nostr.build/c6879f458252641d04d0aa65fd7f1e005a4f7362fd407467306edc2f4acdb113.jpg" - discovery_topzaps = build_example_top_zapped("Top Zapped notes", - "discovery_content_top_zaps", - admin_config=admin_config_top_zaps, - options=options_top_zapped, - image=image, - cost=cost, - update_rate=global_update_rate, - processing_msg=custom_processing_msg, - update_db=update_db) - - discovery_topzaps.run() - - # Popular Garden&Plants - admin_config_plants = AdminConfig() - admin_config_plants.REBROADCAST_NIP89 = rebbroadcast_NIP89 - admin_config_plants.UPDATE_PROFILE = False - # admin_config_plants.DELETE_NIP89 = True - # admin_config_plants.PRIVKEY = "430bacf525a2f6efd6db1f049eb7c04e0c0314182ef1c17df39f46fe66416ddf" - # admin_config_plants.EVENTID = "f42adb15f4c67b884d58b09084907d94471d1a54185dce0217a69111c703aa14" - # admin_config_plants.POW = True - options_plants = { - "search_list": ["garden", "gardening", "nature", " plants ", " plant ", " herb ", " herbs " " pine ", - "homesteading", "rosemary", "chicken", "🪻", "🌿", "☘️", "🌲", "flower", "forest", "watering", - "permies", "planting", "farm", "vegetable", "fruit", " grass ", "sunshine", - "#flowerstr", "#bloomscrolling", "#treestr", "#plantstr", "touchgrass", ], - "avoid_list": ["porn", "smoke", "nsfw", "bitcoin", "bolt12", "bolt11", "github", "currency", "utxo", - "encryption", "government", "airpod", "ipad", "iphone", "android", "warren", - "moderna", "pfizer", "corona", "socialism", - "murder", "tax", "engagement", "hodlers", "hodl", "gdp", "global markets", "crypto", "wherostr", - "presidency", "dollar", "asset", "microsoft", "amazon", "billionaire", "ceo", "industry", - "white house", "blocks", "streaming", "summary", "wealth", "beef", "cunt", "nigger", "business", - "retail", "bakery", "synth", "slaughterhouse", "hamas", "dog days", "ww3", "socialmedia", - "nintendo", "signature", "deepfake", "congressman", "cypherpunk", "minister", "dissentwatch", - "inkblot", "covid", "robot", "pandemic", "bethesda", "zap farming", " defi ", " minister ", - "nostr-hotter-site", " ai ", "palestine", "https://boards.4chan", "https://techcrunch.com", - "https://screenrant.com"], - "db_name": "db/nostr_recent_notes.db", - "db_since": 12 * 60 * 60, # 12h since gmt - "personalized": False, - "logger": False} - - image = "https://image.nostr.build/a816f3f5e98e91e8a47d50f4cd7a2c17545f556d9bb0a6086a659b9abdf7ab68.jpg" - description = "I show recent notes about plants and gardening" - custom_processing_msg = ["Finding the best notes for you.. #blooming", "Looking for some positivity.. #touchgrass", - "Looking for #goodvibes..", "All I do is #blooming.."] - update_db = False - cost = 0 - discovery_test_sub = build_example_topic("Garden & Growth", "discovery_content_garden", - admin_config_plants, options_plants, - image=image, - description=description, - update_rate=global_update_rate, - cost=cost, - processing_msg=custom_processing_msg, - update_db=update_db) - discovery_test_sub.run() # Popular Animals (Fluffy frens) admin_config_animals = AdminConfig() @@ -358,6 +288,77 @@ def playground(): discovery_animals.run() + # Popular Garden&Plants + admin_config_plants = AdminConfig() + admin_config_plants.REBROADCAST_NIP89 = rebbroadcast_NIP89 + admin_config_plants.UPDATE_PROFILE = False + # admin_config_plants.DELETE_NIP89 = True + # admin_config_plants.PRIVKEY = "430bacf525a2f6efd6db1f049eb7c04e0c0314182ef1c17df39f46fe66416ddf" + # admin_config_plants.EVENTID = "f42adb15f4c67b884d58b09084907d94471d1a54185dce0217a69111c703aa14" + # admin_config_plants.POW = True + options_plants = { + "search_list": ["garden", "gardening", "nature", " plants ", " plant ", " herb ", " herbs " " pine ", + "homesteading", "rosemary", "chicken", "🪻", "🌿", "☘️", "🌲", "flower", "forest", "watering", + "permies", "planting", "farm", "vegetable", "fruit", " grass ", "sunshine", + "#flowerstr", "#bloomscrolling", "#treestr", "#plantstr", "touchgrass", ], + "avoid_list": ["porn", "smoke", "nsfw", "bitcoin", "bolt12", "bolt11", "github", "currency", "utxo", + "encryption", "government", "airpod", "ipad", "iphone", "android", "warren", + "moderna", "pfizer", "corona", "socialism", + "murder", "tax", "engagement", "hodlers", "hodl", "gdp", "global markets", "crypto", "wherostr", + "presidency", "dollar", "asset", "microsoft", "amazon", "billionaire", "ceo", "industry", + "white house", "blocks", "streaming", "summary", "wealth", "beef", "cunt", "nigger", "business", + "retail", "bakery", "synth", "slaughterhouse", "hamas", "dog days", "ww3", "socialmedia", + "nintendo", "signature", "deepfake", "congressman", "cypherpunk", "minister", "dissentwatch", + "inkblot", "covid", "robot", "pandemic", "bethesda", "zap farming", " defi ", " minister ", + "nostr-hotter-site", " ai ", "palestine", "https://boards.4chan", "https://techcrunch.com", + "https://screenrant.com"], + "db_name": "db/nostr_recent_notes.db", + "db_since": 12 * 60 * 60, # 12h since gmt + "personalized": False, + "logger": False} + + image = "https://image.nostr.build/a816f3f5e98e91e8a47d50f4cd7a2c17545f556d9bb0a6086a659b9abdf7ab68.jpg" + description = "I show recent notes about plants and gardening" + custom_processing_msg = ["Finding the best notes for you.. #blooming", "Looking for some positivity.. #touchgrass", + "Looking for #goodvibes..", "All I do is #blooming.."] + update_db = False + cost = 0 + discovery_test_sub = build_example_topic("Garden & Growth", "discovery_content_garden", + admin_config_plants, options_plants, + image=image, + description=description, + update_rate=global_update_rate, + cost=cost, + processing_msg=custom_processing_msg, + update_db=update_db) + discovery_test_sub.run() + + # Popular top zapped + admin_config_top_zaps = AdminConfig() + admin_config_top_zaps.REBROADCAST_NIP89 = rebbroadcast_NIP89 + admin_config_top_zaps.UPDATE_PROFILE = False + custom_processing_msg = ["Looking for most zapped notes", "Let's see which notes people currently zap..", + "Let's find valuable notes. #value4value"] + update_db = False + + options_top_zapped = { + "db_name": "db/nostr_recent_notes.db", + "db_since": 60 * 60 * 4, # 4h since gmt, + } + cost = 0 + image = "https://image.nostr.build/c6879f458252641d04d0aa65fd7f1e005a4f7362fd407467306edc2f4acdb113.jpg" + discovery_topzaps = build_example_top_zapped("Top Zapped notes", + "discovery_content_top_zaps", + admin_config=admin_config_top_zaps, + options=options_top_zapped, + image=image, + cost=cost, + update_rate=global_update_rate, + processing_msg=custom_processing_msg, + update_db=update_db) + + discovery_topzaps.run() + # Popular Followers admin_config_followers = AdminConfig() admin_config_followers.REBROADCAST_NIP89 = rebbroadcast_NIP89