caracal 0.2.0

Nostr client for Gemini
use askama::Template;
use nostr_sdk::prelude::*;
use std::collections::HashMap;
use std::time::Duration;
use windmark_titanesque::{context::RouteContext, response::Response};

use crate::aska::WindTemplate;
use crate::nostru::get_user_metadata;
use crate::user::CaracalUser;

#[derive(Template, Clone)]
#[template(path = "contact_list.gmi", escape = "txt")]
struct ContactListTemplate {
    contacts: Vec<Contact>,
    metadatas: HashMap<PublicKey, Metadata>,
}

pub async fn contact_list_index(
    _ctx: RouteContext,
    user: &'static mut CaracalUser,
) -> Response {
    let Ok(contacts) =
        user.client.get_contact_list(Duration::from_secs(5)).await
    else {
        return Response::temporary_failure("Failed to fetch contact list");
    };

    let mut metadatas = HashMap::new();
    for contact in &contacts {
        if let Some(metadata) =
            get_user_metadata(&user.client, contact.public_key).await
        {
            metadatas.insert(contact.public_key, metadata);
        }
    }

    Response::success(WindTemplate::render(ContactListTemplate {
        contacts,
        metadatas,
    }))
}