From f7c4f718d3f128cd8665b3090bbfe6f660800f61 Mon Sep 17 00:00:00 2001 From: Believethehype <1097224+believethehype@users.noreply.github.com> Date: Wed, 25 Sep 2024 10:21:30 +0200 Subject: [PATCH] add bot example, add legacy code for nip04 support (on lifeline) --- nostr_dvm/bot.py | 51 +++++++++------ nostr_dvm/dvm.py | 2 +- nostr_dvm/utils/database_utils.py | 7 +- nostr_dvm/utils/dvmconfig.py | 2 +- nostr_dvm/utils/gallery_utils.py | 2 +- nostr_dvm/utils/nip65_utils.py | 32 ++++++++- nostr_dvm/utils/nip89_utils.py | 2 +- nostr_dvm/utils/nostr_utils.py | 57 +++++++++++++++- nostr_dvm/utils/nut_wallet_utils.py | 2 +- nostr_dvm/utils/output_utils.py | 2 +- nostr_dvm/utils/{print.py => print_utils.py} | 0 nostr_dvm/utils/reaction_utils.py | 2 +- tests/simplebot.py | 8 ++- tutorials/01_preparations.ipynb | 2 +- tutorials/02_run_dvm.py | 9 ++- tutorials/04_simple_chat_bot.py | 68 ++++++++++++++++++++ 16 files changed, 213 insertions(+), 35 deletions(-) rename nostr_dvm/utils/{print.py => print_utils.py} (100%) create mode 100644 tutorials/04_simple_chat_bot.py diff --git a/nostr_dvm/bot.py b/nostr_dvm/bot.py index 0d9bf2c..8b6e2b4 100644 --- a/nostr_dvm/bot.py +++ b/nostr_dvm/bot.py @@ -2,7 +2,7 @@ import asyncio import json import os import signal -import time + from datetime import timedelta from nostr_sdk import (Keys, Client, Timestamp, Filter, nip04_decrypt, HandleNotification, EventBuilder, PublicKey, @@ -13,12 +13,13 @@ from nostr_dvm.utils.admin_utils import admin_make_database_updates from nostr_dvm.utils.database_utils import get_or_add_user, update_user_balance, create_sql_table, update_sql_table from nostr_dvm.utils.definitions import EventDefinitions, InvoiceToWatch from nostr_dvm.utils.nip89_utils import nip89_fetch_events_pubkey, NIP89Config -from nostr_dvm.utils.nostr_utils import send_event +from nostr_dvm.utils.nostr_utils import send_event, send_nip04_dm from nostr_dvm.utils.output_utils import PostProcessFunctionType, post_process_list_to_users, \ post_process_list_to_events from nostr_dvm.utils.zap_utils import parse_zap_event_tags, pay_bolt11_ln_bits, zaprequest, create_bolt11_ln_bits, \ check_bolt11_ln_bits_is_paid, parse_amount_from_bolt11_invoice from nostr_dvm.utils.cashu_utils import redeem_cashu +from nostr_dvm.utils.print_utils import bcolors class Bot: @@ -57,7 +58,7 @@ class Bot: self.job_list = [] - print("Nostr BOT public key: " + str(pk.to_bech32()) + " Hex: " + str(pk.to_hex()) + " Name: " + self.NAME) # + + print(bcolors.BLUE + "Nostr BOT public key: " + str(pk.to_bech32()) + " Hex: " + str(pk.to_hex()) + " Name: " + self.NAME + bcolors.ENDC) # + # " Supported DVM tasks: " + # ', '.join(p.NAME + ":" + p.TASK for p in self.dvm_config.SUPPORTED_DVMS) + "\n") if dvm_config.CHATBOT is not None: @@ -245,7 +246,8 @@ class Bot: await self.client.send_private_msg(PublicKey.parse(sender), message, None) else: #await self.client.send_direct_msg(PublicKey.parse(sender), message, None) - await self.client.send_private_msg(PublicKey.parse(sender), message, None) + #await self.client.send_private_msg(PublicKey.parse(sender), message, None) + await send_nip04_dm(self.client, message, sender, self.dvm_config) @@ -264,8 +266,9 @@ class Bot: if giftwrap: await self.client.send_private_msg(PublicKey.parse(sender), message, None) else: + await send_nip04_dm(self.client, message, sender, self.dvm_config) #await self.client.send_direct_msg(PublicKey.parse(sender), message, None) - await self.client.send_private_msg(PublicKey.parse(sender), message, None) + #await self.client.send_private_msg(PublicKey.parse(sender), message, None) elif decrypted_text.startswith("cashuA"): print("Received Cashu token:" + decrypted_text) cashu_redeemed, cashu_message, total_amount, fees = await redeem_cashu(decrypted_text, @@ -283,7 +286,9 @@ class Bot: await self.client.send_private_msg(PublicKey.parse(sender), message, None) else: #await self.client.send_direct_msg(PublicKey.parse(sender), message, None) - await self.client.send_private_msg(PublicKey.parse(sender), message, None) + #await self.client.send_private_msg(PublicKey.parse(sender), message, None) + #await send_nip04_dm(self.client, message, sender, self.keys) + await send_nip04_dm(self.client, message, sender, self.dvm_config) elif decrypted_text.lower().startswith("what's the second best"): await asyncio.sleep(2.0) message = "No, there is no second best.\n\nhttps://cdn.nostr.build/p/mYLv.mp4" @@ -291,8 +296,8 @@ class Bot: await self.client.send_private_msg(PublicKey.parse(sender), message, None) else: #await self.client.send_direct_msg(PublicKey.parse(sender), message, nostr_event.id()) - await self.client.send_private_msg(PublicKey.parse(sender), message, None) - + #await self.client.send_private_msg(PublicKey.parse(sender), message, None) + await send_nip04_dm(self.client, message, sender, self.dvm_config) else: # Build an overview of known DVMs and send it to the user @@ -389,8 +394,9 @@ class Bot: await self.client.send_private_msg(PublicKey.parse(entry["npub"]), content, None) else: #await self.client.send_direct_msg(PublicKey.from_hex(entry['npub']), content, None) - await self.client.send_private_msg(PublicKey.parse(entry['npub']), - content, None) + #await self.client.send_private_msg(PublicKey.parse(entry['npub']), + # content, None) + await send_nip04_dm(self.client, content, PublicKey.parse(entry['npub']), self.dvm_config) print(status + ": " + content) print( "[" + self.NAME + "] Received reaction from " + nostr_event.author().to_hex() + " message to orignal sender " + user.name) @@ -421,8 +427,9 @@ class Bot: None) else: #await self.client.send_direct_msg(PublicKey.parse(PublicKey.parse(entry["npub"])), message, None) - await self.client.send_private_msg(PublicKey.parse(entry["npub"]), message, None) - + #await self.client.send_private_msg(PublicKey.parse(entry["npub"]), message, None) + await send_nip04_dm(self.client, content, PublicKey.parse(entry['npub']), + self.dvm_config) print( "[" + self.NAME + "] Replying " + user.name + " with \"scheduled\" confirmation") @@ -432,8 +439,13 @@ class Bot: message = "Current balance: " + str( user.balance) + " Sats. Balance of " + str(amount) + " Sats required. Please zap me with at least " + str(int(amount - user.balance))+ " Sats, then try again.", #await self.client.send_direct_msg(PublicKey.parse(PublicKey.parse(entry["npub"])), # message, None) - await self.client.send_private_msg(PublicKey.parse(entry["npub"]), - message, None) + #await self.client.send_private_msg(PublicKey.parse(entry["npub"]), + # + if entry["giftwrap"]: + await self.client.send_private_msg(PublicKey.parse(entry["npub"]), message, + None) + else: + await send_nip04_dm(self.client, message, PublicKey.parse(entry['npub']), self.dvm_config) return if len(tag.as_vec()) > 2: @@ -508,7 +520,8 @@ class Bot: await self.client.send_private_msg(PublicKey.parse(user.npub), content, None) else: #await self.client.send_direct_msg(PublicKey.parse(user.npub), content, None) - await self.client.send_private_msg(PublicKey.parse(user.npub), content, None) + #await self.client.send_private_msg(PublicKey.parse(user.npub), content, None) + await send_nip04_dm(self.client, content, PublicKey.parse(user.npub), self.dvm_config) except Exception as e: print(e) @@ -581,7 +594,8 @@ class Bot: await self.client.send_private_msg(PublicKey.parse(sender), text, nostr_event.id()) else: #await self.client.send_direct_msg(PublicKey.parse(sender), text, nostr_event.id()) - await self.client.send_private_msg(PublicKey.parse(sender), text, nostr_event.id()) + #await self.client.send_private_msg(PublicKey.parse(sender), text, nostr_event.id()) + await send_nip04_dm(self.client, text, PublicKey.parse(sender), self.dvm_config) async def answer_blacklisted(nostr_event, giftwrap, sender): message = "Your are currently blocked from this service." @@ -589,7 +603,8 @@ class Bot: await self.client.send_private_msg(PublicKey.parse(sender), message, None) else: #await self.client.send_direct_msg(nostr_event.author(), message, None) - await self.client.send_private_msg(PublicKey.parse(sender), message, None) + #await self.client.send_private_msg(PublicKey.parse(sender), message, None) + await send_nip04_dm(self.client, message, PublicKey.parse(sender), self.dvm_config) @@ -603,7 +618,7 @@ class Bot: await self.client.send_private_msg(PublicKey.parse(sender), info, None) else: #await self.client.send_direct_msg(nostr_event.author(), info, None) - await self.client.send_private_msg(PublicKey.parse(sender), info, None) + await send_nip04_dm(self.client, info, PublicKey.parse(sender), self.dvm_config) def build_params(decrypted_text, author, index): tags = [] diff --git a/nostr_dvm/dvm.py b/nostr_dvm/dvm.py index 3b4f3b0..e95e8ea 100644 --- a/nostr_dvm/dvm.py +++ b/nostr_dvm/dvm.py @@ -22,7 +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 +from nostr_dvm.utils.print_utils import bcolors class DVM: diff --git a/nostr_dvm/utils/database_utils.py b/nostr_dvm/utils/database_utils.py index cfb93c7..0e6ac40 100644 --- a/nostr_dvm/utils/database_utils.py +++ b/nostr_dvm/utils/database_utils.py @@ -7,10 +7,12 @@ from dataclasses import dataclass from datetime import timedelta from logging import Filter +from coincurve import PrivateKey from nostr_sdk import Timestamp, Keys, PublicKey, EventBuilder, Filter, Kind from nostr_dvm.utils.definitions import relay_timeout -from nostr_dvm.utils.nostr_utils import send_event +from nostr_dvm.utils.dvmconfig import DVMConfig +from nostr_dvm.utils.nostr_utils import send_event, send_nip04_dm @dataclass @@ -197,7 +199,8 @@ async def update_user_balance(db, npub, additional_sats, client, config, giftwra await client.send_private_msg(PublicKey.parse(npub), message, None) else: #await client.send_direct_msg(PublicKey.parse(npub), message, None) - await client.send_private_msg(PublicKey.parse(npub), message, None) + #await client.send_private_msg(PublicKey.parse(npub), message, None) + await send_nip04_dm(client, message, npub, config) def update_user_subscription(npub, subscribed_until, client, dvm_config): diff --git a/nostr_dvm/utils/dvmconfig.py b/nostr_dvm/utils/dvmconfig.py index e924ad8..131c966 100644 --- a/nostr_dvm/utils/dvmconfig.py +++ b/nostr_dvm/utils/dvmconfig.py @@ -15,7 +15,7 @@ class DVMConfig: FIX_COST: float = None PER_UNIT_COST: float = None - RELAY_LIST = ["wss://relay.primal.net", + RELAY_LIST = [ "wss://nostr.mom", "wss://nostr.oxtr.dev", "wss://relay.nostr.net" ] diff --git a/nostr_dvm/utils/gallery_utils.py b/nostr_dvm/utils/gallery_utils.py index f31c446..574c5f9 100644 --- a/nostr_dvm/utils/gallery_utils.py +++ b/nostr_dvm/utils/gallery_utils.py @@ -2,7 +2,7 @@ from nostr_sdk import Tag, Keys, EventBuilder, Kind from nostr_dvm.utils.definitions import EventDefinitions from nostr_dvm.utils.nostr_utils import send_event -from nostr_dvm.utils.print import bcolors +from nostr_dvm.utils.print_utils import bcolors async def gallery_announce_list(tags, dvm_config, client): diff --git a/nostr_dvm/utils/nip65_utils.py b/nostr_dvm/utils/nip65_utils.py index 3ed0785..e56a66c 100644 --- a/nostr_dvm/utils/nip65_utils.py +++ b/nostr_dvm/utils/nip65_utils.py @@ -1,11 +1,38 @@ -from nostr_sdk import Tag, Keys, EventBuilder +from nostr_sdk import Tag, Keys, EventBuilder, Kind from nostr_dvm.utils.definitions import EventDefinitions from nostr_dvm.utils.nostr_utils import send_event -from nostr_dvm.utils.print import bcolors +from nostr_dvm.utils.print_utils import bcolors + + + + + +async def announce_dm_relays(dvm_config, client): + tags = [] + + for relay in dvm_config.RELAY_LIST: + r_tag = Tag.parse(["r", relay]) + tags.append(r_tag) + + keys = Keys.parse(dvm_config.NIP89.PK) + content = "" + + event = EventBuilder(Kind(10050), content, tags).to_event(keys) + eventid = await send_event(event, client=client, dvm_config=dvm_config) + if (eventid is not None): + print( + bcolors.BLUE + "[" + dvm_config.NIP89.NAME + "] Announced DM relays for " + dvm_config.NIP89.NAME + " (EventID: " + str( + eventid.id.to_hex()) + ")" + bcolors.ENDC) + else: + print( + bcolors.RED + "[" + dvm_config.NIP89.NAME + "] Could not announce DM relays for " + dvm_config.NIP89.NAME + bcolors.ENDC) async def nip65_announce_relays(dvm_config, client): + # todo we might want to call the dm relays seperately but for now we do it together with the inbox relays + await announce_dm_relays(dvm_config, client) + tags = [] for relay in dvm_config.RELAY_LIST: @@ -24,3 +51,4 @@ async def nip65_announce_relays(dvm_config, client): else: print( bcolors.RED + "[" + dvm_config.NIP89.NAME + "] Could not announce NIP 65 for " + dvm_config.NIP89.NAME + bcolors.ENDC) + diff --git a/nostr_dvm/utils/nip89_utils.py b/nostr_dvm/utils/nip89_utils.py index 8145f29..f3c92f4 100644 --- a/nostr_dvm/utils/nip89_utils.py +++ b/nostr_dvm/utils/nip89_utils.py @@ -8,7 +8,7 @@ from nostr_sdk import Tag, Keys, EventBuilder, Filter, Alphabet, PublicKey, Clie from nostr_dvm.utils.definitions import EventDefinitions, relay_timeout from nostr_dvm.utils.nostr_utils import send_event -from nostr_dvm.utils.print import bcolors +from nostr_dvm.utils.print_utils import bcolors class NIP89Config: diff --git a/nostr_dvm/utils/nostr_utils.py b/nostr_dvm/utils/nostr_utils.py index c92c36f..e188b7f 100644 --- a/nostr_dvm/utils/nostr_utils.py +++ b/nostr_dvm/utils/nostr_utils.py @@ -7,7 +7,7 @@ from typing import List import dotenv from nostr_sdk import Filter, Client, Alphabet, EventId, Event, PublicKey, Tag, Keys, nip04_decrypt, Metadata, Options, \ Nip19Event, SingleLetterTag, RelayOptions, RelayLimits, SecretKey, NostrSigner, Connection, ConnectionTarget, \ - EventSource + EventSource, EventBuilder, Kind, nip04_encrypt from nostr_dvm.utils.definitions import EventDefinitions, relay_timeout, relay_timeout_long @@ -141,6 +141,29 @@ async def get_inbox_relays(event_to_send: Event, client: Client, dvm_config): return relays +async def get_dm_relays(event_to_send: Event, client: Client, dvm_config): + ptags = [] + for tag in event_to_send.tags(): + if tag.as_vec()[0] == 'p': + ptag = PublicKey.parse(tag.as_vec()[1]) + ptags.append(ptag) + + filter = Filter().kinds([Kind(10050)]).authors(ptags) + events = await client.get_events_of([filter], relay_timeout) + if len(events) == 0: + return [] + else: + nip65event = events[0] + relays = [] + for tag in nip65event.tags(): + if ((tag.as_vec()[0] == 'r' and len(tag.as_vec()) == 2) + or ((tag.as_vec()[0] == 'r' and len(tag.as_vec()) == 3) and tag.as_vec()[2] == "read")): + rtag = tag.as_vec()[1] + if rtag.rstrip("/") not in dvm_config.AVOID_PAID_OUTBOX_RELAY_LIST: + if rtag.startswith("ws") and " " not in rtag: + relays.append(rtag) + return relays + async def get_main_relays(event_to_send: Event, client: Client, dvm_config): ptags = [] for tag in event_to_send.tags(): @@ -404,6 +427,38 @@ async def update_profile(dvm_config, client, lud16=""): await client.set_metadata(metadata) +async def send_nip04_dm(client: Client, msg, receiver: PublicKey, dvm_config ): + + signer = NostrSigner.keys(Keys.parse(dvm_config.PRIVATE_KEY)) + content = await signer.nip04_encrypt(receiver, msg) + ptag = Tag.parse(["p", receiver.to_hex()]) + event = EventBuilder(Kind(4), content, [ptag]).to_event(Keys.parse(dvm_config.PRIVATE_KEY)) + await client.send_event(event) + + + + + # relays = await get_dm_relays(event, client, dvm_config) + # + # outboxclient = Client(signer) + # print("[" + dvm_config.NIP89.NAME + "] Receiver Inbox relays: " + str(relays)) + # + # for relay in relays[:5]: + # try: + # await outboxclient.add_relay(relay) + # except: + # print("[" + dvm_config.NIP89.NAME + "] " + relay + " couldn't be added to outbox relays") + # # + # await outboxclient.connect() + # try: + # print("Connected, sending event") + # event_id = await outboxclient.send_event(event) + # print(event_id.output) + # except Exception as e: + # print(e) + + + def check_and_set_private_key(identifier): if not os.getenv("DVM_PRIVATE_KEY_" + identifier.upper()): pk = Keys.generate().secret_key().to_hex() diff --git a/nostr_dvm/utils/nut_wallet_utils.py b/nostr_dvm/utils/nut_wallet_utils.py index a909973..c998da0 100644 --- a/nostr_dvm/utils/nut_wallet_utils.py +++ b/nostr_dvm/utils/nut_wallet_utils.py @@ -12,7 +12,7 @@ from nostr_dvm.utils.nostr_utils import check_and_set_private_key from nostr_dvm.utils.zap_utils import pay_bolt11_ln_bits, zaprequest from nostr_sdk import Tag, Keys, nip44_encrypt, nip44_decrypt, Nip44Version, EventBuilder, Client, Filter, Kind, \ EventId, nip04_decrypt, nip04_encrypt, Options, NostrSigner, PublicKey, init_logger, LogLevel, Metadata -from nostr_dvm.utils.print import bcolors +from nostr_dvm.utils.print_utils import bcolors class NutWallet(object): diff --git a/nostr_dvm/utils/output_utils.py b/nostr_dvm/utils/output_utils.py index 0723b33..7f088e6 100644 --- a/nostr_dvm/utils/output_utils.py +++ b/nostr_dvm/utils/output_utils.py @@ -10,7 +10,7 @@ from nostr_sdk import Tag, PublicKey, EventId, Keys, nip04_encrypt, EventBuilder from pyupload.uploader import CatboxUploader import pandas -from nostr_dvm.utils.print import bcolors +from nostr_dvm.utils.print_utils import bcolors from nostr_dvm.utils.definitions import EventDefinitions from nostr_dvm.utils.dvmconfig import DVMConfig from nostr_dvm.utils.nip98_utils import generate_nip98_header diff --git a/nostr_dvm/utils/print.py b/nostr_dvm/utils/print_utils.py similarity index 100% rename from nostr_dvm/utils/print.py rename to nostr_dvm/utils/print_utils.py diff --git a/nostr_dvm/utils/reaction_utils.py b/nostr_dvm/utils/reaction_utils.py index 3902250..bd8d4ef 100644 --- a/nostr_dvm/utils/reaction_utils.py +++ b/nostr_dvm/utils/reaction_utils.py @@ -4,7 +4,7 @@ from nostr_sdk import Tag, Keys, EventBuilder, Kind, NostrSigner, Client from nostr_dvm.utils.dvmconfig import DVMConfig from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key -from nostr_dvm.utils.print import bcolors +from nostr_dvm.utils.print_utils import bcolors async def create_reaction(keys, title, dtag): diff --git a/tests/simplebot.py b/tests/simplebot.py index 55061f1..33530d2 100644 --- a/tests/simplebot.py +++ b/tests/simplebot.py @@ -2,7 +2,10 @@ import asyncio import time from nostr_sdk import Client, NostrSigner, Keys, Event, UnsignedEvent, Filter, \ - HandleNotification, Timestamp, nip04_decrypt, UnwrappedGift, init_logger, LogLevel, Kind, KindEnum + HandleNotification, Timestamp, nip04_decrypt, UnwrappedGift, init_logger, LogLevel, Kind, KindEnum, EventBuilder, \ + Tag + +from nostr_dvm.utils.nostr_utils import send_nip04_dm async def test(): @@ -39,8 +42,7 @@ async def test(): try: msg = nip04_decrypt(sk, event.author(), event.content()) print(f"Received new msg: {msg}") - #await client.send_direct_msg(event.author(), f"Echo: {msg}", event.id()) - await client.send_private_msg(event.author(), f"Echo: {msg}", event.id()) + await send_nip04_dm(client, msg, event.author(), sk) except Exception as e: diff --git a/tutorials/01_preparations.ipynb b/tutorials/01_preparations.ipynb index 6c6e6f4..c3b6823 100644 --- a/tutorials/01_preparations.ipynb +++ b/tutorials/01_preparations.ipynb @@ -28,7 +28,7 @@ "lnbits_admin_key = \"\" #TODO set your key here\n", "lnbits_wallet_id = \"\" #TODO set your key here\n", "lnbits_host= \"https://demo.lnbits.com\" #TODO you can use demo.lnbits.com, but rather use your own instance\n", - "nostdress_domain = \"nostrdvm.com\" #TODO use your own nostdress instance, or use the default one" + "nostdress_domain = \"nostrdvm.com\" # use your own nostdress instance, or use the default one" ], "id": "2e71e7aa2ebdac50" }, diff --git a/tutorials/02_run_dvm.py b/tutorials/02_run_dvm.py index 0d82a6e..257f442 100644 --- a/tutorials/02_run_dvm.py +++ b/tutorials/02_run_dvm.py @@ -35,8 +35,15 @@ def run_dvm(identifier): name = "My very first DVM" # Next we initalize a GenericDVM with the name and the dvm_config and the options we just created, as well as # an empty AdminConfig() and NIP89Config(). We will check these out in later tutorials, so don't worry about them now. + + + # We add an admin config. By configuring it we can perform certain tasks, for example on start of the DVM + admin_config = AdminConfig() + # We broadcast our NIP65 inbox relays so other clients know where to write to so we receive it + admin_config.REBROADCAST_NIP65_RELAY_LIST = True + dvm = GenericDVM(name=name, dvm_config=dvm_config, options=options, - nip89config=NIP89Config(), admin_config=AdminConfig()) + nip89config=NIP89Config(), admin_config=admin_config) # Normally we would define the dvm interface as we do in the tasks folder (we will do it later in the tutorials as well, diff --git a/tutorials/04_simple_chat_bot.py b/tutorials/04_simple_chat_bot.py new file mode 100644 index 0000000..9358dc3 --- /dev/null +++ b/tutorials/04_simple_chat_bot.py @@ -0,0 +1,68 @@ +# In tutorial 2 we have written a very simplistic DVM that replies with "The result of the DVM is: #RunDVM" +# In tutorial 3 we have written a client that requests a response from the DVM and gets the reply back. +# In this tutorial we build a simple bot that bridges the communication between the user and the Kind 5050 +# (Text generation) DVM. + + + +import asyncio +import os +import threading +from pathlib import Path + +import dotenv + +from nostr_dvm.bot import Bot +from nostr_dvm.tasks.generic_dvm import GenericDVM +from nostr_sdk import Kind, Keys +from nostr_dvm.utils.admin_utils import AdminConfig +from nostr_dvm.utils.dvmconfig import build_default_config, DVMConfig +from nostr_dvm.utils.nip89_utils import NIP89Config +from nostr_dvm.utils.zap_utils import change_ln_address + + +def run_dvm(identifier): + + + identifier = "bot_test" + bot_config = build_default_config(identifier) + # The main purpose is of the Bot is to be an indexable overview of multiple DVMs. But we will use it in "chatbot" mode here + # by setting the CHATBOT option to true + bot_config.CHATBOT = True + # And we simply hand over the publickey of our DVM from tutorial 1 + bot_config.DVM_KEY = "aa8ab5b774d47e7b29a985dd739cfdcccf93451678bf7977ba1b2e094ecd8b30" # TODO replace with your DVM + + # We update our relay list and profile and Start the bot + admin_config = AdminConfig() + admin_config.REBROADCAST_NIP65_RELAY_LIST = True + admin_config.UPDATE_PROFILE = True + x = threading.Thread(target=Bot, args=([bot_config, admin_config])) + x.start() + + + # Now you can copy the npub to a Social client of your choice and (if tutorials 2 and 4 are running) it should reply + # in your client. + + + + +if __name__ == '__main__': + #We open the .env file we created before. + env_path = Path('.env') + if not env_path.is_file(): + with open('.env', 'w') as f: + print("Writing new .env file") + f.write('') + if env_path.is_file(): + print(f'loading environment from {env_path.resolve()}') + dotenv.load_dotenv(env_path, verbose=True, override=True) + else: + raise FileNotFoundError(f'.env file not found at {env_path} ') + + # Replace the identifier with the one from the last notebook, or a new dvmconfig will be stored + identifier = "tutorial01" + + # psst, you can change your lightning address here: + #asyncio.run(change_ln_address(identifier, "test", DVMConfig(), True)) + + run_dvm(identifier)