sneedstr/src/noose/user.rs

150 lines
3.7 KiB
Rust

use regex::Regex;
use rusqlite::Row;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use validator::{Validate, ValidationError};
lazy_static! {
static ref VALID_CHARACTERS: Regex = Regex::new(r"^[a-zA-Z0-9\_]+$").unwrap();
}
pub enum Nip05Table {
Table,
Pubkey,
Username,
Relays,
JoinedAt,
}
impl sea_query::Iden for Nip05Table {
fn unquoted(&self, s: &mut dyn std::fmt::Write) {
write!(
s,
"{}",
match self {
Self::Table => "nip05",
Self::Pubkey => "pubkey",
Self::Username => "username",
Self::Relays => "relays",
Self::JoinedAt => "joined_at",
}
)
.unwrap()
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct UserRow {
pub pubkey: String,
pub username: String,
relays: Vec<String>,
joined_at: i64,
}
impl UserRow {
pub fn new(pubkey: String, username: String, relays: Vec<String>) -> Self {
Self {
pubkey,
username,
relays,
joined_at: nostr::Timestamp::now().as_i64(),
}
}
}
impl From<&Row<'_>> for UserRow {
fn from(row: &Row) -> Self {
let pubkey: String = row.get("pubkey").unwrap();
let username: String = row.get("username").unwrap();
let relays_raw: String = row.get("relays").unwrap_or_default();
let joined_at: i64 = row.get("joined_at").unwrap();
let relays: Vec<String> = match serde_json::from_str(&relays_raw) {
Ok(val) => val,
Err(_) => vec![],
};
Self {
pubkey,
username,
relays,
joined_at,
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct Nip05Profile {
names: HashMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
relays: Option<HashMap<String, Vec<String>>>,
}
impl From<UserRow> for Nip05Profile {
fn from(value: UserRow) -> Self {
let mut name: HashMap<String, String> = HashMap::new();
name.insert(value.username, value.pubkey.clone());
let relay = match value.relays.is_empty() {
true => None,
false => {
let mut relay: HashMap<String, Vec<String>> = HashMap::new();
relay.insert(value.pubkey.clone(), value.relays);
Some(relay)
}
};
Self {
names: name,
relays: relay,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Validate)]
pub struct User {
#[validate(custom = "validate_pubkey")]
pub pubkey: Option<String>,
#[validate(length(min = 1), regex = "VALID_CHARACTERS")]
pub name: Option<String>,
}
pub fn validate_pubkey(value: &str) -> Result<(), ValidationError> {
use nostr::prelude::FromPkStr;
match nostr::Keys::from_pk_str(value) {
Ok(_) => Ok(()),
Err(_) => Err(ValidationError::new("Unable to parse pubkey")),
}
}
#[cfg(test)]
mod tests {
use super::{Nip05Profile, UserRow};
#[test]
fn make_nip05() {
let user_row = UserRow::new(
"npub1m2w0ckmkgj4wtvl8muwjynh56j3qd4nddca4exdg4mdrkepvfnhsmusy54".to_string(),
"test_user".to_string(),
vec![],
);
let nip05 = Nip05Profile::from(user_row);
dbg!(&nip05);
dbg!(serde_json::to_string(&nip05).unwrap());
}
#[test]
fn parse_relay_vec() {
let relays_raw = "";
let relays: Vec<String> = match serde_json::from_str(relays_raw) {
Ok(val) => val,
Err(_) => vec![],
};
dbg!(relays);
}
}