forked from coracle/caravel
Publish metadata on startup
This commit is contained in:
+10
-1
@@ -37,6 +37,9 @@ Environment variables:
|
||||
| `RELAY_DOMAIN` | Relay base domain for subdomains | `spaces.coracle.social` |
|
||||
| `NWC_URL` | Platform NWC URL for invoice generation | _required for billing_ |
|
||||
| `NOSTR_INDEXER_RELAYS` | Comma-separated relays to fetch kind `10050` DM relays | _required for notifications_ |
|
||||
| `PLATFORM_NAME` | Platform display name for kind `0` metadata | _optional_ |
|
||||
| `PLATFORM_DESCRIPTION` | Platform description for kind `0` metadata | _optional_ |
|
||||
| `PLATFORM_MESSAGING_RELAYS` | Comma-separated relays published in kind `10050` | _optional_ |
|
||||
|
||||
The database directory is created automatically if it doesn’t exist.
|
||||
|
||||
@@ -82,6 +85,13 @@ The backend runs an in-process billing loop that:
|
||||
- Sends NIP-17 DMs with invoices when recurring is off
|
||||
- Sends NIP-17 DMs on successful payment when recurring is on
|
||||
|
||||
On startup, the backend publishes:
|
||||
|
||||
- Kind `0` metadata (name/description)
|
||||
- Kind `10050` relay list for DMs
|
||||
|
||||
These are published to the relays listed in `NOSTR_INDEXER_RELAYS`.
|
||||
|
||||
## API Routes
|
||||
|
||||
Tenant routes (all require NIP-98 auth; pubkey is inferred from the token):
|
||||
@@ -108,4 +118,3 @@ Admin routes (all require NIP-98 auth; pubkey must be in `HOSTING_ADMIN_PUBKEYS`
|
||||
## Next Steps
|
||||
|
||||
- Add invoice generation and billing jobs
|
||||
- On start, publish kind 0, 10002, 10050 to indexer relays based on env vars
|
||||
|
||||
@@ -11,6 +11,9 @@ pub struct Config {
|
||||
pub relay_domain: String,
|
||||
pub platform_nwc_url: String,
|
||||
pub indexer_relays: Vec<String>,
|
||||
pub platform_name: String,
|
||||
pub platform_description: String,
|
||||
pub platform_messaging_relays: Vec<String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -40,6 +43,14 @@ impl Config {
|
||||
.map(|v| v.trim().to_string())
|
||||
.filter(|v| !v.is_empty())
|
||||
.collect::<Vec<_>>();
|
||||
let platform_name = env::var("PLATFORM_NAME").unwrap_or_default();
|
||||
let platform_description = env::var("PLATFORM_DESCRIPTION").unwrap_or_default();
|
||||
let platform_messaging_relays = env::var("PLATFORM_MESSAGING_RELAYS")
|
||||
.unwrap_or_default()
|
||||
.split(',')
|
||||
.map(|v| v.trim().to_string())
|
||||
.filter(|v| !v.is_empty())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Self {
|
||||
database_url,
|
||||
@@ -51,6 +62,9 @@ impl Config {
|
||||
relay_domain,
|
||||
platform_nwc_url,
|
||||
indexer_relays,
|
||||
platform_name,
|
||||
platform_description,
|
||||
platform_messaging_relays,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ mod config;
|
||||
mod db;
|
||||
mod models;
|
||||
mod notifications;
|
||||
mod platform;
|
||||
mod provisioning;
|
||||
mod repo;
|
||||
|
||||
@@ -20,6 +21,7 @@ use crate::config::Config;
|
||||
use crate::db::init_pool;
|
||||
use crate::billing::BillingService;
|
||||
use crate::notifications::Nip17Notifier;
|
||||
use crate::platform::publish_platform_identity;
|
||||
use crate::provisioning::Provisioner;
|
||||
use crate::repo::Repo;
|
||||
|
||||
@@ -35,6 +37,14 @@ async fn main() -> Result<()> {
|
||||
|
||||
let pool = init_pool(&config.database_url).await?;
|
||||
let repo = Repo::new(pool);
|
||||
publish_platform_identity(
|
||||
&config.platform_secret,
|
||||
&config.indexer_relays,
|
||||
&config.platform_name,
|
||||
&config.platform_description,
|
||||
&config.platform_messaging_relays,
|
||||
)
|
||||
.await?;
|
||||
let notifier = Nip17Notifier::new(config.platform_secret.clone(), config.indexer_relays.clone()).await?;
|
||||
let billing = BillingService::new(
|
||||
repo.clone(),
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use nostr_sdk::prelude::*;
|
||||
|
||||
pub async fn publish_platform_identity(
|
||||
platform_secret: &str,
|
||||
indexer_relays: &[String],
|
||||
name: &str,
|
||||
description: &str,
|
||||
messaging_relays: &[String],
|
||||
) -> Result<()> {
|
||||
if indexer_relays.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if platform_secret.trim().is_empty() {
|
||||
return Err(anyhow!("PLATFORM_SECRET is required for platform identity"));
|
||||
}
|
||||
|
||||
let keys = Keys::parse(platform_secret)?;
|
||||
let client = Client::new(keys);
|
||||
|
||||
for relay in indexer_relays {
|
||||
client.add_relay(relay).await?;
|
||||
}
|
||||
|
||||
client.connect().await;
|
||||
|
||||
let mut metadata = Metadata::new();
|
||||
if !name.is_empty() {
|
||||
metadata = metadata.name(name);
|
||||
}
|
||||
if !description.is_empty() {
|
||||
metadata = metadata.about(description);
|
||||
}
|
||||
|
||||
let metadata_builder = EventBuilder::metadata(&metadata);
|
||||
client.send_event_builder(metadata_builder).await?;
|
||||
|
||||
if messaging_relays.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut tags = Vec::new();
|
||||
for relay in messaging_relays {
|
||||
let tag = Tag::parse(["relay", relay.as_str()])?;
|
||||
tags.push(tag);
|
||||
}
|
||||
|
||||
let relay_builder = EventBuilder::new(Kind::Custom(10050), "").tags(tags);
|
||||
client.send_event_builder(relay_builder).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user