caracal 0.2.0

Nostr client for Gemini
use super::response::dec_urlq;
use crate::aska::WindTemplate;
use crate::routes::response::*;
use crate::routes::{ugate, ugate_mut};
use askama::Template;
use nostr::{Keys, nips::nip46::NostrConnectURI};
use nostr_connect::prelude::*;
use nostr_sdk::prelude::*;
use rust_i18n::t;
use std::sync::Arc;
use windmark_titanesque::{context::RouteContext, response::Response};

#[derive(Template)]
#[template(path = "nostr_connect.gmi", escape = "txt")]
pub struct NostrConnnectTemplate {}

#[derive(Template)]
#[template(path = "nostr_connect_ok.gmi", escape = "txt")]
pub struct NostrConnnectSuccessTemplate {}

pub async fn nostr_connect_index(ctx: RouteContext) -> Response {
    let Some(_user) = ugate(ctx.certificate).await else {
        return resp_nocert();
    };

    Response::success(WindTemplate::render(NostrConnnectTemplate {}))
}

pub async fn nostr_connect_change(ctx: RouteContext) -> Response {
    let Some(user) = ugate_mut(ctx.certificate).await else {
        return resp_nocert();
    };

    let client_keys = Keys::generate();

    if let Some(input_uri) = dec_urlq(&ctx.url) {
        if let Ok(uri) = NostrConnectURI::parse(&input_uri) {
            user.connect_uri = Some(uri.clone());

            if let Ok(signer) = NostrConnect::new(
                uri,
                client_keys,
                std::time::Duration::from_secs(20),
                None,
            ) {
                user.signer = Arc::new(signer);
                user.client.set_signer(user.signer.clone()).await;

                let _ = user.tx.send(0).await;

                Response::success(WindTemplate::render(
                    NostrConnnectSuccessTemplate {},
                ))
            } else {
                Response::temporary_failure(t!("bunker_conn_failed"))
            }
        } else {
            Response::input(t!("invalid_input_bunker_uri"))
        }
    } else {
        Response::input(t!("input_bunker_uri"))
    }
}