Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c08fae7ba8 |
@@ -31,6 +31,17 @@ int nt_publish(const char *event_json,
|
||||
int relay_count,
|
||||
int timeout_ms);
|
||||
|
||||
/*
|
||||
* Same as nt_publish_detailed(), but skips db relay-post logging.
|
||||
* Intended for background worker usage when DB handle is thread-affine.
|
||||
*/
|
||||
int nt_publish_detailed_nodb(const char *event_json,
|
||||
const char **relay_urls,
|
||||
int relay_count,
|
||||
int timeout_ms,
|
||||
nt_publish_result_t **results_out,
|
||||
int *result_count_out);
|
||||
|
||||
/* Free result array returned by nt_publish_detailed(). */
|
||||
void nt_publish_results_free(nt_publish_result_t *results, int result_count);
|
||||
|
||||
|
||||
@@ -13,4 +13,14 @@ int publish_signed_event_with_report(const char *label,
|
||||
cJSON *tags,
|
||||
int timeout_ms);
|
||||
|
||||
/*
|
||||
* Fire-and-forget publish wrapper.
|
||||
* Returns 0 when background job is started, -1 on immediate setup failure.
|
||||
*/
|
||||
int publish_signed_event_with_report_async(const char *label,
|
||||
int kind,
|
||||
const char *content,
|
||||
cJSON *tags,
|
||||
int timeout_ms);
|
||||
|
||||
#endif /* PUBLISH_H */
|
||||
|
||||
@@ -34,6 +34,7 @@ extern nt_state_t g_state;
|
||||
void state_init(void);
|
||||
void state_cleanup(void);
|
||||
int state_load_user_info(void);
|
||||
int state_load_user_info_async(void);
|
||||
void state_parse_relay_list(void);
|
||||
const char **state_get_read_relays(int *count);
|
||||
const char **state_get_write_relays(int *count);
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
*/
|
||||
#define NT_VERSION_MAJOR 0
|
||||
#define NT_VERSION_MINOR 0
|
||||
#define NT_VERSION_PATCH 14
|
||||
#define NT_VERSION "v0.0.14"
|
||||
#define NT_VERSION_PATCH 15
|
||||
#define NT_VERSION "v0.0.15"
|
||||
|
||||
#include <ncurses.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -364,12 +364,10 @@ void menu_login(void) {
|
||||
free(local_items);
|
||||
free(labels);
|
||||
|
||||
(void)state_load_user_info();
|
||||
|
||||
if (g_state.kind0_json && strcmp(g_state.kind0_json, "{}") == 0) {
|
||||
nt_log("No profile found on relays. Setting up new user...");
|
||||
menu_add_new_user();
|
||||
(void)state_load_user_info();
|
||||
if (state_load_user_info_async() != 0) {
|
||||
nt_log("Failed to start background user-info load.");
|
||||
} else {
|
||||
nt_log("Loading profile/relay data in background...");
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -418,7 +416,7 @@ void menu_login(void) {
|
||||
snprintf(endpoint_url, sizeof(endpoint_url), "%s", (saved_endpoint && saved_endpoint[0] != '\0') ? saved_endpoint : "");
|
||||
(void)menu_prompt("> Login > URL Signer",
|
||||
"Signer URL (http://<npub>.fips:8080)",
|
||||
endpoint_url,
|
||||
(saved_endpoint && saved_endpoint[0] != '\0') ? saved_endpoint : "",
|
||||
endpoint_url,
|
||||
sizeof(endpoint_url));
|
||||
|
||||
@@ -486,12 +484,10 @@ void menu_login(void) {
|
||||
|
||||
nt_log("Signed in via n_signer URL (%s) npub: %s", endpoint_url, g_state.npub_bech32);
|
||||
|
||||
(void)state_load_user_info();
|
||||
|
||||
if (g_state.kind0_json && strcmp(g_state.kind0_json, "{}") == 0) {
|
||||
nt_log("No profile found on relays. Setting up new user...");
|
||||
menu_add_new_user();
|
||||
(void)state_load_user_info();
|
||||
if (state_load_user_info_async() != 0) {
|
||||
nt_log("Failed to start background user-info load.");
|
||||
} else {
|
||||
nt_log("Loading profile/relay data in background...");
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -511,7 +507,7 @@ void menu_login(void) {
|
||||
|
||||
(void)menu_prompt("> Login > Qrexec Signer",
|
||||
"Target signer qube (nsigner-vault)",
|
||||
target_qube,
|
||||
(saved_target && saved_target[0] != '\0') ? saved_target : "nsigner-vault",
|
||||
target_qube,
|
||||
sizeof(target_qube));
|
||||
if (target_qube[0] == '\0') {
|
||||
@@ -520,7 +516,7 @@ void menu_login(void) {
|
||||
|
||||
(void)menu_prompt("> Login > Qrexec Signer",
|
||||
"Qrexec service (qubes.NsignerRpc)",
|
||||
service_name,
|
||||
"qubes.NsignerRpc",
|
||||
service_name,
|
||||
sizeof(service_name));
|
||||
if (service_name[0] == '\0') {
|
||||
@@ -567,12 +563,10 @@ void menu_login(void) {
|
||||
|
||||
nt_log("Signed in via qrexec n_signer (%s:%s) npub: %s", target_qube, service_name, g_state.npub_bech32);
|
||||
|
||||
(void)state_load_user_info();
|
||||
|
||||
if (g_state.kind0_json && strcmp(g_state.kind0_json, "{}") == 0) {
|
||||
nt_log("No profile found on relays. Setting up new user...");
|
||||
menu_add_new_user();
|
||||
(void)state_load_user_info();
|
||||
if (state_load_user_info_async() != 0) {
|
||||
nt_log("Failed to start background user-info load.");
|
||||
} else {
|
||||
nt_log("Loading profile/relay data in background...");
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -11,7 +11,7 @@ void menu_tweet(void) {
|
||||
TuiFrame frame = nt_frame("> Main Menu > Tweet");
|
||||
TuiStatus status = nt_status();
|
||||
char text[4096];
|
||||
int posted;
|
||||
int queued;
|
||||
|
||||
tuin_render_header(&frame);
|
||||
nt_print_reset();
|
||||
@@ -28,11 +28,12 @@ void menu_tweet(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
posted = publish_signed_event_with_report("Tweet", 1, text, NULL, 8000);
|
||||
queued = publish_signed_event_with_report_async("Tweet", 1, text, NULL, 8000);
|
||||
|
||||
if (posted < 0) {
|
||||
tuin_notice("Tweet publish failed.");
|
||||
} else {
|
||||
nt_log("Tweet published.");
|
||||
if (queued != 0) {
|
||||
tuin_notice("Tweet publish failed to start.");
|
||||
return;
|
||||
}
|
||||
|
||||
nt_log("Tweet queued; publishing in background.");
|
||||
}
|
||||
|
||||
97
src/net.c
97
src/net.c
@@ -3,6 +3,7 @@
|
||||
#include "db.h"
|
||||
#include "state.h"
|
||||
#include "signer.h"
|
||||
#include "tui.h"
|
||||
|
||||
#include "../resources/nostr_core_lib/cjson/cJSON.h"
|
||||
#include "../resources/nostr_core_lib/nostr_core/nip042.h"
|
||||
@@ -396,12 +397,13 @@ static int nt_wait_publish_ok(nostr_ws_client_t *client,
|
||||
}
|
||||
|
||||
/* Publish one event to each relay: connect -> EVENT -> OK -> close. */
|
||||
int nt_publish_detailed(const char *event_json,
|
||||
const char **relay_urls,
|
||||
int relay_count,
|
||||
int timeout_ms,
|
||||
nt_publish_result_t **results_out,
|
||||
int *result_count_out) {
|
||||
static int nt_publish_detailed_impl(const char *event_json,
|
||||
const char **relay_urls,
|
||||
int relay_count,
|
||||
int timeout_ms,
|
||||
int with_db_log,
|
||||
nt_publish_result_t **results_out,
|
||||
int *result_count_out) {
|
||||
cJSON *event = NULL;
|
||||
char *event_id = NULL;
|
||||
nt_publish_result_t *results = NULL;
|
||||
@@ -456,7 +458,9 @@ int nt_publish_detailed(const char *event_json,
|
||||
client = nostr_ws_connect(relay);
|
||||
if (!client) {
|
||||
response = nt_strdup_local("connect_failed");
|
||||
db_log_relay_post(relay, event_id, 0, response ? response : "connect_failed");
|
||||
if (with_db_log) {
|
||||
db_log_relay_post(relay, event_id, 0, response ? response : "connect_failed");
|
||||
}
|
||||
slot->posted = 0;
|
||||
slot->response = response;
|
||||
continue;
|
||||
@@ -466,7 +470,9 @@ int nt_publish_detailed(const char *event_json,
|
||||
|
||||
if (nostr_relay_send_event(client, event) != NOSTR_WS_SUCCESS) {
|
||||
response = nt_strdup_local("send_failed");
|
||||
db_log_relay_post(relay, event_id, 0, response ? response : "send_failed");
|
||||
if (with_db_log) {
|
||||
db_log_relay_post(relay, event_id, 0, response ? response : "send_failed");
|
||||
}
|
||||
slot->posted = 0;
|
||||
slot->response = response;
|
||||
nostr_ws_close(client);
|
||||
@@ -482,7 +488,9 @@ int nt_publish_detailed(const char *event_json,
|
||||
accepted_count++;
|
||||
}
|
||||
|
||||
db_log_relay_post(relay, event_id, posted, response ? response : "no_response");
|
||||
if (with_db_log) {
|
||||
db_log_relay_post(relay, event_id, posted, response ? response : "no_response");
|
||||
}
|
||||
|
||||
slot->posted = posted;
|
||||
slot->response = response;
|
||||
@@ -498,6 +506,36 @@ int nt_publish_detailed(const char *event_json,
|
||||
return accepted_count;
|
||||
}
|
||||
|
||||
int nt_publish_detailed(const char *event_json,
|
||||
const char **relay_urls,
|
||||
int relay_count,
|
||||
int timeout_ms,
|
||||
nt_publish_result_t **results_out,
|
||||
int *result_count_out) {
|
||||
return nt_publish_detailed_impl(event_json,
|
||||
relay_urls,
|
||||
relay_count,
|
||||
timeout_ms,
|
||||
1,
|
||||
results_out,
|
||||
result_count_out);
|
||||
}
|
||||
|
||||
int nt_publish_detailed_nodb(const char *event_json,
|
||||
const char **relay_urls,
|
||||
int relay_count,
|
||||
int timeout_ms,
|
||||
nt_publish_result_t **results_out,
|
||||
int *result_count_out) {
|
||||
return nt_publish_detailed_impl(event_json,
|
||||
relay_urls,
|
||||
relay_count,
|
||||
timeout_ms,
|
||||
0,
|
||||
results_out,
|
||||
result_count_out);
|
||||
}
|
||||
|
||||
int nt_publish(const char *event_json,
|
||||
const char **relay_urls,
|
||||
int relay_count,
|
||||
@@ -569,11 +607,10 @@ static __attribute__((unused)) int nt_query_one_relay(const char *relay_url,
|
||||
cJSON_AddItemToArray(req_msg, cJSON_Duplicate(filter, 1));
|
||||
{
|
||||
char *req_json = cJSON_PrintUnformatted(req_msg);
|
||||
fprintf(stderr,
|
||||
"%s: request to %s: %s\n",
|
||||
phase_label ? phase_label : "query",
|
||||
relay_url ? relay_url : "(unknown relay)",
|
||||
req_json ? req_json : "(serialize_failed)");
|
||||
nt_log("%s: request to %s: %s",
|
||||
phase_label ? phase_label : "query",
|
||||
relay_url ? relay_url : "(unknown relay)",
|
||||
req_json ? req_json : "(serialize_failed)");
|
||||
free(req_json);
|
||||
}
|
||||
cJSON_Delete(req_msg);
|
||||
@@ -601,11 +638,10 @@ static __attribute__((unused)) int nt_query_one_relay(const char *relay_url,
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stderr,
|
||||
"%s: response from %s: %s\n",
|
||||
phase_label ? phase_label : "query",
|
||||
relay_url ? relay_url : "(unknown relay)",
|
||||
buffer);
|
||||
nt_log("%s: response from %s: %s",
|
||||
phase_label ? phase_label : "query",
|
||||
relay_url ? relay_url : "(unknown relay)",
|
||||
buffer);
|
||||
}
|
||||
|
||||
if (nostr_parse_relay_message(buffer, &message_type, &parsed) != NOSTR_WS_SUCCESS) {
|
||||
@@ -619,11 +655,10 @@ static __attribute__((unused)) int nt_query_one_relay(const char *relay_url,
|
||||
if (cJSON_IsObject(event_obj)) {
|
||||
if (verbose) {
|
||||
char *received_event = cJSON_PrintUnformatted(event_obj);
|
||||
fprintf(stderr,
|
||||
"%s: event from %s: %s\n",
|
||||
phase_label ? phase_label : "query",
|
||||
relay_url ? relay_url : "(unknown relay)",
|
||||
received_event ? received_event : "(serialize_failed)");
|
||||
nt_log("%s: event from %s: %s",
|
||||
phase_label ? phase_label : "query",
|
||||
relay_url ? relay_url : "(unknown relay)",
|
||||
received_event ? received_event : "(serialize_failed)");
|
||||
free(received_event);
|
||||
}
|
||||
|
||||
@@ -716,10 +751,9 @@ int nt_query_sync_verbose(const char *filter_json,
|
||||
}
|
||||
|
||||
if (verbose && phase_label) {
|
||||
fprintf(stderr,
|
||||
"%s: querying %d relays via nostr_core relay pool\n",
|
||||
phase_label,
|
||||
relay_count);
|
||||
nt_log("%s: querying %d relays via nostr_core relay pool",
|
||||
phase_label,
|
||||
relay_count);
|
||||
}
|
||||
|
||||
pool_events = nostr_relay_pool_query_sync(pool,
|
||||
@@ -757,10 +791,9 @@ int nt_query_sync_verbose(const char *filter_json,
|
||||
free(pool_events);
|
||||
|
||||
if (verbose && phase_label) {
|
||||
fprintf(stderr,
|
||||
"%s: relay pool collected %d unique events\n",
|
||||
phase_label,
|
||||
events_n);
|
||||
nt_log("%s: relay pool collected %d unique events",
|
||||
phase_label,
|
||||
events_n);
|
||||
}
|
||||
|
||||
nostr_relay_pool_destroy(pool);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "tui.h"
|
||||
|
||||
#include <ncurses.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -16,9 +17,11 @@ static int g_body_row = 0;
|
||||
static char g_app_name[128] = "NOSTR TERMINAL";
|
||||
static char g_app_version[64] = "";
|
||||
static char g_user[256] = "";
|
||||
static char g_status_line[512] = "";
|
||||
static NtLogEntry g_log_entries[NT_LOG_MAX];
|
||||
static int g_log_head = 0;
|
||||
static int g_log_count = 0;
|
||||
static pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static WINDOW *nt_body_window(void) {
|
||||
return (WINDOW *)tuin_body_window();
|
||||
@@ -86,17 +89,6 @@ int nt_run_external_editor(int (*spawn)(void *user), void *user) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *nt_log_latest(void) {
|
||||
int idx;
|
||||
|
||||
if (g_log_count <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
idx = (g_log_head - 1 + NT_LOG_MAX) % NT_LOG_MAX;
|
||||
return g_log_entries[idx].text;
|
||||
}
|
||||
|
||||
TuiFrame nt_frame(const char *breadcrumb) {
|
||||
static char composed_title[512];
|
||||
TuiFrame frame;
|
||||
@@ -115,7 +107,15 @@ TuiFrame nt_frame(const char *breadcrumb) {
|
||||
|
||||
TuiStatus nt_status(void) {
|
||||
TuiStatus status;
|
||||
status.text = nt_log_latest();
|
||||
|
||||
pthread_mutex_lock(&g_log_mutex);
|
||||
if (g_status_line[0] == '\0' && g_log_count > 0) {
|
||||
int idx = (g_log_head - 1 + NT_LOG_MAX) % NT_LOG_MAX;
|
||||
snprintf(g_status_line, sizeof(g_status_line), "%s", g_log_entries[idx].text);
|
||||
}
|
||||
status.text = g_status_line;
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -160,13 +160,18 @@ void nt_log(const char *fmt, ...) {
|
||||
snprintf(ts, sizeof(ts), "[--:--:--]");
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&g_log_mutex);
|
||||
|
||||
idx = g_log_head;
|
||||
snprintf(g_log_entries[idx].text, sizeof(g_log_entries[idx].text), "%s %s", ts, msg);
|
||||
snprintf(g_status_line, sizeof(g_status_line), "%s", g_log_entries[idx].text);
|
||||
|
||||
g_log_head = (g_log_head + 1) % NT_LOG_MAX;
|
||||
if (g_log_count < NT_LOG_MAX) {
|
||||
g_log_count++;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
}
|
||||
|
||||
void nt_log_show(void) {
|
||||
@@ -177,6 +182,7 @@ void nt_log_show(void) {
|
||||
int i;
|
||||
|
||||
log_text[0] = '\0';
|
||||
pthread_mutex_lock(&g_log_mutex);
|
||||
for (i = 0; i < g_log_count; ++i) {
|
||||
int idx = (g_log_head - g_log_count + i + NT_LOG_MAX) % NT_LOG_MAX;
|
||||
int n = snprintf(log_text + pos, sizeof(log_text) - (size_t)pos, "%s%s",
|
||||
@@ -191,13 +197,17 @@ void nt_log_show(void) {
|
||||
}
|
||||
pos += n;
|
||||
}
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
|
||||
tuin_pager_run(&frame, log_text, &status);
|
||||
tuin_pager_run_ex(&frame, log_text, &status, 1);
|
||||
}
|
||||
|
||||
void nt_log_clear(void) {
|
||||
pthread_mutex_lock(&g_log_mutex);
|
||||
g_log_head = 0;
|
||||
g_log_count = 0;
|
||||
g_status_line[0] = '\0';
|
||||
pthread_mutex_unlock(&g_log_mutex);
|
||||
}
|
||||
|
||||
void nt_pager_show_text(const char *breadcrumb, const char *text) {
|
||||
|
||||
223
src/publish.c
223
src/publish.c
@@ -5,15 +5,109 @@
|
||||
#include "tui.h"
|
||||
#include "signer.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
int publish_signed_event_with_report(const char *label,
|
||||
int kind,
|
||||
const char *content,
|
||||
cJSON *tags,
|
||||
int timeout_ms) {
|
||||
typedef struct {
|
||||
char *label;
|
||||
char *event_json;
|
||||
char **relay_urls;
|
||||
int relay_count;
|
||||
int timeout_ms;
|
||||
} NtPublishJob;
|
||||
|
||||
static int publish_signed_event_with_report_impl(const char *label,
|
||||
int kind,
|
||||
const char *content,
|
||||
cJSON *tags,
|
||||
int timeout_ms,
|
||||
int with_db_log);
|
||||
|
||||
static char *publish_strdup_local(const char *s) {
|
||||
size_t n;
|
||||
char *out;
|
||||
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
n = strlen(s);
|
||||
out = (char *)malloc(n + 1U);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(out, s, n + 1U);
|
||||
return out;
|
||||
}
|
||||
|
||||
static void publish_job_free(NtPublishJob *job) {
|
||||
if (!job) {
|
||||
return;
|
||||
}
|
||||
free(job->label);
|
||||
free(job->event_json);
|
||||
if (job->relay_urls) {
|
||||
int i;
|
||||
for (i = 0; i < job->relay_count; i++) {
|
||||
free(job->relay_urls[i]);
|
||||
}
|
||||
free(job->relay_urls);
|
||||
}
|
||||
free(job);
|
||||
}
|
||||
|
||||
static void *publish_worker_main(void *arg) {
|
||||
NtPublishJob *job = (NtPublishJob *)arg;
|
||||
nt_publish_result_t *results = NULL;
|
||||
int result_count = 0;
|
||||
int accepted_count = 0;
|
||||
int i;
|
||||
|
||||
if (!job) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nt_log("%s: posting to %d relay(s)...", job->label, job->relay_count);
|
||||
|
||||
accepted_count = nt_publish_detailed_nodb(job->event_json,
|
||||
(const char **)job->relay_urls,
|
||||
job->relay_count,
|
||||
job->timeout_ms,
|
||||
&results,
|
||||
&result_count);
|
||||
|
||||
if (result_count <= 0) {
|
||||
nt_log("%s: no relay attempts were made.", job->label);
|
||||
publish_job_free(job);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < result_count; i++) {
|
||||
const char *relay = results[i].relay_url ? results[i].relay_url : "(unknown relay)";
|
||||
const char *response = results[i].response ? results[i].response : "(no response)";
|
||||
|
||||
if (results[i].posted) {
|
||||
nt_log("[OK] %s", relay);
|
||||
} else {
|
||||
nt_log("[FAIL] %s", relay);
|
||||
nt_log(" %s", response);
|
||||
}
|
||||
}
|
||||
|
||||
nt_log("%s: accepted by %d/%d relay(s).", job->label, accepted_count, result_count);
|
||||
nt_publish_results_free(results, result_count);
|
||||
publish_job_free(job);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int publish_signed_event_with_report_impl(const char *label,
|
||||
int kind,
|
||||
const char *content,
|
||||
cJSON *tags,
|
||||
int timeout_ms,
|
||||
int with_db_log) {
|
||||
char *event_json = NULL;
|
||||
const char **write_relays;
|
||||
int relay_count = 0;
|
||||
@@ -38,12 +132,19 @@ int publish_signed_event_with_report(const char *label,
|
||||
nt_log("%s", event_json);
|
||||
nt_log("Posting to %d relay(s)...", relay_count);
|
||||
|
||||
accepted_count = nt_publish_detailed(event_json,
|
||||
write_relays,
|
||||
relay_count,
|
||||
timeout_ms,
|
||||
&results,
|
||||
&result_count);
|
||||
accepted_count = with_db_log
|
||||
? nt_publish_detailed(event_json,
|
||||
write_relays,
|
||||
relay_count,
|
||||
timeout_ms,
|
||||
&results,
|
||||
&result_count)
|
||||
: nt_publish_detailed_nodb(event_json,
|
||||
write_relays,
|
||||
relay_count,
|
||||
timeout_ms,
|
||||
&results,
|
||||
&result_count);
|
||||
|
||||
free(event_json);
|
||||
|
||||
@@ -68,3 +169,103 @@ int publish_signed_event_with_report(const char *label,
|
||||
nt_publish_results_free(results, result_count);
|
||||
return accepted_count;
|
||||
}
|
||||
|
||||
int publish_signed_event_with_report(const char *label,
|
||||
int kind,
|
||||
const char *content,
|
||||
cJSON *tags,
|
||||
int timeout_ms) {
|
||||
return publish_signed_event_with_report_impl(label,
|
||||
kind,
|
||||
content,
|
||||
tags,
|
||||
timeout_ms,
|
||||
1);
|
||||
}
|
||||
|
||||
int publish_signed_event_with_report_async(const char *label,
|
||||
int kind,
|
||||
const char *content,
|
||||
cJSON *tags,
|
||||
int timeout_ms) {
|
||||
NtPublishJob *job;
|
||||
pthread_t tid;
|
||||
char *event_json = NULL;
|
||||
const char **write_relays = NULL;
|
||||
int relay_count = 0;
|
||||
int i;
|
||||
|
||||
if (!label || label[0] == '\0') {
|
||||
label = "Event";
|
||||
}
|
||||
|
||||
/* Sign synchronously on UI thread; only network publish happens in background. */
|
||||
if (signer_create_and_sign(kind, content ? content : "", tags, time(NULL), &event_json) != 0 || !event_json) {
|
||||
nt_log("%s: failed to serialize event.", label);
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_relays = state_get_write_relays(&relay_count);
|
||||
|
||||
job = (NtPublishJob *)calloc(1, sizeof(*job));
|
||||
if (!job) {
|
||||
free(event_json);
|
||||
return -1;
|
||||
}
|
||||
|
||||
job->label = publish_strdup_local(label);
|
||||
job->event_json = event_json;
|
||||
job->relay_count = relay_count;
|
||||
job->timeout_ms = timeout_ms;
|
||||
|
||||
if (relay_count > 0) {
|
||||
job->relay_urls = (char **)calloc((size_t)relay_count, sizeof(char *));
|
||||
if (!job->relay_urls) {
|
||||
publish_job_free(job);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < relay_count; i++) {
|
||||
const char *src = (write_relays && write_relays[i]) ? write_relays[i] : "";
|
||||
job->relay_urls[i] = publish_strdup_local(src);
|
||||
if (!job->relay_urls[i]) {
|
||||
publish_job_free(job);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!job->label || !job->event_json) {
|
||||
publish_job_free(job);
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
int has_attr = 0;
|
||||
|
||||
if (pthread_attr_init(&attr) == 0) {
|
||||
has_attr = 1;
|
||||
(void)pthread_attr_setstacksize(&attr, 1024U * 1024U);
|
||||
}
|
||||
|
||||
if (pthread_create(&tid, has_attr ? &attr : NULL, publish_worker_main, job) != 0) {
|
||||
if (has_attr) {
|
||||
(void)pthread_attr_destroy(&attr);
|
||||
}
|
||||
publish_job_free(job);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (has_attr) {
|
||||
(void)pthread_attr_destroy(&attr);
|
||||
}
|
||||
}
|
||||
|
||||
if (pthread_detach(tid) != 0) {
|
||||
publish_job_free(job);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
73
src/state.c
73
src/state.c
@@ -10,13 +10,19 @@
|
||||
#include "../resources/nostr_core_lib/nostr_core/nip044.h"
|
||||
#include "../resources/nostr_core_lib/nostr_core/utils.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "tui.h"
|
||||
|
||||
nt_state_t g_state;
|
||||
|
||||
static pthread_mutex_t g_user_info_load_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int g_user_info_loading = 0;
|
||||
|
||||
static char *state_strdup_local(const char *s) {
|
||||
size_t n;
|
||||
char *out;
|
||||
@@ -337,7 +343,7 @@ int state_load_user_info(void) {
|
||||
free(g_state.user_settings_json);
|
||||
g_state.user_settings_json = NULL;
|
||||
|
||||
fprintf(stderr, "Attempting to fetch kind 10002 relays from bootstrap relays\n");
|
||||
nt_log("Attempting to fetch kind 10002 relays from bootstrap relays");
|
||||
snprintf(filter,
|
||||
sizeof(filter),
|
||||
"{\"authors\":[\"%s\"],\"kinds\":[10002],\"limit\":1}",
|
||||
@@ -357,7 +363,7 @@ int state_load_user_info(void) {
|
||||
state_parse_relay_list();
|
||||
relays = state_get_read_relays(&relay_count);
|
||||
|
||||
fprintf(stderr, "Attempting to fetch kinds [0,3,10096,17375] from user relays\n");
|
||||
nt_log("Attempting to fetch kinds [0,3,10096,17375] from user relays");
|
||||
snprintf(filter,
|
||||
sizeof(filter),
|
||||
"{\"authors\":[\"%s\"],\"kinds\":[0,3,10096,17375],\"limit\":200}",
|
||||
@@ -424,7 +430,7 @@ int state_load_user_info(void) {
|
||||
free(kind10096_event);
|
||||
free(kind17375_event);
|
||||
|
||||
fprintf(stderr, "Attempting to fetch user-settings (kind 30078, d=user-settings)\n");
|
||||
nt_log("Attempting to fetch user-settings (kind 30078, d=user-settings)");
|
||||
snprintf(filter,
|
||||
sizeof(filter),
|
||||
"{\"authors\":[\"%s\"],\"kinds\":[30078],\"#d\":[\"user-settings\"],\"limit\":1}",
|
||||
@@ -453,14 +459,13 @@ int state_load_user_info(void) {
|
||||
free(settings_event_json);
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"Load summary: 10002=%s 0=%s 3=%s 10096=%s 17375=%s user_settings=%s\n",
|
||||
g_state.kind10002_json ? "ok" : "missing",
|
||||
(g_state.kind0_json && strcmp(g_state.kind0_json, "{}") != 0) ? "ok" : "missing",
|
||||
(g_state.kind3_json && strstr(g_state.kind3_json, "\"tags\"") != NULL) ? "ok" : "missing",
|
||||
(g_state.kind10096_json && strcmp(g_state.kind10096_json, "{}") != 0) ? "ok" : "missing",
|
||||
(g_state.kind17375_json && strcmp(g_state.kind17375_json, "{}") != 0) ? "ok" : "missing",
|
||||
g_state.user_settings_json ? "ok" : "missing");
|
||||
nt_log("Load summary: 10002=%s 0=%s 3=%s 10096=%s 17375=%s user_settings=%s",
|
||||
g_state.kind10002_json ? "ok" : "missing",
|
||||
(g_state.kind0_json && strcmp(g_state.kind0_json, "{}") != 0) ? "ok" : "missing",
|
||||
(g_state.kind3_json && strstr(g_state.kind3_json, "\"tags\"") != NULL) ? "ok" : "missing",
|
||||
(g_state.kind10096_json && strcmp(g_state.kind10096_json, "{}") != 0) ? "ok" : "missing",
|
||||
(g_state.kind17375_json && strcmp(g_state.kind17375_json, "{}") != 0) ? "ok" : "missing",
|
||||
g_state.user_settings_json ? "ok" : "missing");
|
||||
|
||||
snprintf(g_state.user_name, sizeof(g_state.user_name), "%s", "not logged in");
|
||||
if (g_state.kind0_json) {
|
||||
@@ -481,6 +486,52 @@ int state_load_user_info(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *state_user_info_load_worker(void *arg) {
|
||||
(void)arg;
|
||||
(void)state_load_user_info();
|
||||
|
||||
pthread_mutex_lock(&g_user_info_load_mutex);
|
||||
g_user_info_loading = 0;
|
||||
pthread_mutex_unlock(&g_user_info_load_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int state_load_user_info_async(void) {
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
int has_attr = 0;
|
||||
|
||||
pthread_mutex_lock(&g_user_info_load_mutex);
|
||||
if (g_user_info_loading) {
|
||||
pthread_mutex_unlock(&g_user_info_load_mutex);
|
||||
return 0;
|
||||
}
|
||||
g_user_info_loading = 1;
|
||||
pthread_mutex_unlock(&g_user_info_load_mutex);
|
||||
|
||||
if (pthread_attr_init(&attr) == 0) {
|
||||
has_attr = 1;
|
||||
(void)pthread_attr_setstacksize(&attr, 1024U * 1024U);
|
||||
}
|
||||
|
||||
if (pthread_create(&tid, has_attr ? &attr : NULL, state_user_info_load_worker, NULL) != 0) {
|
||||
if (has_attr) {
|
||||
(void)pthread_attr_destroy(&attr);
|
||||
}
|
||||
pthread_mutex_lock(&g_user_info_load_mutex);
|
||||
g_user_info_loading = 0;
|
||||
pthread_mutex_unlock(&g_user_info_load_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (has_attr) {
|
||||
(void)pthread_attr_destroy(&attr);
|
||||
}
|
||||
|
||||
(void)pthread_detach(tid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char **state_get_read_relays(int *count) {
|
||||
if (g_state.read_relay_count > 0 && g_state.read_relays) {
|
||||
if (count) {
|
||||
|
||||
Reference in New Issue
Block a user