Compare commits

...

1 Commits

6 changed files with 341 additions and 341 deletions

View File

@@ -3078,10 +3078,14 @@
messageDiv.className = 'log-entry';
const directionColor = direction === 'sent' ? '#007bff' : '#28a745';
// Convert newlines to <br> tags for proper HTML display
const formattedMessage = message.replace(/\n/g, '<br>');
messageDiv.innerHTML = `
<span class="log-timestamp">${timestamp}</span>
<span style="color: ${directionColor}; font-weight: bold;">[${direction.toUpperCase()}]</span>
${message}
<span style="white-space: pre-wrap;">${formattedMessage}</span>
`;
// Remove the "No messages received yet" placeholder if it exists

View File

@@ -1 +1 @@
1159431
1220948

View File

@@ -36,9 +36,13 @@ extern const char* get_tag_value(cJSON* event, const char* tag_name, int value_i
// Forward declarations for config functions
extern const char* get_relay_pubkey_cached(void);
extern char* get_relay_private_key(void);
extern const char* get_config_value(const char* key);
extern int get_config_bool(const char* key, int default_value);
extern const char* get_admin_pubkey_cached(void);
// Forward declarations for database functions
extern int store_event(cJSON* event);
extern int broadcast_event_to_subscriptions(cJSON* event);
// Forward declarations for stats generation
extern char* generate_stats_json(void);
@@ -315,6 +319,224 @@ char* generate_stats_json(void) {
return json_string;
}
// Unified NIP-17 response sender - handles all common response logic
int send_nip17_response(const char* sender_pubkey, const char* response_content,
char* error_message, size_t error_size) {
if (!sender_pubkey || !response_content || !error_message) {
if (error_message) {
strncpy(error_message, "NIP-17: Invalid parameters for response", error_size - 1);
}
return -1;
}
// Get relay keys for signing
const char* relay_pubkey = get_relay_pubkey_cached();
char* relay_privkey_hex = get_relay_private_key();
if (!relay_pubkey || !relay_privkey_hex) {
if (relay_privkey_hex) free(relay_privkey_hex);
strncpy(error_message, "NIP-17: Could not get relay keys for response", error_size - 1);
return -1;
}
// Convert relay private key to bytes
unsigned char relay_privkey[32];
if (nostr_hex_to_bytes(relay_privkey_hex, relay_privkey, sizeof(relay_privkey)) != 0) {
free(relay_privkey_hex);
strncpy(error_message, "NIP-17: Failed to convert relay private key for response", error_size - 1);
return -1;
}
free(relay_privkey_hex);
// Create DM response event using library function
cJSON* dm_response = nostr_nip17_create_chat_event(
response_content, // message content
(const char**)&sender_pubkey, // recipient pubkeys
1, // num recipients
NULL, // subject (optional)
NULL, // reply_to_event_id (optional)
NULL, // reply_relay_url (optional)
relay_pubkey // sender pubkey
);
if (!dm_response) {
strncpy(error_message, "NIP-17: Failed to create DM response event", error_size - 1);
return -1;
}
// Create and sign gift wrap using library function
cJSON* gift_wraps[1];
int send_result = nostr_nip17_send_dm(
dm_response, // dm_event
(const char**)&sender_pubkey, // recipient_pubkeys
1, // num_recipients
relay_privkey, // sender_private_key
gift_wraps, // gift_wraps_out
1 // max_gift_wraps
);
cJSON_Delete(dm_response);
if (send_result != 1 || !gift_wraps[0]) {
strncpy(error_message, "NIP-17: Failed to create and sign response gift wrap", error_size - 1);
return -1;
}
// Fix the p tag in the gift wrap - library function may use wrong pubkey
cJSON* gift_wrap_tags = cJSON_GetObjectItem(gift_wraps[0], "tags");
if (gift_wrap_tags && cJSON_IsArray(gift_wrap_tags)) {
// Find and replace the p tag with the correct user pubkey
cJSON* tag = NULL;
cJSON_ArrayForEach(tag, gift_wrap_tags) {
if (cJSON_IsArray(tag) && cJSON_GetArraySize(tag) >= 2) {
cJSON* tag_name = cJSON_GetArrayItem(tag, 0);
if (tag_name && cJSON_IsString(tag_name) &&
strcmp(cJSON_GetStringValue(tag_name), "p") == 0) {
// Replace the p tag value with the correct user pubkey
cJSON_ReplaceItemInArray(tag, 1, cJSON_CreateString(sender_pubkey));
log_info("NIP-17: Fixed p tag in response gift wrap");
break;
}
}
}
}
// Store the gift wrap in database
int store_result = store_event(gift_wraps[0]);
if (store_result != 0) {
cJSON_Delete(gift_wraps[0]);
strncpy(error_message, "NIP-17: Failed to store response gift wrap", error_size - 1);
return -1;
}
// Broadcast the response event to active subscriptions
int broadcast_count = broadcast_event_to_subscriptions(gift_wraps[0]);
char debug_broadcast_msg[128];
snprintf(debug_broadcast_msg, sizeof(debug_broadcast_msg),
"NIP-17: Response broadcast to %d subscriptions", broadcast_count);
log_info(debug_broadcast_msg);
cJSON_Delete(gift_wraps[0]);
return 0;
}
// Generate config text from database
char* generate_config_text(void) {
extern sqlite3* g_db;
if (!g_db) {
log_error("NIP-17: Database not available for config query");
return NULL;
}
// Build comprehensive config text from database
char* config_text = malloc(8192);
if (!config_text) {
log_error("NIP-17: Failed to allocate memory for config text");
return NULL;
}
int offset = 0;
// Header
offset += snprintf(config_text + offset, 8192 - offset,
"🔧 Relay Configuration\n"
"━━━━━━━━━━━━━━━━━━━━━━━━\n");
// Query all config values from database
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(g_db, "SELECT key, value FROM config ORDER BY key", -1, &stmt, NULL) == SQLITE_OK) {
while (sqlite3_step(stmt) == SQLITE_ROW && offset < 8192 - 200) {
const char* key = (const char*)sqlite3_column_text(stmt, 0);
const char* value = (const char*)sqlite3_column_text(stmt, 1);
if (key && value) {
offset += snprintf(config_text + offset, 8192 - offset,
"%s: %s\n", key, value);
}
}
sqlite3_finalize(stmt);
} else {
free(config_text);
log_error("NIP-17: Failed to query config from database");
return NULL;
}
// Footer
offset += snprintf(config_text + offset, 8192 - offset,
"\n✅ Configuration retrieved successfully");
return config_text;
}
// Generate human-readable stats text
char* generate_stats_text(void) {
char* stats_json = generate_stats_json();
if (!stats_json) {
log_error("NIP-17: Failed to generate stats for plain text command");
return NULL;
}
// Parse the JSON to extract values for human-readable format
cJSON* stats_obj = cJSON_Parse(stats_json);
char* stats_text = malloc(4096);
if (!stats_text) {
free(stats_json);
if (stats_obj) cJSON_Delete(stats_obj);
return NULL;
}
if (stats_obj) {
cJSON* total_events = cJSON_GetObjectItem(stats_obj, "total_events");
cJSON* db_size = cJSON_GetObjectItem(stats_obj, "database_size_bytes");
cJSON* time_stats = cJSON_GetObjectItem(stats_obj, "time_stats");
long long total = total_events ? (long long)cJSON_GetNumberValue(total_events) : 0;
long long db_bytes = db_size ? (long long)cJSON_GetNumberValue(db_size) : 0;
double db_mb = db_bytes / (1024.0 * 1024.0);
long long last_24h = 0, last_7d = 0, last_30d = 0;
if (time_stats) {
cJSON* h24 = cJSON_GetObjectItem(time_stats, "last_24h");
cJSON* d7 = cJSON_GetObjectItem(time_stats, "last_7d");
cJSON* d30 = cJSON_GetObjectItem(time_stats, "last_30d");
last_24h = h24 ? (long long)cJSON_GetNumberValue(h24) : 0;
last_7d = d7 ? (long long)cJSON_GetNumberValue(d7) : 0;
last_30d = d30 ? (long long)cJSON_GetNumberValue(d30) : 0;
}
snprintf(stats_text, 4096,
"📊 Relay Statistics\n"
"━━━━━━━━━━━━━━━━━━━━\n"
"Total Events: %lld\n"
"Database Size: %.2f MB (%lld bytes)\n"
"\n"
"📈 Recent Activity\n"
"━━━━━━━━━━━━━━━━━━━\n"
"Last 24 hours: %lld events\n"
"Last 7 days: %lld events\n"
"Last 30 days: %lld events\n"
"\n"
"✅ Statistics retrieved successfully",
total, db_mb, db_bytes, last_24h, last_7d, last_30d
);
cJSON_Delete(stats_obj);
} else {
// Fallback if JSON parsing fails
snprintf(stats_text, 4096,
"📊 Relay Statistics\n"
"━━━━━━━━━━━━━━━━━━━━\n"
"Raw data: %s\n"
"\n"
"⚠️ Could not parse statistics data",
stats_json
);
}
free(stats_json);
return stats_text;
}
// Main NIP-17 processing function
cJSON* process_nip17_admin_message(cJSON* gift_wrap_event, char* error_message, size_t error_size, struct lws* wsi) {
if (!gift_wrap_event || !error_message) {
@@ -375,8 +597,50 @@ cJSON* process_nip17_admin_message(cJSON* gift_wrap_event, char* error_message,
// Step 4: Process admin command
int result = process_nip17_admin_command(inner_dm, error_message, error_size, wsi);
// Step 5: Create response if command was processed successfully
// Step 5: For plain text commands (stats/config), the response is already handled
// Only create a generic response for other command types that don't handle their own responses
if (result == 0) {
// Extract content to check if it's a plain text command
cJSON* content_obj = cJSON_GetObjectItem(inner_dm, "content");
if (content_obj && cJSON_IsString(content_obj)) {
const char* dm_content = cJSON_GetStringValue(content_obj);
// Check if it's a plain text command that already handled its response
char content_lower[256];
size_t content_len = strlen(dm_content);
size_t copy_len = content_len < sizeof(content_lower) - 1 ? content_len : sizeof(content_lower) - 1;
memcpy(content_lower, dm_content, copy_len);
content_lower[copy_len] = '\0';
// Convert to lowercase
for (size_t i = 0; i < copy_len; i++) {
if (content_lower[i] >= 'A' && content_lower[i] <= 'Z') {
content_lower[i] = content_lower[i] + 32;
}
}
// If it's a plain text stats or config command, don't create additional response
if (strstr(content_lower, "stats") != NULL || strstr(content_lower, "statistics") != NULL ||
strstr(content_lower, "config") != NULL || strstr(content_lower, "configuration") != NULL) {
log_info("NIP-17: Plain text command already handled response, skipping generic response");
cJSON_Delete(inner_dm);
return NULL; // No additional response needed
}
// Check if it's a JSON array command that might be stats
cJSON* command_array = cJSON_Parse(dm_content);
if (command_array && cJSON_IsArray(command_array) && cJSON_GetArraySize(command_array) > 0) {
cJSON* first_item = cJSON_GetArrayItem(command_array, 0);
if (cJSON_IsString(first_item) && strcmp(cJSON_GetStringValue(first_item), "stats") == 0) {
log_info("NIP-17: JSON stats command already handled response, skipping generic response");
cJSON_Delete(command_array);
cJSON_Delete(inner_dm);
return NULL; // No additional response needed
}
cJSON_Delete(command_array);
}
}
// Get sender pubkey for response from the decrypted DM event
cJSON* sender_pubkey_obj = cJSON_GetObjectItem(inner_dm, "pubkey");
if (sender_pubkey_obj && cJSON_IsString(sender_pubkey_obj)) {
@@ -557,112 +821,20 @@ int process_nip17_admin_command(cJSON* dm_event, char* error_message, size_t err
log_info("NIP-17: Recognized plain text 'stats' command from admin");
log_info("NIP-17: Action: Generate and send relay statistics");
// Generate stats JSON
char* stats_json = generate_stats_json();
if (!stats_json) {
log_error("NIP-17: Failed to generate stats for plain text command");
char* stats_text = generate_stats_text();
if (!stats_text) {
return -1;
}
// Get relay keys for signing
const char* relay_pubkey = get_relay_pubkey_cached();
char* relay_privkey_hex = get_relay_private_key();
if (!relay_pubkey || !relay_privkey_hex) {
free(stats_json);
log_error("NIP-17: Could not get relay keys for stats response");
char error_msg[256];
int result = send_nip17_response(sender_pubkey, stats_text, error_msg, sizeof(error_msg));
free(stats_text);
if (result != 0) {
log_error(error_msg);
return -1;
}
// Convert relay private key to bytes
unsigned char relay_privkey[32];
if (nostr_hex_to_bytes(relay_privkey_hex, relay_privkey, sizeof(relay_privkey)) != 0) {
free(stats_json);
free(relay_privkey_hex);
log_error("NIP-17: Failed to convert relay private key for stats response");
return -1;
}
free(relay_privkey_hex);
// Create DM response event using library function
cJSON* dm_response = nostr_nip17_create_chat_event(
stats_json, // message content
(const char**)&sender_pubkey, // recipient pubkeys
1, // num recipients
NULL, // subject (optional)
NULL, // reply_to_event_id (optional)
NULL, // reply_relay_url (optional)
relay_pubkey // sender pubkey
);
free(stats_json);
if (!dm_response) {
log_error("NIP-17: Failed to create DM response event for stats");
return -1;
}
// Create and sign gift wrap using library function
cJSON* gift_wraps[1];
int send_result = nostr_nip17_send_dm(
dm_response, // dm_event
(const char**)&sender_pubkey, // recipient_pubkeys
1, // num_recipients
relay_privkey, // sender_private_key
gift_wraps, // gift_wraps_out
1 // max_gift_wraps
);
cJSON_Delete(dm_response);
if (send_result != 1 || !gift_wraps[0]) {
log_error("NIP-17: Failed to create and sign response gift wrap for stats");
return -1;
}
// Fix the p tag in the gift wrap - library function may use wrong pubkey
cJSON* gift_wrap_tags = cJSON_GetObjectItem(gift_wraps[0], "tags");
if (gift_wrap_tags && cJSON_IsArray(gift_wrap_tags)) {
// Find and replace the p tag with the correct user pubkey
cJSON* tag = NULL;
cJSON_ArrayForEach(tag, gift_wrap_tags) {
if (cJSON_IsArray(tag) && cJSON_GetArraySize(tag) >= 2) {
cJSON* tag_name = cJSON_GetArrayItem(tag, 0);
if (tag_name && cJSON_IsString(tag_name) &&
strcmp(cJSON_GetStringValue(tag_name), "p") == 0) {
// Replace the p tag value with the correct user pubkey
cJSON_ReplaceItemInArray(tag, 1, cJSON_CreateString(sender_pubkey));
log_info("NIP-17: Fixed p tag in stats response gift wrap");
break;
}
}
}
}
// Debug print to show the response event
char* response_debug = cJSON_Print(gift_wraps[0]);
if (response_debug) {
log_info("DM Admin: Response event created");
printf(" Response event: %s\n", response_debug);
free(response_debug);
}
// Debug: Print event before storing
char* debug_before_store = cJSON_Print(gift_wraps[0]);
if (debug_before_store) {
log_info("DEBUG EVENT: Before storing in database");
printf(" Event: %s\n", debug_before_store);
free(debug_before_store);
}
// Store the gift wrap in database
int store_result = store_event(gift_wraps[0]);
cJSON_Delete(gift_wraps[0]);
if (store_result != 0) {
log_error("NIP-17: Failed to store response gift wrap for stats");
return -1;
}
log_success("NIP-17: Stats command processed successfully, response sent");
return 0;
}
@@ -671,129 +843,20 @@ int process_nip17_admin_command(cJSON* dm_event, char* error_message, size_t err
log_info("NIP-17: Recognized plain text 'config' command from admin");
log_info("NIP-17: Action: Generate and send relay configuration");
// Get relay pubkey for config response
const char* relay_pubkey = get_relay_pubkey_cached();
// Generate config JSON - for now, use a simple config summary
cJSON* config_response = cJSON_CreateObject();
cJSON_AddStringToObject(config_response, "command", "config");
cJSON_AddStringToObject(config_response, "relay_pubkey", relay_pubkey ? relay_pubkey : "unknown");
// Add some basic config values
const char* port = get_config_value("relay_port");
const char* nip42_auth = get_config_bool("nip42_auth_required_events", 0) ? "enabled" : "disabled";
const char* nip42_sub = get_config_bool("nip42_auth_required_subscriptions", 0) ? "enabled" : "disabled";
cJSON_AddStringToObject(config_response, "relay_port", port ? port : "8888");
cJSON_AddStringToObject(config_response, "nip42_auth_events", nip42_auth);
cJSON_AddStringToObject(config_response, "nip42_auth_subscriptions", nip42_sub);
char* config_json = cJSON_Print(config_response);
cJSON_Delete(config_response);
if (!config_json) {
log_error("NIP-17: Failed to generate config JSON for plain text command");
char* config_text = generate_config_text();
if (!config_text) {
return -1;
}
// Get relay keys for signing
char* relay_privkey_hex = get_relay_private_key();
if (!relay_privkey_hex) {
free(config_json);
log_error("NIP-17: Could not get relay private key for config response");
char error_msg[256];
int result = send_nip17_response(sender_pubkey, config_text, error_msg, sizeof(error_msg));
free(config_text);
if (result != 0) {
log_error(error_msg);
return -1;
}
// Convert relay private key to bytes
unsigned char relay_privkey[32];
if (nostr_hex_to_bytes(relay_privkey_hex, relay_privkey, sizeof(relay_privkey)) != 0) {
free(config_json);
free(relay_privkey_hex);
log_error("NIP-17: Failed to convert relay private key for config response");
return -1;
}
free(relay_privkey_hex);
// Create DM response event using library function
cJSON* dm_response = nostr_nip17_create_chat_event(
config_json, // message content
(const char**)&sender_pubkey, // recipient pubkeys
1, // num recipients
NULL, // subject (optional)
NULL, // reply_to_event_id (optional)
NULL, // reply_relay_url (optional)
relay_pubkey // sender pubkey (already declared above)
);
free(config_json);
if (!dm_response) {
log_error("NIP-17: Failed to create DM response event for config");
return -1;
}
// Create and sign gift wrap using library function
cJSON* gift_wraps[1];
int send_result = nostr_nip17_send_dm(
dm_response, // dm_event
(const char**)&sender_pubkey, // recipient_pubkeys
1, // num_recipients
relay_privkey, // sender_private_key
gift_wraps, // gift_wraps_out
1 // max_gift_wraps
);
cJSON_Delete(dm_response);
if (send_result != 1 || !gift_wraps[0]) {
log_error("NIP-17: Failed to create and sign response gift wrap for config");
return -1;
}
// Fix the p tag in the gift wrap - library function may use wrong pubkey
cJSON* gift_wrap_tags = cJSON_GetObjectItem(gift_wraps[0], "tags");
if (gift_wrap_tags && cJSON_IsArray(gift_wrap_tags)) {
// Find and replace the p tag with the correct user pubkey
cJSON* tag = NULL;
cJSON_ArrayForEach(tag, gift_wrap_tags) {
if (cJSON_IsArray(tag) && cJSON_GetArraySize(tag) >= 2) {
cJSON* tag_name = cJSON_GetArrayItem(tag, 0);
if (tag_name && cJSON_IsString(tag_name) &&
strcmp(cJSON_GetStringValue(tag_name), "p") == 0) {
// Replace the p tag value with the correct user pubkey
cJSON_ReplaceItemInArray(tag, 1, cJSON_CreateString(sender_pubkey));
log_info("NIP-17: Fixed p tag in config response gift wrap");
break;
}
}
}
}
// Debug: Print event after p tag fix
char* debug_after_fix = cJSON_Print(gift_wraps[0]);
if (debug_after_fix) {
log_info("DEBUG EVENT: After p tag fix");
printf(" Event: %s\n", debug_after_fix);
free(debug_after_fix);
}
// Debug print to show the response event
char* response_debug = cJSON_Print(gift_wraps[0]);
if (response_debug) {
log_info("DM Admin: Response event created");
printf(" Response event: %s\n", response_debug);
free(response_debug);
}
// Store the gift wrap in database
int store_result = store_event(gift_wraps[0]);
cJSON_Delete(gift_wraps[0]);
if (store_result != 0) {
log_error("NIP-17: Failed to store response gift wrap for config");
return -1;
}
log_success("NIP-17: Config command processed successfully, response sent");
return 0;
}
@@ -814,7 +877,16 @@ int process_nip17_admin_command(cJSON* dm_event, char* error_message, size_t err
if (cJSON_IsString(first_item) && strcmp(cJSON_GetStringValue(first_item), "stats") == 0) {
log_info("NIP-17: Processing 'stats' command directly");
// Generate stats JSON
// Get sender pubkey for response
cJSON* sender_pubkey_obj = cJSON_GetObjectItem(dm_event, "pubkey");
if (!sender_pubkey_obj || !cJSON_IsString(sender_pubkey_obj)) {
cJSON_Delete(command_array);
strncpy(error_message, "NIP-17: DM missing sender pubkey", error_size - 1);
return -1;
}
const char* sender_pubkey = cJSON_GetStringValue(sender_pubkey_obj);
// Generate stats JSON (for JSON array commands, use JSON format)
char* stats_json = generate_stats_json();
if (!stats_json) {
cJSON_Delete(command_array);
@@ -822,114 +894,17 @@ int process_nip17_admin_command(cJSON* dm_event, char* error_message, size_t err
return -1;
}
// Get sender pubkey for response
cJSON* sender_pubkey_obj = cJSON_GetObjectItem(dm_event, "pubkey");
if (!sender_pubkey_obj || !cJSON_IsString(sender_pubkey_obj)) {
free(stats_json);
cJSON_Delete(command_array);
strncpy(error_message, "NIP-17: DM missing sender pubkey", error_size - 1);
return -1;
}
const char* sender_pubkey = cJSON_GetStringValue(sender_pubkey_obj);
// Get relay keys for signing
const char* relay_pubkey = get_relay_pubkey_cached();
char* relay_privkey_hex = get_relay_private_key();
if (!relay_pubkey || !relay_privkey_hex) {
free(stats_json);
cJSON_Delete(command_array);
if (relay_privkey_hex) free(relay_privkey_hex);
strncpy(error_message, "NIP-17: Could not get relay keys", error_size - 1);
return -1;
}
// Convert relay private key to bytes
unsigned char relay_privkey[32];
if (nostr_hex_to_bytes(relay_privkey_hex, relay_privkey, sizeof(relay_privkey)) != 0) {
free(stats_json);
free(relay_privkey_hex);
cJSON_Delete(command_array);
strncpy(error_message, "NIP-17: Failed to convert relay private key", error_size - 1);
return -1;
}
free(relay_privkey_hex);
// Create DM response event using library function
cJSON* dm_response = nostr_nip17_create_chat_event(
stats_json, // message content
(const char**)&sender_pubkey, // recipient pubkeys
1, // num recipients
NULL, // subject (optional)
NULL, // reply_to_event_id (optional)
NULL, // reply_relay_url (optional)
relay_pubkey // sender pubkey
);
char error_msg[256];
int result = send_nip17_response(sender_pubkey, stats_json, error_msg, sizeof(error_msg));
free(stats_json);
if (!dm_response) {
cJSON_Delete(command_array);
strncpy(error_message, "NIP-17: Failed to create DM response event", error_size - 1);
return -1;
}
// Create and sign gift wrap using library function
cJSON* gift_wraps[1];
int send_result = nostr_nip17_send_dm(
dm_response, // dm_event
(const char**)&sender_pubkey, // recipient_pubkeys
1, // num_recipients
relay_privkey, // sender_private_key
gift_wraps, // gift_wraps_out
1 // max_gift_wraps
);
cJSON_Delete(dm_response);
if (send_result != 1 || !gift_wraps[0]) {
cJSON_Delete(command_array);
strncpy(error_message, "NIP-17: Failed to create and sign response gift wrap", error_size - 1);
return -1;
}
// Fix the p tag in the gift wrap - library function may use wrong pubkey
cJSON* gift_wrap_tags = cJSON_GetObjectItem(gift_wraps[0], "tags");
if (gift_wrap_tags && cJSON_IsArray(gift_wrap_tags)) {
// Find and replace the p tag with the correct user pubkey
cJSON* tag = NULL;
cJSON_ArrayForEach(tag, gift_wrap_tags) {
if (cJSON_IsArray(tag) && cJSON_GetArraySize(tag) >= 2) {
cJSON* tag_name = cJSON_GetArrayItem(tag, 0);
if (tag_name && cJSON_IsString(tag_name) &&
strcmp(cJSON_GetStringValue(tag_name), "p") == 0) {
// Replace the p tag value with the correct user pubkey
cJSON_ReplaceItemInArray(tag, 1, cJSON_CreateString(sender_pubkey));
log_info("NIP-17: Fixed p tag in JSON array stats response gift wrap");
break;
}
}
}
}
// Debug print to show the response event
char* response_debug = cJSON_Print(gift_wraps[0]);
if (response_debug) {
log_info("DM Admin: Response event created");
printf(" Response event: %s\n", response_debug);
free(response_debug);
}
// Store the gift wrap in database
int store_result = store_event(gift_wraps[0]);
cJSON_Delete(gift_wraps[0]);
if (store_result != 0) {
cJSON_Delete(command_array);
strncpy(error_message, "NIP-17: Failed to store response gift wrap", error_size - 1);
return -1;
}
cJSON_Delete(command_array);
if (result != 0) {
log_error(error_msg);
strncpy(error_message, error_msg, error_size - 1);
return -1;
}
log_success("NIP-17: Stats command processed successfully");
return 0;
}

View File

@@ -18,4 +18,10 @@ int process_nip17_admin_command(cJSON* dm_event, char* error_message, size_t err
int is_nip17_gift_wrap_for_relay(cJSON* gift_wrap_event);
char* generate_stats_json(void);
// Unified NIP-17 response functions
int send_nip17_response(const char* sender_pubkey, const char* response_content,
char* error_message, size_t error_size);
char* generate_config_text(void);
char* generate_stats_text(void);
#endif // DM_ADMIN_H

File diff suppressed because one or more lines are too long

View File

@@ -644,17 +644,32 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
cJSON* response_event = process_nip17_admin_message(event, nip17_error, sizeof(nip17_error), wsi);
if (!response_event) {
log_error("DEBUG NIP17: NIP-17 admin message processing failed");
result = -1;
size_t error_len = strlen(nip17_error);
size_t copy_len = (error_len < sizeof(error_message) - 1) ? error_len : sizeof(error_message) - 1;
memcpy(error_message, nip17_error, copy_len);
error_message[copy_len] = '\0';
// Check if this is an error or if the command was already handled
if (strlen(nip17_error) > 0) {
// There was an actual error
log_error("DEBUG NIP17: NIP-17 admin message processing failed");
result = -1;
size_t error_len = strlen(nip17_error);
size_t copy_len = (error_len < sizeof(error_message) - 1) ? error_len : sizeof(error_message) - 1;
memcpy(error_message, nip17_error, copy_len);
error_message[copy_len] = '\0';
char debug_nip17_error_msg[600];
snprintf(debug_nip17_error_msg, sizeof(debug_nip17_error_msg),
"DEBUG NIP17 ERROR: %.400s", nip17_error);
log_error(debug_nip17_error_msg);
char debug_nip17_error_msg[600];
snprintf(debug_nip17_error_msg, sizeof(debug_nip17_error_msg),
"DEBUG NIP17 ERROR: %.400s", nip17_error);
log_error(debug_nip17_error_msg);
} else {
// No error message means the command was already handled (plain text commands)
log_success("DEBUG NIP17: NIP-17 admin message processed successfully (already handled)");
// Store the original gift wrap event in database
if (store_event(event) != 0) {
log_error("DEBUG NIP17: Failed to store gift wrap event in database");
result = -1;
strncpy(error_message, "error: failed to store gift wrap event", sizeof(error_message) - 1);
} else {
log_info("DEBUG NIP17: Gift wrap event stored successfully in database");
}
}
} else {
log_success("DEBUG NIP17: NIP-17 admin message processed successfully");
// Store the original gift wrap event in database (unlike kind 23456)