use super::route_prelude::*;
use nostr::nips::nip46::NostrConnectURI;
use nostr_connect::prelude::*;
use nostr_sdk::prelude::*;
use std::sync::Arc;
#[derive(Template)]
#[template(path = "connect/index.gmi", escape = "txt")]
pub struct NostrConnectTemplate {}
#[derive(Template)]
#[template(path = "connect/success.gmi", escape = "txt")]
pub struct NostrConnectSuccessTemplate {}
#[derive(Template)]
#[template(path = "connect/failure.gmi", escape = "txt")]
pub struct NostrConnectFailureTemplate {}
#[derive(Template)]
#[template(path = "connect/direct.gmi", escape = "txt")]
pub struct NostrConnectClientInitTemplate<'a> {
pub uri: &'a NostrConnectURI,
}
pub async fn nostr_connect_index(
_ctx: RouteContext,
_user: &'static mut CaracalUser,
) -> Response {
Response::success(WindTemplate::render(NostrConnectTemplate {}))
}
fn ask_bunker_uri() -> Response {
Response::input(t!("input_bunker_uri"))
}
pub async fn nostr_connect_bunker(
ctx: RouteContext,
user: &'static mut CaracalUser,
) -> Response {
let Ok(client_keys) = user.get_client_keys() else {
return Response::temporary_failure("Client keys error");
};
let config = user.nostr_config();
match ctx.action() {
Action::New => {
if let Some(input_uri) = dec_urlq(&ctx.url) {
if let Ok(uri) = NostrConnectURI::parse(&input_uri) {
let connect_string = uri.to_string();
if let Ok(signer) = NostrConnect::new(
uri.clone(),
client_keys,
std::time::Duration::from_secs(20),
None,
) {
let mut nostr_config = user.nostr_config();
nostr_config.last_bunker_uri = Some(connect_string);
let _ = user.save_nostr_config(&nostr_config);
user.signer = Arc::new(signer);
user.client.set_signer(user.signer.clone()).await;
user.connect_uri = Some(uri.clone());
let _ = user.tx.send(0).await;
Response::temporary_redirect("/")
} else {
user.connect_uri = None;
let _ = user.client.unset_signer().await;
Response::success(WindTemplate::render(
NostrConnectFailureTemplate {},
))
}
} else {
user.connect_uri = None;
Response::input(t!("invalid_input_bunker_uri"))
}
} else {
ask_bunker_uri()
}
}
Action::Reconnect => {
if let Some(uri) = config.last_bunker_uri {
Response::temporary_redirect(format!(
"/connect/bunker/new?{}",
encode(&uri)
))
} else {
ask_bunker_uri()
}
}
_ => ask_bunker_uri(),
}
}
pub async fn nostr_connect_client_initiated(
_ctx: RouteContext,
user: &'static mut CaracalUser,
) -> Response {
let Ok(client_keys) = user.get_client_keys() else {
return Response::temporary_failure("Client keys error");
};
let uri = NostrConnectURI::client(
client_keys.public_key(),
vec![RelayUrl::parse("wss://nos.lol").unwrap()],
"caracal",
);
let Ok(signer) = NostrConnect::new(
uri.clone(),
client_keys,
Duration::from_secs(20),
None,
) else {
return Response::temporary_failure("Failed to build signer");
};
user.client.set_signer(signer).await;
user.connect_uri = Some(uri.clone());
Response::success(WindTemplate::render(NostrConnectClientInitTemplate {
uri: &uri,
}))
}