v0.7.42 - Fix ephemeral event storage and document monitoring system

This commit is contained in:
Your Name
2025-10-26 15:02:00 -04:00
parent 2bff4a5f44
commit af186800fa
10 changed files with 408 additions and 16 deletions

12
tests/debug.log Normal file
View File

@@ -0,0 +1,12 @@
=== NOSTR WebSocket Debug Log Started ===
[14:13:42.079] SEND localhost:8888: ["EVENT", {
"pubkey": "e74e808f64b82fe4671b92cdf83f6dd5f5f44dbcb67fbd0e044f34a6193e0994",
"created_at": 1761499244,
"kind": 1059,
"tags": [["p", "4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa"]],
"content": "ApTb8y2oD3/TtVCV73Szhgfh5ODlluGd5zjsH44g5BBwaGB1NshOJ/5kF/XN0TfYJKQBe07UTpnOYMZ4l2ppU6SrR8Tor+ZEiAF/kpCpa/x6LDDIvf4mueQicDKjOf8Y6oEbsxYjtFrpuSC0LLMgLaVhcZjAgVD0YQTo+8nHOzHZD5RBr305vdnrxIe4ubEficAHCpnKq9L3A46AIyb+aHjjTbSYmB061cf6hzLSnmdh5xeACExjhxwsX9ivSvqGYcDNsH1JCM8EYQyRX9xAPDBYM1yuS8PpadqMluOcqOd/FFYyjYNpFrardblPsjUzZTz/TDSLyrYFDUKNa7pWIhW1asc1ZaY0ry0AoWnbl/QyMxqBjDFXd3mJfWccYsOI/Yrx3sxbZdL+ayRlQeQuDk/M9rQkH8GN/5+GE1aN5I6eVl0F37Axc/lLuIt/AIpoTwZYAEi9j/BYGLP6sYkjUp0foz91QximOTgu8evynu+nfAv330HVkipTIGOjEZea7QNSK0Fylxs8fanHlmiqWGyfyBeoWpxGslHZVu6K9k7GC8ABEIdNRa8vlqlphPfWPCS70Lnq3LgeKOj1C3sNF9ST8g7pth/0FEZgXruzhpx/EyjsasNbdLZg3iX1QwRS0P4L341Flrztovt8npyP9ytTiukkYIQzXCX8XuWjiaUuzXiLkVazjh0Nl03ikKKu2+7nuaBB92geBjbGT76zZ6HeXBgcmC7dWn7pHhzqu+QTonZK0oCl427Fs0eXiYsILjxFFQkmk7OHXgdZF9jquNXloz5lgwY9S3xj4JyRwLN/9xfh16awxLZNEFvX10X97bXsmNMRUDrJJPkKMTSxZpvuTbd+Lx2iB++4NyGZibNa6nOWOJG9d2LwEzIcIHS0uQpEIPl7Ccz6+rmkVh9kLbB2rda2fYp9GCOcn6XbfaXZZXJM+HAQwPJgrtDiuQex0tEIcQcB9CYCN4ze9HCt1kb23TUgEDAipz/RqYP4dOCYmRZ7vaYk/irJ+iRDfnvPK0Id1TrSeo5kaVc7py2zWZRVdndpTM8RvW0SLwdldXDIv+ym/mS0L7bchoaYjoNeuTNKQ6AOoc0E7f4ySr65FUKYd2FTvIsP2Avsa3S+D0za30ensxr733l80AQlVmUPrhsgOzzjEuOW1hGlGus38X+CDDEuMSJnq3hvz/CxVtAk71Zkbyr5lc1BPi758Y4rlZFQnhaKYKv5nSFJc7GtDykv+1cwxNGC6AxGKprnYMDVxuAIFYBztFitdO5BsjWvvKzAbleszewtGfjE2NgltIJk+gQlTpWvLNxd3gvb+qHarfEv7BPnPfsKktDpEfuNMKXdJPANyACq5gXj854o/X8iO2iLm7JSdMhEQgIIyHNyLCCQdLDnqDWIfcdyIzAfRilSCwImt3CVJBGD7HoXRbwGRR3vgEBcoVPmsYzaU9vr62I=",
"id": "75c178ee47aac3ab9e984ddb85bdf9d8c68ade0d97e9cd86bb39e3110218a589",
"sig": "aba8382cc8d6ba6bba467109d2ddc19718732fe803d71e73fd2db62c1cbbb1b4527447240906e01755139067a71c75d8c03271826ca5d0226c818cb7fb495fe2"
}]
[14:13:42.083] RECV localhost:8888: ["OK", "75c178ee47aac3ab9e984ddb85bdf9d8c68ade0d97e9cd86bb39e3110218a589", true, ""]

BIN
tests/sendDM Executable file

Binary file not shown.

296
tests/sendDM.c Normal file
View File

@@ -0,0 +1,296 @@
/*
* NIP-17 Private Direct Messages - Command Line Application
*
* This example demonstrates how to send NIP-17 private direct messages
* using the Nostr Core Library.
*
* Usage:
* ./send_nip17_dm -r <recipient> -s <sender> [-R <relay>]... <message>
*
* Options:
* -r <recipient>: The recipient's public key (npub or hex)
* -s <sender>: The sender's private key (nsec or hex)
* -R <relay>: Relay URL to send to (can be specified multiple times)
* <message>: The message to send (must be the last argument)
*
* If no relays are specified, uses default relay.
* If no sender key is provided, uses a default test key.
*
* Examples:
* ./send_nip17_dm -r npub1example... -s nsec1test... -R wss://relay1.com "Hello from NIP-17!"
* ./send_nip17_dm -r 4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa -s aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -R ws://localhost:8888 "config"
*/
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include "../nostr_core_lib/nostr_core/nostr_core.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
// Default test private key (for demonstration - DO NOT USE IN PRODUCTION)
#define DEFAULT_SENDER_NSEC "nsec12kgt0dv2k2safv6s32w8f89z9uw27e68hjaa0d66c5xvk70ezpwqncd045"
// Default relay for sending DMs
#define DEFAULT_RELAY "wss://relay.laantungir.net"
// Progress callback for publishing
void publish_progress_callback(const char* relay_url, const char* status,
const char* message, int success_count,
int total_relays, int completed_relays, void* user_data) {
(void)user_data;
if (relay_url) {
printf("📡 [%s]: %s", relay_url, status);
if (message) {
printf(" - %s", message);
}
printf(" (%d/%d completed, %d successful)\n", completed_relays, total_relays, success_count);
} else {
printf("📡 PUBLISH COMPLETE: %d/%d successful\n", success_count, total_relays);
}
}
/**
* Convert npub or hex pubkey to hex format
*/
int convert_pubkey_to_hex(const char* input_pubkey, char* output_hex) {
// Check if it's already hex (64 characters)
if (strlen(input_pubkey) == 64) {
// Assume it's already hex
strcpy(output_hex, input_pubkey);
return 0;
}
// Check if it's an npub (starts with "npub1")
if (strncmp(input_pubkey, "npub1", 5) == 0) {
// Convert npub to hex
unsigned char pubkey_bytes[32];
if (nostr_decode_npub(input_pubkey, pubkey_bytes) != 0) {
fprintf(stderr, "Error: Invalid npub format\n");
return -1;
}
nostr_bytes_to_hex(pubkey_bytes, 32, output_hex);
return 0;
}
fprintf(stderr, "Error: Public key must be 64-character hex or valid npub\n");
return -1;
}
/**
* Convert nsec to private key bytes if needed
*/
int convert_nsec_to_private_key(const char* input_nsec, unsigned char* private_key) {
// Check if it's already hex (64 characters)
if (strlen(input_nsec) == 64) {
// Convert hex to bytes
if (nostr_hex_to_bytes(input_nsec, private_key, 32) != 0) {
fprintf(stderr, "Error: Invalid hex private key\n");
return -1;
}
return 0;
}
// Check if it's an nsec (starts with "nsec1")
if (strncmp(input_nsec, "nsec1", 5) == 0) {
// Convert nsec directly to private key bytes
if (nostr_decode_nsec(input_nsec, private_key) != 0) {
fprintf(stderr, "Error: Invalid nsec format\n");
return -1;
}
return 0;
}
fprintf(stderr, "Error: Private key must be 64-character hex or valid nsec\n");
return -1;
}
/**
* Main function
*/
int main(int argc, char* argv[]) {
char* recipient_key = NULL;
char* sender_key = NULL;
char** relays = NULL;
int relay_count = 0;
char* message = NULL;
// Parse command line options
int opt;
while ((opt = getopt(argc, argv, "r:s:R:")) != -1) {
switch (opt) {
case 'r':
recipient_key = optarg;
break;
case 's':
sender_key = optarg;
break;
case 'R':
relays = realloc(relays, (relay_count + 1) * sizeof(char*));
relays[relay_count] = optarg;
relay_count++;
break;
default:
fprintf(stderr, "Usage: %s -r <recipient> -s <sender> [-R <relay>]... <message>\n", argv[0]);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -r <recipient>: The recipient's public key (npub or hex)\n");
fprintf(stderr, " -s <sender>: The sender's private key (nsec or hex)\n");
fprintf(stderr, " -R <relay>: Relay URL to send to (can be specified multiple times)\n");
fprintf(stderr, " <message>: The message to send (must be the last argument)\n");
return 1;
}
}
// Check for required arguments
if (!recipient_key) {
fprintf(stderr, "Error: Recipient key (-r) is required\n");
return 1;
}
// Get message from remaining arguments
if (optind >= argc) {
fprintf(stderr, "Error: Message is required\n");
return 1;
}
message = argv[optind];
// Use default values if not provided
if (!sender_key) {
sender_key = DEFAULT_SENDER_NSEC;
}
if (relay_count == 0) {
relays = malloc(sizeof(char*));
relays[0] = DEFAULT_RELAY;
relay_count = 1;
}
printf("🧪 NIP-17 Private Direct Message Sender\n");
printf("======================================\n\n");
// Initialize crypto
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize crypto\n");
free(relays);
return 1;
}
// Convert recipient pubkey
char recipient_pubkey_hex[65];
if (convert_pubkey_to_hex(recipient_key, recipient_pubkey_hex) != 0) {
free(relays);
return 1;
}
// Convert sender private key
unsigned char sender_privkey[32];
if (convert_nsec_to_private_key(sender_key, sender_privkey) != 0) {
free(relays);
return 1;
}
// Derive sender public key for display
unsigned char sender_pubkey_bytes[32];
char sender_pubkey_hex[65];
if (nostr_ec_public_key_from_private_key(sender_privkey, sender_pubkey_bytes) != 0) {
fprintf(stderr, "Failed to derive sender public key\n");
return 1;
}
nostr_bytes_to_hex(sender_pubkey_bytes, 32, sender_pubkey_hex);
printf("📤 Sender: %s\n", sender_pubkey_hex);
printf("📥 Recipient: %s\n", recipient_pubkey_hex);
printf("💬 Message: %s\n", message);
printf("🌐 Relays: ");
for (int i = 0; i < relay_count; i++) {
printf("%s", relays[i]);
if (i < relay_count - 1) printf(", ");
}
printf("\n\n");
// Create DM event
printf("💬 Creating DM event...\n");
const char* recipient_pubkeys[] = {recipient_pubkey_hex};
cJSON* dm_event = nostr_nip17_create_chat_event(
message,
recipient_pubkeys,
1,
"NIP-17 CLI", // subject
NULL, // no reply
relays[0], // relay hint (use first relay)
sender_pubkey_hex
);
if (!dm_event) {
fprintf(stderr, "Failed to create DM event\n");
return 1;
}
printf("✅ Created DM event (kind 14)\n");
// Send DM (create gift wraps)
printf("🎁 Creating gift wraps...\n");
cJSON* gift_wraps[10]; // Max 10 gift wraps
int gift_wrap_count = nostr_nip17_send_dm(
dm_event,
recipient_pubkeys,
1,
sender_privkey,
gift_wraps,
10
);
cJSON_Delete(dm_event); // Original DM event no longer needed
if (gift_wrap_count <= 0) {
fprintf(stderr, "Failed to create gift wraps\n");
return 1;
}
printf("✅ Created %d gift wrap(s)\n", gift_wrap_count);
// Publish the gift wrap to relays
printf("\n📤 Publishing gift wrap to %d relay(s)...\n", relay_count);
int success_count = 0;
publish_result_t* publish_results = synchronous_publish_event_with_progress(
(const char**)relays,
relay_count,
gift_wraps[0], // Send the first gift wrap
&success_count,
10, // 10 second timeout
publish_progress_callback,
NULL, // no user data
0, // NIP-42 disabled
NULL // no private key for auth
);
if (!publish_results || success_count == 0) {
fprintf(stderr, "\n❌ Failed to publish gift wrap to any relay (success_count: %d/%d)\n", success_count, relay_count);
// Clean up gift wraps
for (int i = 0; i < gift_wrap_count; i++) {
cJSON_Delete(gift_wraps[i]);
}
if (publish_results) free(publish_results);
free(relays);
return 1;
}
printf("\n✅ Successfully published NIP-17 DM to %d/%d relay(s)!\n", success_count, relay_count);
// Clean up
free(publish_results);
for (int i = 0; i < gift_wrap_count; i++) {
cJSON_Delete(gift_wraps[i]);
}
free(relays);
nostr_cleanup();
printf("\n🎉 DM sent successfully! The recipient can now decrypt it using their private key.\n");
return 0;
}