post-process external dvms, if option is set

This commit is contained in:
Believethehype 2023-12-01 12:12:46 +01:00
parent e51d8c7de3
commit 56cdddce2c
6 changed files with 65 additions and 25 deletions

View File

@ -3,7 +3,6 @@ import os
import signal
import time
from datetime import timedelta
from threading import Thread
from nostr_sdk import (Keys, Client, Timestamp, Filter, nip04_decrypt, HandleNotification, EventBuilder, PublicKey,
Options, Tag, Event, nip04_encrypt)
@ -13,6 +12,7 @@ from utils.database_utils import get_or_add_user, update_user_balance, create_sq
from utils.definitions import EventDefinitions
from utils.nip89_utils import nip89_fetch_events_pubkey
from utils.nostr_utils import send_event
from utils.output_utils import PostProcessFunctionType, post_process_list_to_users, post_process_list_to_events
from utils.zap_utils import parse_zap_event_tags, pay_bolt11_ln_bits, zap
@ -138,7 +138,7 @@ class Bot:
# send the event to the DVM
send_event(nip90request, client=self.client, dvm_config=self.dvm_config)
#print(nip90request.as_json())
# print(nip90request.as_json())
@ -234,7 +234,7 @@ class Bot:
# if we get a bolt11, we pay and move on
user = get_or_add_user(db=self.dvm_config.DB, npub=entry["npub"],
client=self.client, config=self.dvm_config)
if user.balance > amount:
if user.balance >= amount:
balance = max(user.balance - amount, 0)
update_sql_table(db=self.dvm_config.DB, npub=user.npub, balance=balance,
iswhitelisted=user.iswhitelisted, isblacklisted=user.isblacklisted,
@ -315,6 +315,20 @@ class Bot:
else:
return
dvms = [x for x in self.dvm_config.SUPPORTED_DVMS if
x.PUBLIC_KEY == nostr_event.pubkey().to_hex() and x.KIND == nostr_event.kind() - 1000]
print(dvms[0])
if len(dvms) > 0:
dvm = dvms[0]
if dvm.dvm_config.EXTERNAL_POST_PROCESS_TYPE != PostProcessFunctionType.NONE:
if dvm.dvm_config.EXTERNAL_POST_PROCESS_TYPE == PostProcessFunctionType.LIST_TO_EVENTS:
content = post_process_list_to_events(content)
elif dvm.dvm_config.EXTERNAL_POST_PROCESS_TYPE == PostProcessFunctionType.LIST_TO_USERS:
content = post_process_list_to_users(content)
print("[" + self.NAME + "] Received results, message to orignal sender " + user.name)
time.sleep(1.0)
reply_event = EventBuilder.new_encrypted_direct_msg(self.keys,

12
main.py
View File

@ -12,6 +12,7 @@ from playground import build_pdf_extractor, build_googletranslator, build_unstab
from utils.definitions import EventDefinitions
from utils.dvmconfig import DVMConfig
from utils.nostr_utils import check_and_set_private_key
from utils.output_utils import PostProcessFunctionType
def run_nostr_dvm_with_local_config():
@ -88,7 +89,7 @@ def run_nostr_dvm_with_local_config():
pubkey="d483935d6bfcef3645195c04c97bbb70aedb6e65665c5ea83e562ca3c7acb978",
task="text-to-image",
kind=EventDefinitions.KIND_NIP90_GENERATE_IMAGE,
fix_cost=100, per_unit_cost=0)
fix_cost=80, per_unit_cost=0)
tasktiger_external.SUPPORTS_ENCRYPTION = False # if the dvm does not support encrypted events, just send a regular event and mark it with p tag. Other dvms might initial answer
bot_config.SUPPORTED_DVMS.append(tasktiger_external)
@ -97,10 +98,11 @@ def run_nostr_dvm_with_local_config():
# DVM: 8 Another external dvm for recommendations:
ymhm_external = build_external_dvm(name="External DVM: You might have missed",
pubkey="6b37d5dc88c1cbd32d75b713f6d4c2f7766276f51c9337af9d32c8d715cc1b93",
task="content-discovery",
kind=EventDefinitions.KIND_NIP90_CONTENT_DISCOVERY,
fix_cost=0, per_unit_cost=0)
pubkey="6b37d5dc88c1cbd32d75b713f6d4c2f7766276f51c9337af9d32c8d715cc1b93",
task="content-discovery",
kind=EventDefinitions.KIND_NIP90_CONTENT_DISCOVERY,
fix_cost=0, per_unit_cost=0,
external_post_process=PostProcessFunctionType.LIST_TO_EVENTS)
ymhm_external.SUPPORTS_ENCRYPTION = False # if the dvm does not support encrypted events, just send a regular event and mark it with p tag. Other dvms might initial answer
bot_config.SUPPORTED_DVMS.append(ymhm_external)

View File

@ -18,6 +18,7 @@ from utils.admin_utils import AdminConfig
from utils.dvmconfig import DVMConfig
from utils.nip89_utils import NIP89Config, check_and_set_d_tag
from utils.nostr_utils import check_and_set_private_key
from utils.output_utils import PostProcessFunctionType
"""
This File is a playground to create DVMs. It shows some examples of DVMs that make use of the modules in the tasks folder
@ -241,7 +242,8 @@ def build_googletranscribe(name, identifier):
nip89info["image"])
nip89config.CONTENT = json.dumps(nip89info)
return SpeechToTextGoogle(name=name, dvm_config=dvm_config, nip89config=nip89config,
admin_config=admin_config, options=options)
admin_config=admin_config, options=options)
def build_sketcher(name, identifier):
dvm_config = DVMConfig()
@ -415,11 +417,12 @@ def build_inactive_follows_finder(name, identifier):
# This function can be used to build a DVM object for a DVM we don't control, but we want the bot to be aware of.
# See main.py for examples.
def build_external_dvm(name, pubkey, task, kind, fix_cost, per_unit_cost):
def build_external_dvm(name, pubkey, task, kind, fix_cost, per_unit_cost, external_post_process=PostProcessFunctionType.NONE):
dvm_config = DVMConfig()
dvm_config.PUBLIC_KEY = PublicKey.from_hex(pubkey).to_hex()
dvm_config.FIX_COST = fix_cost
dvm_config.PER_UNIT_COST = per_unit_cost
dvm_config.EXTERNAL_POST_PROCESS_TYPE = external_post_process
nip89info = {
"name": name,
}
@ -427,7 +430,9 @@ def build_external_dvm(name, pubkey, task, kind, fix_cost, per_unit_cost):
nip89config.KIND = kind
nip89config.CONTENT = json.dumps(nip89info)
return DVMTaskInterface(name=name, dvm_config=dvm_config, nip89config=nip89config, task=task)
interface = DVMTaskInterface(name=name, dvm_config=dvm_config, nip89config=nip89config, task=task)
return interface
# Little optional Gimmick:

View File

@ -12,6 +12,7 @@ from utils.definitions import EventDefinitions
from utils.dvmconfig import DVMConfig
from utils.nip89_utils import NIP89Config
from utils.nostr_utils import get_event_by_id
from utils.output_utils import post_process_list_to_users
"""
This File contains a Module to find inactive follows for a user on nostr
@ -158,13 +159,7 @@ class DiscoverInactiveFollows(DVMTaskInterface):
if tag.as_vec()[0] == 'output':
format = tag.as_vec()[1]
if format == "text/plain": # check for output type
result_list = json.loads(result)
inactive_follows_list = ""
for tag in result_list:
p_tag = Tag.parse(tag)
inactive_follows_list = inactive_follows_list + "nostr:" + PublicKey.from_hex(
p_tag.as_vec()[1]).to_bech32() + "\n"
return inactive_follows_list
result = post_process_list_to_users(result)
# if not text/plain, don't post-process
return result

View File

@ -1,8 +1,5 @@
import os
from nostr_sdk import Keys
from utils.nip89_utils import NIP89Config
from utils.output_utils import PostProcessFunctionType
class DVMConfig:
@ -19,6 +16,7 @@ class DVMConfig:
"wss://nostr-pub.wellorder.net"]
RELAY_TIMEOUT = 3
EXTERNAL_POST_PROCESS_TYPE = PostProcessFunctionType.NONE # Leave this on None, except the DVM is external
LNBITS_INVOICE_KEY = ''
LNBITS_ADMIN_KEY = '' # In order to pay invoices, e.g. from the bot to DVMs, or reimburse users.
LNBITS_URL = 'https://lnbits.com'

View File

@ -5,6 +5,7 @@ from types import NoneType
import emoji
import requests
from nostr_sdk import Tag, PublicKey, EventId
from pyupload.uploader import CatboxUploader
import pandas
@ -14,6 +15,12 @@ Post process results to either given output format or a Nostr readable plain tex
'''
class PostProcessFunctionType:
NONE = 0
LIST_TO_USERS = 1
LIST_TO_EVENTS = 2
def post_process_result(anno, original_event):
print("Post-processing...")
if isinstance(anno, pandas.DataFrame): # if input is an anno we parse it to required output format
@ -33,7 +40,7 @@ def post_process_result(anno, original_event):
if output_format == "text/plain":
result = pandas_to_plaintext(anno)
result = replace_broken_words(
str(result).replace("\"", "").replace('[', "").replace(']',
str(result).replace("\"", "").replace('[', "").replace(']',
"").lstrip(None))
return result
@ -78,7 +85,7 @@ def post_process_result(anno, original_event):
result = pandas_to_plaintext(anno)
print(result)
result = str(result).replace("\"", "").replace('[', "").replace(']',
"").lstrip(None)
"").lstrip(None)
return result
elif isinstance(anno, NoneType):
return "An error occurred"
@ -87,6 +94,26 @@ def post_process_result(anno, original_event):
return result
def post_process_list_to_events(result):
result_list = json.loads(result)
result_str = ""
for tag in result_list:
p_tag = Tag.parse(tag)
result_str = result_str + "nostr:" + EventId.from_hex(
p_tag.as_vec()[1]).to_bech32() + "\n"
return result_str
def post_process_list_to_users(result):
result_list = json.loads(result)
result_str = ""
for tag in result_list:
p_tag = Tag.parse(tag)
result_str = result_str + "nostr:" + PublicKey.from_hex(
p_tag.as_vec()[1]).to_bech32() + "\n"
return result_str
def pandas_to_plaintext(anno):
result = ""
for each_row in anno['name']:
@ -96,7 +123,6 @@ def pandas_to_plaintext(anno):
return result
'''
Convenience function to replace words like Noster with Nostr
'''