move set_options to class, improve print messages, colored print messages

This commit is contained in:
Believethehype
2024-05-31 10:27:18 +02:00
parent b8cd322150
commit c26db73650
35 changed files with 188 additions and 176 deletions

View File

@@ -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, \ 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 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.cashu_utils import redeem_cashu
from nostr_dvm.utils.print import bcolors
class DVM: class DVM:
@@ -47,9 +48,10 @@ class DVM:
self.job_list = [] self.job_list = []
self.jobs_on_hold_list = [] self.jobs_on_hold_list = []
pk = self.keys.public_key() pk = self.keys.public_key()
print(bcolors.GREEN + "[" + self.dvm_config.NIP89.NAME + "] " + "Nostr DVM public key: " + str(
print("Nostr DVM public key: " + str(pk.to_bech32()) + " Hex: " + str(pk.to_hex()) + " Supported DVM tasks: " + pk.to_bech32()) + " Hex: " +
', '.join(p.NAME + ":" + p.TASK for p in self.dvm_config.SUPPORTED_DVMS) + "\n") 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: for relay in self.dvm_config.RELAY_LIST:
self.client.add_relay(relay) 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 event is encrypted, but we can't decrypt it (e.g. because its directed to someone else), return
if nip90_event is None: if nip90_event is None:
return return
task_is_free = False task_is_free = False
user_has_active_subscription = False user_has_active_subscription = False
cashu = "" cashu = ""
@@ -104,7 +106,6 @@ class DVM:
print("[" + self.dvm_config.NIP89.NAME + "] No public request, also not addressed to me.") print("[" + self.dvm_config.NIP89.NAME + "] No public request, also not addressed to me.")
return return
# check if task is supported by the current DVM # check if task is supported by the current DVM
task_supported, task = check_task_is_supported(nip90_event, client=self.client, task_supported, task = check_task_is_supported(nip90_event, client=self.client,
config=self.dvm_config) config=self.dvm_config)
@@ -119,17 +120,16 @@ class DVM:
print("[" + self.dvm_config.NIP89.NAME + "] Request by blacklisted user, skipped") print("[" + self.dvm_config.NIP89.NAME + "] Request by blacklisted user, skipped")
return 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) 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) amount = get_amount_per_task(task, self.dvm_config, duration)
if amount is None: if amount is None:
return return
# If this is a subscription DVM and the Task is directed to us, check for active subscription # If this is a subscription DVM and the Task is directed to us, check for active subscription
if dvm_config.NIP88 is not None and p_tag_str == self.dvm_config.PUBLIC_KEY: if dvm_config.NIP88 is not None and p_tag_str == self.dvm_config.PUBLIC_KEY:
send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client,
"Checking Subscription Status, please wait..",self.dvm_config) "Checking Subscription Status, please wait..", self.dvm_config)
# if we stored in the database that the user has an active subscription, we don't need to check it # if we stored in the database that the user has an active subscription, we don't need to check it
print("User Subscription: " + str(user.subscribed) + " Current time: " + str( print("User Subscription: " + str(user.subscribed) + " Current time: " + str(
Timestamp.now().as_secs())) Timestamp.now().as_secs()))
@@ -139,7 +139,8 @@ class DVM:
user_has_active_subscription = True user_has_active_subscription = True
send_job_status_reaction(nip90_event, "subscription-required", True, amount, send_job_status_reaction(nip90_event, "subscription-required", True, amount,
self.client, "User subscripton active until " + self.client, "User subscripton active until " +
Timestamp.from_secs(int(user.subscribed)).to_human_datetime().replace("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 # otherwise we check for an active subscription by checking recipie events
else: else:
print("[" + self.dvm_config.NIP89.NAME + "] Checking Subscription status") print("[" + self.dvm_config.NIP89.NAME + "] Checking Subscription status")
@@ -153,7 +154,11 @@ class DVM:
if subscription_status["isActive"]: if subscription_status["isActive"]:
send_job_status_reaction(nip90_event, "subscription-required", True, amount, self.client, 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) self.dvm_config)
print("Checked Recipe: User subscribed until: " + str( print("Checked Recipe: User subscribed until: " + str(
Timestamp.from_secs(int(subscription_status["validUntil"])).to_human_datetime())) Timestamp.from_secs(int(subscription_status["validUntil"])).to_human_datetime()))
@@ -349,12 +354,12 @@ class DVM:
# update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client, # update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client,
# config=self.dvm_config) # config=self.dvm_config)
# a regular note # a regular note
elif not anon and dvm_config.NIP88 is None: elif not anon and dvm_config.NIP88 is None:
print("[" + self.dvm_config.NIP89.NAME + "] Profile Zap received for DVM balance: " + print("[" + self.dvm_config.NIP89.NAME + "] Profile Zap received for DVM balance: " +
str(invoice_amount) + " Sats from " + str(user.name)) str(invoice_amount) + " Sats from " + str(user.name))
# update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client, # update_user_balance(self.dvm_config.DB, sender, invoice_amount, client=self.client,
# config=self.dvm_config) # config=self.dvm_config)
except Exception as e: except Exception as e:
print("[" + self.dvm_config.NIP89.NAME + "] Error during content decryption: " + str(e)) print("[" + self.dvm_config.NIP89.NAME + "] Error during content decryption: " + str(e))
@@ -472,8 +477,9 @@ class DVM:
self.keys) self.keys)
send_event(reply_event, client=self.client, dvm_config=self.dvm_config) 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, def send_job_status_reaction(original_event, status, is_paid=True, amount=0, client=None,
content=None, content=None,
@@ -503,7 +509,6 @@ class DVM:
else: else:
reply_tags.append(p_tag) reply_tags.append(p_tag)
if status == "success" or status == "error": # if status == "success" or status == "error": #
for x in self.job_list: for x in self.job_list:
if x.event == original_event: if x.event == original_event:
@@ -572,8 +577,9 @@ class DVM:
keys = Keys.parse(dvm_config.PRIVATE_KEY) 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).to_event(keys)
send_event(reaction_event, client=self.client, dvm_config=self.dvm_config) 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() return reaction_event.as_json()
def do_work(job_event, amount): def do_work(job_event, amount):
@@ -618,11 +624,13 @@ class DVM:
post_processed = dvm.post_process(result, job_event) post_processed = dvm.post_process(result, job_event)
send_nostr_reply_event(post_processed, job_event.as_json()) send_nostr_reply_event(post_processed, job_event.as_json())
except Exception as e: 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), send_job_status_reaction(job_event, "error", content=str(e),
dvm_config=self.dvm_config) dvm_config=self.dvm_config)
except Exception as e: except Exception as e:
print(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. # 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, send_job_status_reaction(job_event, "error", content=result,
dvm_config=self.dvm_config) dvm_config=self.dvm_config)

View File

@@ -123,13 +123,13 @@ class DVMTaskInterface:
"""Post-process the data and return the result Use default function, if not overwritten""" """Post-process the data and return the result Use default function, if not overwritten"""
return post_process_result(result, event) return post_process_result(result, event)
@staticmethod def set_options(self, request_form):
def set_options(request_form):
print("Setting options...") print("[" + self.dvm_config.NIP89.NAME + "] " + "Setting options...")
opts = [] opts = []
if request_form.get("options"): if request_form.get("options"):
opts = json.loads(request_form["options"]) opts = json.loads(request_form["options"])
print(opts) print("[" + self.dvm_config.NIP89.NAME + "] " + str(opts))
return dict(opts) return dict(opts)
@staticmethod @staticmethod

View File

@@ -87,7 +87,7 @@ class AdvancedSearch(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
from nostr_sdk import Filter 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))) opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)))
sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY)

View File

@@ -89,7 +89,7 @@ class AdvancedSearchWine(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
from nostr_sdk import Filter from nostr_sdk import Filter
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
userkeys = [] userkeys = []
for user in options["users"]: for user in options["users"]:
tag = Tag.parse(user) tag = Tag.parse(user)

View File

@@ -58,7 +58,6 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface):
if self.logger: if self.logger:
init_logger(LogLevel.DEBUG) init_logger(LogLevel.DEBUG)
if self.dvm_config.UPDATE_DATABASE: if self.dvm_config.UPDATE_DATABASE:
self.sync_db() self.sync_db()
@@ -76,7 +75,6 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface):
def create_request_from_nostr_event(self, event, client=None, dvm_config=None): def create_request_from_nostr_event(self, event, client=None, dvm_config=None):
self.dvm_config = dvm_config self.dvm_config = dvm_config
print(self.dvm_config.PRIVATE_KEY)
request_form = {"jobID": event.id().to_hex()} request_form = {"jobID": event.id().to_hex()}
@@ -111,13 +109,11 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface):
from types import SimpleNamespace from types import SimpleNamespace
ns = SimpleNamespace() ns = SimpleNamespace()
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
database = NostrDatabase.sqlite(self.db_name) database = NostrDatabase.sqlite(self.db_name)
cli = ClientBuilder().database(database).build() cli = ClientBuilder().database(database).build()
# Negentropy reconciliation # Negentropy reconciliation
# Query events from database # Query events from database
timestamp_hour_ago = Timestamp.now().as_secs() - self.db_since 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) filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).since(since)
events = cli.database().query([filter1]) events = cli.database().query([filter1])
print("[" + self.dvm_config.NIP89.NAME + "] Considering " + str(len(events)) + " Events")
ns.finallist = {} ns.finallist = {}
for event in events: for event in events:
if event.created_at().as_secs() > timestamp_hour_ago: if event.created_at().as_secs() > timestamp_hour_ago:
@@ -138,7 +136,6 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface):
result_list = [] result_list = []
finallist_sorted = sorted(ns.finallist.items(), key=lambda x: x[1], reverse=True)[:int(options["max_results"])] finallist_sorted = sorted(ns.finallist.items(), key=lambda x: x[1], reverse=True)[:int(options["max_results"])]
for entry in finallist_sorted: 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]]) e_tag = Tag.parse(["e", entry[0]])
result_list.append(e_tag.as_vec()) result_list.append(e_tag.as_vec())
@@ -167,7 +164,7 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface):
try: try:
self.result = self.calculate_result(self.request_form) self.result = self.calculate_result(self.request_form)
except Exception as e: except Exception as e:
print("EXCEPTION: "+ e) print("EXCEPTION: " + str(e))
return 1 return 1
def sync_db(self): def sync_db(self):
@@ -191,21 +188,22 @@ class DicoverContentCurrentlyPopular(DVMTaskInterface):
definitions.EventDefinitions.KIND_ZAP]).since(lasthour) # Notes, reactions, zaps definitions.EventDefinitions.KIND_ZAP]).since(lasthour) # Notes, reactions, zaps
# filter = Filter().author(keys.public_key()) # 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..") self.db_since) + " seconds.. this might take a while..")
dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN)
cli.reconcile(filter1, dbopts) cli.reconcile(filter1, dbopts)
database.delete(Filter().until(Timestamp.from_secs( filter_delete = Filter().until(Timestamp.from_secs(Timestamp.now().as_secs() - self.db_since))
Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesnt get too full. database.delete(filter_delete) # Clear old events so db doesn't get too full.
print( 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, # 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 # 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 # 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 = build_default_config(identifier)
dvm_config.USE_OWN_VENV = False dvm_config.USE_OWN_VENV = False
dvm_config.SHOWLOG = True 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.DTAG = check_and_set_d_tag(identifier, name, dvm_config.PRIVATE_KEY, nip89info["image"])
nip89config.CONTENT = json.dumps(nip89info) nip89config.CONTENT = json.dumps(nip89info)
#admin_config.UPDATE_PROFILE = False # admin_config.UPDATE_PROFILE = False
#admin_config.REBROADCAST_NIP89 = False # admin_config.REBROADCAST_NIP89 = False
return DicoverContentCurrentlyPopular(name=name, dvm_config=dvm_config, nip89config=nip89config, return DicoverContentCurrentlyPopular(name=name, dvm_config=dvm_config, nip89config=nip89config,
admin_config=admin_config, options=options) 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 = build_default_config(identifier)
dvm_config.USE_OWN_VENV = False dvm_config.USE_OWN_VENV = False
dvm_config.SHOWLOG = True 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.PERK2DESC = "Support NostrDVM & NostrSDK development"
nip88config.PAYMENT_VERIFIER_PUBKEY = "5b5c045ecdf66fb540bdf2049fe0ef7f1a566fa427a4fe50d400a011b65a3a7e" nip88config.PAYMENT_VERIFIER_PUBKEY = "5b5c045ecdf66fb540bdf2049fe0ef7f1a566fa427a4fe50d400a011b65a3a7e"
#admin_config.UPDATE_PROFILE = False # admin_config.UPDATE_PROFILE = False
#admin_config.REBROADCAST_NIP89 = False # admin_config.REBROADCAST_NIP89 = False
#admin_config.REBROADCAST_NIP88 = False # admin_config.REBROADCAST_NIP88 = False
# admin_config.FETCH_NIP88 = True # admin_config.FETCH_NIP88 = True
# admin_config.EVENTID = "" # admin_config.EVENTID = ""

View File

@@ -58,7 +58,6 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface):
if self.logger: if self.logger:
init_logger(LogLevel.DEBUG) init_logger(LogLevel.DEBUG)
print("UPDATEDB: " + str(self.dvm_config.UPDATE_DATABASE))
if self.dvm_config.UPDATE_DATABASE: if self.dvm_config.UPDATE_DATABASE:
self.sync_db() self.sync_db()
@@ -76,7 +75,6 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface):
def create_request_from_nostr_event(self, event, client=None, dvm_config=None): def create_request_from_nostr_event(self, event, client=None, dvm_config=None):
self.dvm_config = dvm_config self.dvm_config = dvm_config
print(self.dvm_config.PRIVATE_KEY)
request_form = {"jobID": event.id().to_hex()} request_form = {"jobID": event.id().to_hex()}
@@ -110,7 +108,7 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface):
from types import SimpleNamespace from types import SimpleNamespace
ns = SimpleNamespace() ns = SimpleNamespace()
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
database = NostrDatabase.sqlite(self.db_name) database = NostrDatabase.sqlite(self.db_name)
cli = ClientBuilder().database(database).build() cli = ClientBuilder().database(database).build()
@@ -122,6 +120,8 @@ class DicoverContentCurrentlyPopularZaps(DVMTaskInterface):
filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).since(since) filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).since(since)
events = cli.database().query([filter1]) events = cli.database().query([filter1])
print("[" + self.dvm_config.NIP89.NAME + "] Considering " + str(len(events)) + " Events")
ns.finallist = {} ns.finallist = {}
for event in events: for event in events:
if event.created_at().as_secs() > timestamp_hour_ago: 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 definitions.EventDefinitions.KIND_ZAP]).since(lasthour) # Notes, reactions, zaps
# filter = Filter().author(keys.public_key()) # 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..") self.db_since) + " seconds.. this might take a while..")
dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN)
cli.reconcile(filter1, dbopts) cli.reconcile(filter1, dbopts)
database.delete(Filter().until(Timestamp.from_secs( filter_delete = Filter().until(Timestamp.from_secs(Timestamp.now().as_secs() - self.db_since))
Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesnt get too full. database.delete(filter_delete) # Clear old events so db doesn't get too full.
print( 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, # We build an example here that we can call by either calling this file directly from the main directory,

View File

@@ -65,7 +65,6 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface):
def create_request_from_nostr_event(self, event: Event, client=None, dvm_config=None): def create_request_from_nostr_event(self, event: Event, client=None, dvm_config=None):
self.dvm_config = dvm_config self.dvm_config = dvm_config
print(self.dvm_config.PRIVATE_KEY)
request_form = {"jobID": event.id().to_hex()} request_form = {"jobID": event.id().to_hex()}
@@ -95,7 +94,7 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface):
from types import SimpleNamespace from types import SimpleNamespace
ns = SimpleNamespace() ns = SimpleNamespace()
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
relaylimits = RelayLimits.disable() relaylimits = RelayLimits.disable()
opts = ( opts = (
@@ -143,6 +142,7 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface):
filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).authors(followings).since(since) filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).authors(followings).since(since)
events = cli.database().query([filter1]) events = cli.database().query([filter1])
print("[" + self.dvm_config.NIP89.NAME + "] Considering " + str(len(events)) + " Events")
ns.finallist = {} ns.finallist = {}
for event in events: for event in events:
@@ -207,15 +207,14 @@ class DicoverContentCurrentlyPopularFollowers(DVMTaskInterface):
definitions.EventDefinitions.KIND_ZAP]).since(lasthour) # Notes, reactions, zaps definitions.EventDefinitions.KIND_ZAP]).since(lasthour) # Notes, reactions, zaps
# filter = Filter().author(keys.public_key()) # 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..") self.db_since) + " seconds.. this might take a while..")
dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN)
cli.reconcile(filter1, dbopts) cli.reconcile(filter1, dbopts)
database.delete(Filter().until(Timestamp.from_secs( filter_delete = Filter().until(Timestamp.from_secs(Timestamp.now().as_secs() - self.db_since))
Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesnt get too full. database.delete(filter_delete) # Clear old events so db doesn't get too full.
print( 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, # We build an example here that we can call by either calling this file directly from the main directory,

View File

@@ -89,8 +89,6 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface):
def create_request_from_nostr_event(self, event, client=None, dvm_config=None): def create_request_from_nostr_event(self, event, client=None, dvm_config=None):
self.dvm_config = dvm_config self.dvm_config = dvm_config
print(self.dvm_config.PRIVATE_KEY)
request_form = {"jobID": event.id().to_hex()} request_form = {"jobID": event.id().to_hex()}
# default values # default values
@@ -135,28 +133,18 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface):
from types import SimpleNamespace from types import SimpleNamespace
ns = SimpleNamespace() ns = SimpleNamespace()
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)
keys = Keys.parse(sk.to_hex())
signer = NostrSigner.keys(keys)
database = NostrDatabase.sqlite(self.db_name) database = NostrDatabase.sqlite(self.db_name)
cli = ClientBuilder().database(database).build() 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 timestamp_since = Timestamp.now().as_secs() - self.db_since
since = Timestamp.from_secs(timestamp_since) since = Timestamp.from_secs(timestamp_since)
filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).since(since) filter1 = Filter().kind(definitions.EventDefinitions.KIND_NOTE).since(since)
events = cli.database().query([filter1]) events = cli.database().query([filter1])
print(len(events)) print("[" + self.dvm_config.NIP89.NAME + "] Considering " + str(len(events)) + " Events")
ns.final_list = {} ns.final_list = {}
for event in events: for event in events:
@@ -197,7 +185,7 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface):
return 1 return 1
def sync_db(self): 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) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY)
keys = Keys.parse(sk.to_hex()) keys = Keys.parse(sk.to_hex())
signer = NostrSigner.keys(keys) signer = NostrSigner.keys(keys)
@@ -207,7 +195,6 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface):
cli.add_relay("wss://relay.damus.io") cli.add_relay("wss://relay.damus.io")
cli.add_relay("wss://nostr.oxtr.dev") cli.add_relay("wss://nostr.oxtr.dev")
cli.add_relay("wss://nostr21.com") cli.add_relay("wss://nostr21.com")
cli.connect() cli.connect()
timestamp_since = Timestamp.now().as_secs() - self.db_since timestamp_since = Timestamp.now().as_secs() - self.db_since
@@ -217,15 +204,15 @@ class DicoverContentCurrentlyPopularbyTopic(DVMTaskInterface):
EventDefinitions.KIND_LONGFORM]).since(since) # Notes, reactions, zaps EventDefinitions.KIND_LONGFORM]).since(since) # Notes, reactions, zaps
# filter = Filter().author(keys.public_key()) # 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..") self.db_since) + " seconds.. this might take a while..")
dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN) dbopts = NegentropyOptions().direction(NegentropyDirection.DOWN)
cli.reconcile(filter1, dbopts) cli.reconcile(filter1, dbopts)
database.delete(Filter().until(Timestamp.from_secs( filter_delete = Filter().until(Timestamp.from_secs(Timestamp.now().as_secs() - self.db_since))
Timestamp.now().as_secs() - self.db_since))) # Clear old events so db doesn't get too full. database.delete(filter_delete) # Clear old events so db doesn't get too full.
print( 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, # We build an example here that we can call by either calling this file directly from the main directory,

View File

@@ -73,7 +73,7 @@ class MediaConverter(DVMTaskInterface):
return request_form return request_form
def process(self, 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"]) url = upload_media_to_hoster(options["filepath"])
return url return url

View File

@@ -77,7 +77,7 @@ class DiscoveryBotFarms(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
from nostr_sdk import Filter 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))) opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)))
sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY)

View File

@@ -89,7 +89,7 @@ class DiscoverReports(DVMTaskInterface):
cli.connect() cli.connect()
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
step = 20 step = 20
pubkeys = [] pubkeys = []

View File

@@ -88,7 +88,7 @@ class DiscoverInactiveFollows(DVMTaskInterface):
cli.connect() cli.connect()
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
step = 20 step = 20
followers_filter = Filter().author(PublicKey.parse(options["user"])).kind(Kind(3)) followers_filter = Filter().author(PublicKey.parse(options["user"])).kind(Kind(3))

View File

@@ -78,7 +78,7 @@ class DiscoverNonFollowers(DVMTaskInterface):
cli.connect() cli.connect()
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
step = 20 step = 20
followers_filter = Filter().author(PublicKey.from_hex(options["user"])).kind(Kind(3)) followers_filter = Filter().author(PublicKey.from_hex(options["user"])).kind(Kind(3))

View File

@@ -68,7 +68,7 @@ class TrendingNotesNostrBand(DVMTaskInterface):
return request_form return request_form
def process(self, request_form): def process(self, request_form):
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
import requests import requests

View File

@@ -96,7 +96,7 @@ class ImageGenerationDALLE(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
try: try:
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
from openai import OpenAI from openai import OpenAI
client = OpenAI() client = OpenAI()

View File

@@ -93,7 +93,7 @@ class ImageGenerationReplicateSDXL(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
try: try:
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
import replicate import replicate
width = int(options["size"].split("x")[0]) width = int(options["size"].split("x")[0])

View File

@@ -99,7 +99,7 @@ class ImageGenerationMLX(DVMTaskInterface):
try: try:
import mlx.core as mx import mlx.core as mx
from nostr_dvm.backends.mlx.modules.stable_diffusion import StableDiffusion from nostr_dvm.backends.mlx.modules.stable_diffusion import StableDiffusion
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
sd = StableDiffusion() sd = StableDiffusion()
cfg_weight = 7.5 cfg_weight = 7.5

View File

@@ -78,7 +78,7 @@ class SearchUser(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
from nostr_sdk import Filter 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))) opts = (Options().wait_for_send(False).send_timeout(timedelta(seconds=self.dvm_config.RELAY_TIMEOUT)))
sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY) sk = SecretKey.from_hex(self.dvm_config.PRIVATE_KEY)

View File

@@ -104,7 +104,7 @@ class TextSummarizationHuggingChat(DVMTaskInterface):
cookies = sign.login() cookies = sign.login()
sign.saveCookiesToDir(cookie_path_dir) sign.saveCookiesToDir(cookie_path_dir)
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
try: try:
chatbot = hugchat.ChatBot(cookies=cookies.get_dict()) # or cookie_path="usercookies/<email>.json" chatbot = hugchat.ChatBot(cookies=cookies.get_dict()) # or cookie_path="usercookies/<email>.json"

View File

@@ -97,7 +97,7 @@ class SummarizationUnleashedChat(DVMTaskInterface):
from openai import OpenAI from openai import OpenAI
temp_open_ai_api_key = os.environ["OPENAI_API_KEY"] temp_open_ai_api_key = os.environ["OPENAI_API_KEY"]
os.environ["OPENAI_API_KEY"] = os.getenv("UNLEASHED_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: try:
client = OpenAI( client = OpenAI(

View File

@@ -112,7 +112,7 @@ class SpeechToTextGoogle(DVMTaskInterface):
api_key = self.options['api_key'] api_key = self.options['api_key']
else: else:
api_key = None api_key = None
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
# Speech recognition instance # Speech recognition instance
asr = sr.Recognizer() asr = sr.Recognizer()
with sr.AudioFile(options["filepath"]) as source: with sr.AudioFile(options["filepath"]) as source:

View File

@@ -74,7 +74,7 @@ class TextExtractionPDF(DVMTaskInterface):
from pathlib import Path from pathlib import Path
import requests import requests
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
try: try:
file_path = Path('temp.pdf') file_path = Path('temp.pdf')

View File

@@ -71,7 +71,7 @@ class TextGenerationHuggingChat(DVMTaskInterface):
sign.saveCookiesToDir(cookie_path_dir) sign.saveCookiesToDir(cookie_path_dir)
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
try: try:
chatbot = hugchat.ChatBot(cookies=cookies.get_dict()) # or cookie_path="usercookies/<email>.json" chatbot = hugchat.ChatBot(cookies=cookies.get_dict()) # or cookie_path="usercookies/<email>.json"

View File

@@ -71,7 +71,7 @@ class TextGenerationLLMLite(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
from litellm import completion from litellm import completion
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
try: try:
if options["model"].startswith("ollama"): if options["model"].startswith("ollama"):

View File

@@ -64,7 +64,7 @@ class TextGenerationUnleashedChat(DVMTaskInterface):
from openai import OpenAI from openai import OpenAI
temp_open_ai_api_key = os.environ["OPENAI_API_KEY"] temp_open_ai_api_key = os.environ["OPENAI_API_KEY"]
os.environ["OPENAI_API_KEY"] = os.getenv("UNLEASHED_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: try:
client = OpenAI( client = OpenAI(

View File

@@ -106,7 +106,7 @@ class TextToSpeech(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
import torch import torch
from TTS.api import TTS 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" device = "cuda" if torch.cuda.is_available() else "cpu"
# else "mps" if torch.backends.mps.is_available() \ # else "mps" if torch.backends.mps.is_available() \

View File

@@ -80,7 +80,7 @@ class TranslationGoogle(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
from translatepy.translators.google import GoogleTranslate from translatepy.translators.google import GoogleTranslate
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
gtranslate = GoogleTranslate() gtranslate = GoogleTranslate()
length = len(options["text"]) length = len(options["text"])

View File

@@ -78,7 +78,7 @@ class TranslationLibre(DVMTaskInterface):
return request_form return request_form
def process(self, request_form): def process(self, request_form):
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
request = { request = {
"q": options["text"], "q": options["text"],
"source": "auto", "source": "auto",

View File

@@ -81,7 +81,7 @@ class VideoGenerationReplicateSVD(DVMTaskInterface):
def process(self, request_form): def process(self, request_form):
try: try:
options = DVMTaskInterface.set_options(request_form) options = self.set_options(request_form)
print(options["url"]) print(options["url"])
response = requests.get(options["url"]) response = requests.get(options["url"])
image = Image.open(BytesIO(response.content)).convert("RGB") image = Image.open(BytesIO(response.content)).convert("RGB")

View File

@@ -177,7 +177,8 @@ def nip88_announce_tier(dvm_config, client):
event = EventBuilder(EventDefinitions.KIND_NIP88_TIER_EVENT, content, tags).to_event(keys) event = EventBuilder(EventDefinitions.KIND_NIP88_TIER_EVENT, content, tags).to_event(keys)
annotier_id = send_event(event, client=client, dvm_config=dvm_config) 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 return annotier_id
# Relay and payment-verification # Relay and payment-verification

View File

@@ -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.definitions import EventDefinitions
from nostr_dvm.utils.nostr_utils import send_event from nostr_dvm.utils.nostr_utils import send_event
from nostr_dvm.utils.print import bcolors
class NIP89Config: class NIP89Config:
@@ -31,7 +32,9 @@ def nip89_announce_tasks(dvm_config, client):
content = dvm_config.NIP89.CONTENT 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]).to_event(keys)
send_event(event, client=client, dvm_config=dvm_config) 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): def fetch_nip89_parameters_for_deletion(keys, eventid, client, dvmconfig, pow=False):

View File

@@ -211,8 +211,7 @@ def update_profile(dvm_config, client, lud16=""):
.set_lud16(lud16) \ .set_lud16(lud16) \
.set_nip05(lud16) .set_nip05(lud16)
# .set_banner("https://example.com/banner.png") \ # .set_banner("https://example.com/banner.png") \
print("[" + dvm_config.NIP89.NAME + "] Setting profile metadata for " + keys.public_key().to_bech32() + "...")
print(f"Setting profile metadata for {keys.public_key().to_bech32()}...")
print(metadata.as_json()) print(metadata.as_json())
client.set_metadata(metadata) client.set_metadata(metadata)

15
nostr_dvm/utils/print.py Normal file
View File

@@ -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'

View File

@@ -1,6 +1,6 @@
from setuptools import setup, find_packages 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' 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') 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, description=DESCRIPTION,
long_description=LONG_DESCRIPTION, long_description=LONG_DESCRIPTION,
packages=find_packages(include=['nostr_dvm', 'nostr_dvm.*']), packages=find_packages(include=['nostr_dvm', 'nostr_dvm.*']),
#nostr-sdk==0.13.0a2.dev0
install_requires=["nostr-sdk==0.12.0", install_requires=["nostr-sdk==0.12.0",
"bech32", "bech32",
"pycryptodome==3.20.0", "pycryptodome==3.20.0",

View File

@@ -231,76 +231,6 @@ def playground():
custom_processing_msg=custom_processing_msg) custom_processing_msg=custom_processing_msg)
trending_nb.run() 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) # Popular Animals (Fluffy frens)
admin_config_animals = AdminConfig() admin_config_animals = AdminConfig()
@@ -358,6 +288,77 @@ def playground():
discovery_animals.run() 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 # Popular Followers
admin_config_followers = AdminConfig() admin_config_followers = AdminConfig()
admin_config_followers.REBROADCAST_NIP89 = rebbroadcast_NIP89 admin_config_followers.REBROADCAST_NIP89 = rebbroadcast_NIP89