mirror of
https://github.com/mikedilger/gossip.git
synced 2024-10-04 02:40:57 +00:00
Big rewrite of DbPerson to match database
This commit is contained in:
parent
0a5814163d
commit
9b267f6c99
@ -16,9 +16,6 @@ pub use event_relationship::DbEventRelationship;
|
||||
mod relay;
|
||||
pub use relay::DbRelay;
|
||||
|
||||
mod person;
|
||||
pub use person::DbPerson;
|
||||
|
||||
mod contact;
|
||||
pub use contact::DbContact;
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
use nostr_types::PublicKeyHex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DbPerson {
|
||||
pub pubkey: PublicKeyHex,
|
||||
pub name: Option<String>,
|
||||
pub about: Option<String>,
|
||||
pub picture: Option<String>,
|
||||
pub dns_id: Option<String>,
|
||||
pub dns_id_valid: u8,
|
||||
pub dns_id_last_checked: Option<u64>,
|
||||
pub metadata_at: Option<i64>,
|
||||
pub followed: u8,
|
||||
pub followed_last_updated: i64,
|
||||
}
|
45
src/nip05.rs
45
src/nip05.rs
@ -1,7 +1,8 @@
|
||||
use crate::db::{DbPerson, DbPersonRelay, DbRelay};
|
||||
use crate::db::{DbPersonRelay, DbRelay};
|
||||
use crate::error::Error;
|
||||
use crate::globals::GLOBALS;
|
||||
use nostr_types::{Nip05, Unixtime, Url};
|
||||
use crate::people::DbPerson;
|
||||
use nostr_types::{Metadata, Nip05, Unixtime, Url};
|
||||
|
||||
// This updates the people map and the database with the result
|
||||
#[allow(dead_code)]
|
||||
@ -9,29 +10,31 @@ pub async fn validate_nip05(person: DbPerson) -> Result<(), Error> {
|
||||
let now = Unixtime::now().unwrap();
|
||||
|
||||
// invalid if their nip-05 is not set
|
||||
if person.dns_id.is_none() {
|
||||
if person.metadata.is_none() || matches!(person.metadata, Some(Metadata { nip05: None, .. })) {
|
||||
GLOBALS
|
||||
.people
|
||||
.upsert_nip05_validity(&person.pubkey, person.dns_id, false, now.0 as u64)
|
||||
.upsert_nip05_validity(&person.pubkey, None, false, now.0 as u64)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let metadata = person.metadata.as_ref().unwrap().to_owned();
|
||||
let nip05 = metadata.nip05.as_ref().unwrap().to_owned();
|
||||
|
||||
// Split their DNS ID
|
||||
let dns_id = person.dns_id.clone().unwrap();
|
||||
let (user, domain) = match parse_dns_id(&dns_id) {
|
||||
let (user, domain) = match parse_nip05(&nip05) {
|
||||
Ok(pair) => pair,
|
||||
Err(_) => {
|
||||
GLOBALS
|
||||
.people
|
||||
.upsert_nip05_validity(&person.pubkey, person.dns_id, false, now.0 as u64)
|
||||
.upsert_nip05_validity(&person.pubkey, Some(nip05), false, now.0 as u64)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch NIP-05
|
||||
let nip05 = match fetch_nip05(&user, &domain).await {
|
||||
let nip05file = match fetch_nip05(&user, &domain).await {
|
||||
Ok(content) => content,
|
||||
Err(e) => {
|
||||
tracing::error!("NIP-05 fetch issue with {}@{}", user, domain);
|
||||
@ -40,13 +43,13 @@ pub async fn validate_nip05(person: DbPerson) -> Result<(), Error> {
|
||||
};
|
||||
|
||||
// Check if the response matches their public key
|
||||
match nip05.names.get(&user) {
|
||||
match nip05file.names.get(&user) {
|
||||
Some(pk) => {
|
||||
if *pk == person.pubkey {
|
||||
// Validated
|
||||
GLOBALS
|
||||
.people
|
||||
.upsert_nip05_validity(&person.pubkey, person.dns_id, true, now.0 as u64)
|
||||
.upsert_nip05_validity(&person.pubkey, Some(nip05), true, now.0 as u64)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
@ -54,7 +57,7 @@ pub async fn validate_nip05(person: DbPerson) -> Result<(), Error> {
|
||||
// Failed
|
||||
GLOBALS
|
||||
.people
|
||||
.upsert_nip05_validity(&person.pubkey, person.dns_id, false, now.0 as u64)
|
||||
.upsert_nip05_validity(&person.pubkey, Some(nip05), false, now.0 as u64)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
@ -62,15 +65,15 @@ pub async fn validate_nip05(person: DbPerson) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_and_follow_nip05(dns_id: String) -> Result<(), Error> {
|
||||
pub async fn get_and_follow_nip05(nip05: String) -> Result<(), Error> {
|
||||
// Split their DNS ID
|
||||
let (user, domain) = parse_dns_id(&dns_id)?;
|
||||
let (user, domain) = parse_nip05(&nip05)?;
|
||||
|
||||
// Fetch NIP-05
|
||||
let nip05 = fetch_nip05(&user, &domain).await?;
|
||||
let nip05file = fetch_nip05(&user, &domain).await?;
|
||||
|
||||
// Get their pubkey
|
||||
let pubkey = match nip05.names.get(&user) {
|
||||
let pubkey = match nip05file.names.get(&user) {
|
||||
Some(pk) => pk,
|
||||
None => return Err(Error::Nip05KeyNotFound),
|
||||
};
|
||||
@ -80,7 +83,7 @@ pub async fn get_and_follow_nip05(dns_id: String) -> Result<(), Error> {
|
||||
.people
|
||||
.upsert_nip05_validity(
|
||||
pubkey,
|
||||
Some(dns_id.clone()),
|
||||
Some(nip05.clone()),
|
||||
true,
|
||||
Unixtime::now().unwrap().0 as u64,
|
||||
)
|
||||
@ -89,10 +92,10 @@ pub async fn get_and_follow_nip05(dns_id: String) -> Result<(), Error> {
|
||||
// Mark as followed
|
||||
GLOBALS.people.async_follow(pubkey, true).await?;
|
||||
|
||||
tracing::info!("Followed {}", &dns_id);
|
||||
tracing::info!("Followed {}", &nip05);
|
||||
|
||||
// Set their relays
|
||||
let relays = match nip05.relays.get(pubkey) {
|
||||
let relays = match nip05file.relays.get(pubkey) {
|
||||
Some(relays) => relays,
|
||||
None => return Err(Error::Nip05RelaysNotFound),
|
||||
};
|
||||
@ -113,14 +116,14 @@ pub async fn get_and_follow_nip05(dns_id: String) -> Result<(), Error> {
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!("Setup {} relays for {}", relays.len(), &dns_id);
|
||||
tracing::info!("Setup {} relays for {}", relays.len(), &nip05);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// returns user and domain
|
||||
fn parse_dns_id(dns_id: &str) -> Result<(String, String), Error> {
|
||||
let mut parts: Vec<&str> = dns_id.split('@').collect();
|
||||
fn parse_nip05(nip05: &str) -> Result<(String, String), Error> {
|
||||
let mut parts: Vec<&str> = nip05.split('@').collect();
|
||||
|
||||
// Add the underscore as a username if they just specified a domain name.
|
||||
if parts.len() == 1 {
|
||||
|
@ -393,9 +393,9 @@ impl Overlord {
|
||||
ToOverlordMessage::FollowHex(hex, relay) => {
|
||||
Overlord::follow_hexkey(hex, relay).await?;
|
||||
}
|
||||
ToOverlordMessage::FollowNip05(dns_id) => {
|
||||
ToOverlordMessage::FollowNip05(nip05) => {
|
||||
let _ = tokio::spawn(async move {
|
||||
if let Err(e) = crate::nip05::get_and_follow_nip05(dns_id).await {
|
||||
if let Err(e) = crate::nip05::get_and_follow_nip05(nip05).await {
|
||||
tracing::error!("{}", e);
|
||||
}
|
||||
});
|
||||
|
297
src/people.rs
297
src/people.rs
@ -1,4 +1,4 @@
|
||||
use crate::db::{DbPerson, DbPersonRelay};
|
||||
use crate::db::DbPersonRelay;
|
||||
use crate::error::Error;
|
||||
use crate::globals::GLOBALS;
|
||||
use crate::AVATAR_SIZE;
|
||||
@ -9,10 +9,56 @@ use image::imageops::FilterType;
|
||||
use nostr_types::{
|
||||
Event, EventKind, Metadata, PreEvent, PublicKey, PublicKeyHex, Tag, Unixtime, Url,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::cmp::Ordering;
|
||||
use std::time::Duration;
|
||||
use tokio::task;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DbPerson {
|
||||
pub pubkey: PublicKeyHex,
|
||||
pub metadata: Option<Metadata>,
|
||||
pub metadata_at: Option<i64>,
|
||||
pub nip05_valid: u8,
|
||||
pub nip05_last_checked: Option<u64>,
|
||||
pub followed: u8,
|
||||
pub followed_last_updated: i64,
|
||||
}
|
||||
|
||||
impl DbPerson {
|
||||
pub fn name(&self) -> Option<&str> {
|
||||
if let Some(md) = &self.metadata {
|
||||
md.name.as_deref()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn about(&self) -> Option<&str> {
|
||||
if let Some(md) = &self.metadata {
|
||||
md.about.as_deref()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn picture(&self) -> Option<&str> {
|
||||
if let Some(md) = &self.metadata {
|
||||
md.picture.as_deref()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nip05(&self) -> Option<&str> {
|
||||
if let Some(md) = &self.metadata {
|
||||
md.nip05.as_deref()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct People {
|
||||
people: DashMap<PublicKeyHex, DbPerson>,
|
||||
|
||||
@ -110,17 +156,17 @@ impl People {
|
||||
}
|
||||
}
|
||||
if doit {
|
||||
// Process fresh metadata
|
||||
|
||||
person.name = metadata.name;
|
||||
person.about = metadata.about;
|
||||
person.picture = metadata.picture;
|
||||
if person.dns_id != metadata.nip05 {
|
||||
person.dns_id = metadata.nip05;
|
||||
person.dns_id_valid = 0; // changed, so reset to invalid
|
||||
person.dns_id_last_checked = None; // we haven't checked this one yet
|
||||
}
|
||||
let nip05_changed = if let Some(md) = &person.metadata {
|
||||
metadata.nip05 != md.nip05.clone()
|
||||
} else {
|
||||
metadata.nip05.is_some()
|
||||
};
|
||||
person.metadata = Some(metadata);
|
||||
person.metadata_at = Some(asof.0);
|
||||
if nip05_changed {
|
||||
person.nip05_valid = 0; // changed, so reset to invalid
|
||||
person.nip05_last_checked = None; // we haven't checked this one yet
|
||||
}
|
||||
|
||||
// Update the database
|
||||
let person = person.clone();
|
||||
@ -129,15 +175,20 @@ impl People {
|
||||
let maybe_db = GLOBALS.db.blocking_lock();
|
||||
let db = maybe_db.as_ref().unwrap();
|
||||
|
||||
let metadata_json: Option<String> = if let Some(md) = &person.metadata {
|
||||
Some(serde_json::to_string(md)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut stmt = db.prepare(
|
||||
"UPDATE person SET name=?, about=?, picture=?, dns_id=?, metadata_at=? WHERE pubkey=?"
|
||||
"UPDATE person SET metadata=?, metadata_at=?, nip05_valid=?, nip05_last_checked=? WHERE pubkey=?"
|
||||
)?;
|
||||
stmt.execute((
|
||||
&person.name,
|
||||
&person.about,
|
||||
&person.picture,
|
||||
&person.dns_id,
|
||||
&metadata_json,
|
||||
&person.metadata_at,
|
||||
&person.nip05_valid,
|
||||
&person.nip05_last_checked,
|
||||
&pubkeyhex2.0,
|
||||
))?;
|
||||
Ok::<(), Error>(())
|
||||
@ -151,20 +202,26 @@ impl People {
|
||||
let person = person.to_owned();
|
||||
|
||||
// Only if they have a nip05 dns id set
|
||||
if person.dns_id.is_some() {
|
||||
if matches!(
|
||||
person,
|
||||
DbPerson {
|
||||
metadata: Some(Metadata { nip05: Some(_), .. }),
|
||||
..
|
||||
}
|
||||
) {
|
||||
// Recheck nip05 every day if invalid, and every two weeks if valid
|
||||
// FIXME make these settings
|
||||
let recheck_duration = if person.dns_id_valid > 0 {
|
||||
let recheck_duration = if person.nip05_valid > 0 {
|
||||
Duration::from_secs(60 * 60 * 24 * 14)
|
||||
} else {
|
||||
Duration::from_secs(60 * 60 * 24)
|
||||
};
|
||||
|
||||
// Maybe validate nip05
|
||||
if let Some(last) = person.dns_id_last_checked {
|
||||
if let Some(last) = person.nip05_last_checked {
|
||||
if Unixtime::now().unwrap() - Unixtime(last as i64) > recheck_duration {
|
||||
// recheck
|
||||
self.update_dns_id_last_checked(person.pubkey.clone())
|
||||
self.update_nip05_last_checked(person.pubkey.clone())
|
||||
.await?;
|
||||
task::spawn(async move {
|
||||
if let Err(e) = crate::nip05::validate_nip05(person).await {
|
||||
@ -173,7 +230,7 @@ impl People {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
self.update_dns_id_last_checked(person.pubkey.clone())
|
||||
self.update_nip05_last_checked(person.pubkey.clone())
|
||||
.await?;
|
||||
task::spawn(async move {
|
||||
if let Err(e) = crate::nip05::validate_nip05(person).await {
|
||||
@ -194,33 +251,32 @@ impl People {
|
||||
));
|
||||
}
|
||||
|
||||
let sql =
|
||||
"SELECT pubkey, name, about, picture, dns_id, dns_id_valid, dns_id_last_checked, \
|
||||
metadata_at, followed, followed_last_updated FROM person WHERE followed=1"
|
||||
.to_owned();
|
||||
let sql = "SELECT pubkey, metadata, metadata_at, nip05_valid, nip05_last_checked, \
|
||||
followed, followed_last_updated FROM person WHERE followed=1"
|
||||
.to_owned();
|
||||
|
||||
let output: Result<Vec<DbPerson>, Error> = task::spawn_blocking(move || {
|
||||
let maybe_db = GLOBALS.db.blocking_lock();
|
||||
let db = maybe_db.as_ref().unwrap();
|
||||
|
||||
let mut stmt = db.prepare(&sql)?;
|
||||
let rows = stmt.query_map([], |row| {
|
||||
Ok(DbPerson {
|
||||
pubkey: PublicKeyHex(row.get(0)?),
|
||||
name: row.get(1)?,
|
||||
about: row.get(2)?,
|
||||
picture: row.get(3)?,
|
||||
dns_id: row.get(4)?,
|
||||
dns_id_valid: row.get(5)?,
|
||||
dns_id_last_checked: row.get(6)?,
|
||||
metadata_at: row.get(7)?,
|
||||
followed: row.get(8)?,
|
||||
followed_last_updated: row.get(9)?,
|
||||
})
|
||||
})?;
|
||||
let mut rows = stmt.query([])?;
|
||||
let mut output: Vec<DbPerson> = Vec::new();
|
||||
for row in rows {
|
||||
output.push(row?);
|
||||
while let Some(row) = rows.next()? {
|
||||
let metadata_json: Option<String> = row.get(1)?;
|
||||
let metadata = match metadata_json {
|
||||
Some(s) => serde_json::from_str(&s)?,
|
||||
None => None,
|
||||
};
|
||||
output.push(DbPerson {
|
||||
pubkey: PublicKeyHex(row.get(0)?),
|
||||
metadata,
|
||||
metadata_at: row.get(2)?,
|
||||
nip05_valid: row.get(3)?,
|
||||
nip05_last_checked: row.get(4)?,
|
||||
followed: row.get(5)?,
|
||||
followed_last_updated: row.get(6)?,
|
||||
});
|
||||
}
|
||||
Ok(output)
|
||||
})
|
||||
@ -258,7 +314,7 @@ impl People {
|
||||
pub fn get_all(&self) -> Vec<DbPerson> {
|
||||
let mut v: Vec<DbPerson> = self.people.iter().map(|e| e.value().to_owned()).collect();
|
||||
v.sort_by(|a, b| {
|
||||
let c = a.name.cmp(&b.name);
|
||||
let c = a.name().cmp(&b.name());
|
||||
if c == Ordering::Equal {
|
||||
a.pubkey.cmp(&b.pubkey)
|
||||
} else {
|
||||
@ -296,13 +352,13 @@ impl People {
|
||||
// Fail if they don't have a picture url
|
||||
// FIXME: we could get metadata that sets this while we are running, so just failing for
|
||||
// the duration of the client isn't quite right. But for now, retrying is taxing.
|
||||
if person.picture.is_none() {
|
||||
if person.picture().is_none() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// FIXME: we could get metadata that sets this while we are running, so just failing for
|
||||
// the duration of the client isn't quite right. But for now, retrying is taxing.
|
||||
let url = Url::new(person.picture.as_ref().unwrap());
|
||||
let url = Url::new(person.picture().unwrap());
|
||||
if !url.is_valid() {
|
||||
return Err(());
|
||||
}
|
||||
@ -370,7 +426,7 @@ impl People {
|
||||
let mut result_name = String::from("");
|
||||
|
||||
// search for users by name
|
||||
if let Some(name) = &person.name.as_ref() {
|
||||
if let Some(name) = &person.name() {
|
||||
let matchable = name.to_lowercase();
|
||||
if matchable.starts_with(&search) {
|
||||
score = 300;
|
||||
@ -383,15 +439,15 @@ impl People {
|
||||
}
|
||||
|
||||
// search for users by nip05 id
|
||||
if score == 0 && person.dns_id_valid > 0 {
|
||||
if let Some(dns_id) = &person.dns_id.as_ref().map(|n| n.to_lowercase()) {
|
||||
if dns_id.starts_with(&search) {
|
||||
if score == 0 && person.nip05_valid > 0 {
|
||||
if let Some(nip05) = &person.nip05().map(|n| n.to_lowercase()) {
|
||||
if nip05.starts_with(&search) {
|
||||
score = 400;
|
||||
result_name = dns_id.to_string();
|
||||
result_name = nip05.to_string();
|
||||
}
|
||||
if dns_id.contains(&search) {
|
||||
if nip05.contains(&search) {
|
||||
score = 100;
|
||||
result_name = dns_id.to_string();
|
||||
result_name = nip05.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -602,10 +658,10 @@ impl People {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_dns_id_last_checked(&self, pubkeyhex: PublicKeyHex) -> Result<(), Error> {
|
||||
pub async fn update_nip05_last_checked(&self, pubkeyhex: PublicKeyHex) -> Result<(), Error> {
|
||||
let maybe_db = GLOBALS.db.lock().await;
|
||||
let db = maybe_db.as_ref().unwrap();
|
||||
let mut stmt = db.prepare("UPDATE person SET dns_id_last_checked=? WHERE pubkey=?")?;
|
||||
let mut stmt = db.prepare("UPDATE person SET nip05_last_checked=? WHERE pubkey=?")?;
|
||||
let now = Unixtime::now().unwrap().0;
|
||||
stmt.execute((&now, &pubkeyhex.0))?;
|
||||
Ok(())
|
||||
@ -614,36 +670,54 @@ impl People {
|
||||
pub async fn upsert_nip05_validity(
|
||||
&self,
|
||||
pubkeyhex: &PublicKeyHex,
|
||||
dns_id: Option<String>,
|
||||
dns_id_valid: bool,
|
||||
dns_id_last_checked: u64,
|
||||
nip05: Option<String>,
|
||||
nip05_valid: bool,
|
||||
nip05_last_checked: u64,
|
||||
) -> Result<(), Error> {
|
||||
// Update memory
|
||||
if let Some(mut dbperson) = self.people.get_mut(pubkeyhex) {
|
||||
dbperson.dns_id = dns_id.clone();
|
||||
dbperson.dns_id_valid = u8::from(dns_id_valid);
|
||||
dbperson.dns_id_last_checked = Some(dns_id_last_checked);
|
||||
if let Some(metadata) = &mut dbperson.metadata {
|
||||
metadata.nip05 = nip05.clone()
|
||||
} else {
|
||||
let mut metadata = Metadata::new();
|
||||
metadata.nip05 = nip05.clone();
|
||||
dbperson.metadata = Some(metadata);
|
||||
}
|
||||
dbperson.nip05_valid = u8::from(nip05_valid);
|
||||
dbperson.nip05_last_checked = Some(nip05_last_checked);
|
||||
}
|
||||
|
||||
// Update in database
|
||||
let sql = "INSERT INTO person (pubkey, dns_id, dns_id_valid, dns_id_last_checked) \
|
||||
let sql = "INSERT INTO person (pubkey, metadata, nip05_valid, nip05_last_checked) \
|
||||
values (?, ?, ?, ?) \
|
||||
ON CONFLICT(pubkey) DO UPDATE SET dns_id=?, dns_id_valid=?, dns_id_last_checked=?";
|
||||
ON CONFLICT(pubkey) DO \
|
||||
UPDATE SET metadata=json_patch(metadata, ?), nip05_valid=?, nip05_last_checked=?";
|
||||
|
||||
let pubkeyhex2 = pubkeyhex.to_owned();
|
||||
task::spawn_blocking(move || {
|
||||
let maybe_db = GLOBALS.db.blocking_lock();
|
||||
let db = maybe_db.as_ref().unwrap();
|
||||
|
||||
let mut metadata = Metadata::new();
|
||||
metadata.nip05 = nip05.clone();
|
||||
let metadata_json: Option<String> = Some(serde_json::to_string(&metadata)?);
|
||||
let metadata_patch = format!(
|
||||
"{{\"nip05\": {}}}",
|
||||
match nip05 {
|
||||
Some(s) => s,
|
||||
None => "null".to_owned(),
|
||||
}
|
||||
);
|
||||
|
||||
let mut stmt = db.prepare(sql)?;
|
||||
stmt.execute((
|
||||
&pubkeyhex2.0,
|
||||
&dns_id,
|
||||
&dns_id_valid,
|
||||
&dns_id_last_checked,
|
||||
&dns_id,
|
||||
&dns_id_valid,
|
||||
&dns_id_last_checked,
|
||||
&metadata_json,
|
||||
&nip05_valid,
|
||||
&nip05_last_checked,
|
||||
&metadata_patch,
|
||||
&nip05_valid,
|
||||
&nip05_last_checked,
|
||||
))?;
|
||||
Ok::<(), Error>(())
|
||||
})
|
||||
@ -653,10 +727,10 @@ impl People {
|
||||
}
|
||||
|
||||
async fn fetch(criteria: Option<&str>) -> Result<Vec<DbPerson>, Error> {
|
||||
let sql =
|
||||
"SELECT pubkey, name, about, picture, dns_id, dns_id_valid, dns_id_last_checked, \
|
||||
metadata_at, followed, followed_last_updated FROM person"
|
||||
.to_owned();
|
||||
let sql = "SELECT pubkey, metadata, metadata_at, \
|
||||
nip05_valid, nip05_last_checked, \
|
||||
followed, followed_last_updated FROM person"
|
||||
.to_owned();
|
||||
let sql = match criteria {
|
||||
None => sql,
|
||||
Some(crit) => format!("{} WHERE {}", sql, crit),
|
||||
@ -667,24 +741,23 @@ impl People {
|
||||
let db = maybe_db.as_ref().unwrap();
|
||||
|
||||
let mut stmt = db.prepare(&sql)?;
|
||||
let rows = stmt.query_map([], |row| {
|
||||
Ok(DbPerson {
|
||||
pubkey: PublicKeyHex(row.get(0)?),
|
||||
name: row.get(1)?,
|
||||
about: row.get(2)?,
|
||||
picture: row.get(3)?,
|
||||
dns_id: row.get(4)?,
|
||||
dns_id_valid: row.get(5)?,
|
||||
dns_id_last_checked: row.get(6)?,
|
||||
metadata_at: row.get(7)?,
|
||||
followed: row.get(8)?,
|
||||
followed_last_updated: row.get(9)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
let mut rows = stmt.query([])?;
|
||||
let mut output: Vec<DbPerson> = Vec::new();
|
||||
for row in rows {
|
||||
output.push(row?);
|
||||
while let Some(row) = rows.next()? {
|
||||
let metadata_json: Option<String> = row.get(1)?;
|
||||
let metadata = match metadata_json {
|
||||
Some(s) => serde_json::from_str(&s)?,
|
||||
None => None,
|
||||
};
|
||||
output.push(DbPerson {
|
||||
pubkey: PublicKeyHex(row.get(0)?),
|
||||
metadata,
|
||||
metadata_at: row.get(2)?,
|
||||
nip05_valid: row.get(3)?,
|
||||
nip05_last_checked: row.get(4)?,
|
||||
followed: row.get(5)?,
|
||||
followed_last_updated: row.get(6)?,
|
||||
});
|
||||
}
|
||||
Ok(output)
|
||||
})
|
||||
@ -705,8 +778,10 @@ impl People {
|
||||
|
||||
async fn fetch_many(pubkeys: &[&PublicKeyHex]) -> Result<Vec<DbPerson>, Error> {
|
||||
let sql = format!(
|
||||
"SELECT pubkey, name, about, picture, dns_id, dns_id_valid, dns_id_last_checked, \
|
||||
metadata_at, followed, followed_last_updated FROM person WHERE pubkey IN ({})",
|
||||
"SELECT pubkey, metadata, metadata_at, \
|
||||
nip05_valid, nip05_last_checked, \
|
||||
followed, followed_last_updated \
|
||||
FROM person WHERE pubkey IN ({})",
|
||||
repeat_vars(pubkeys.len())
|
||||
);
|
||||
|
||||
@ -727,17 +802,19 @@ impl People {
|
||||
let mut rows = stmt.raw_query();
|
||||
let mut people: Vec<DbPerson> = Vec::new();
|
||||
while let Some(row) = rows.next()? {
|
||||
let metadata_json: Option<String> = row.get(1)?;
|
||||
let metadata = match metadata_json {
|
||||
Some(s) => serde_json::from_str(&s)?,
|
||||
None => None,
|
||||
};
|
||||
people.push(DbPerson {
|
||||
pubkey: PublicKeyHex(row.get(0)?),
|
||||
name: row.get(1)?,
|
||||
about: row.get(2)?,
|
||||
picture: row.get(3)?,
|
||||
dns_id: row.get(4)?,
|
||||
dns_id_valid: row.get(5)?,
|
||||
dns_id_last_checked: row.get(6)?,
|
||||
metadata_at: row.get(7)?,
|
||||
followed: row.get(8)?,
|
||||
followed_last_updated: row.get(9)?,
|
||||
metadata,
|
||||
metadata_at: row.get(2)?,
|
||||
nip05_valid: row.get(3)?,
|
||||
nip05_last_checked: row.get(4)?,
|
||||
followed: row.get(5)?,
|
||||
followed_last_updated: row.get(6)?,
|
||||
});
|
||||
}
|
||||
|
||||
@ -750,25 +827,27 @@ impl People {
|
||||
|
||||
#[allow(dead_code)]
|
||||
async fn insert(person: DbPerson) -> Result<(), Error> {
|
||||
let sql =
|
||||
"INSERT OR IGNORE INTO person (pubkey, name, about, picture, dns_id, dns_id_valid, \
|
||||
dns_id_last_checked, metadata_at, followed, followed_last_updated) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)";
|
||||
let sql = "INSERT OR IGNORE INTO person (pubkey, metadata, metadata_at, \
|
||||
nip05_valid, nip05_last_checked, followed, followed_last_updated) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)";
|
||||
|
||||
task::spawn_blocking(move || {
|
||||
let maybe_db = GLOBALS.db.blocking_lock();
|
||||
let db = maybe_db.as_ref().unwrap();
|
||||
|
||||
let metadata_json: Option<String> = if let Some(md) = &person.metadata {
|
||||
Some(serde_json::to_string(md)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut stmt = db.prepare(sql)?;
|
||||
stmt.execute((
|
||||
&person.pubkey.0,
|
||||
&person.name,
|
||||
&person.about,
|
||||
&person.picture,
|
||||
&person.dns_id,
|
||||
&person.dns_id_valid,
|
||||
&person.dns_id_last_checked,
|
||||
&metadata_json,
|
||||
&person.metadata_at,
|
||||
&person.nip05_valid,
|
||||
&person.nip05_last_checked,
|
||||
&person.followed,
|
||||
&person.followed_last_updated,
|
||||
))?;
|
||||
|
@ -203,12 +203,12 @@ fn real_posting_area(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
||||
// List tags that will be applied (FIXME: list tags from parent event too in case of reply)
|
||||
for (i, (npub, pubkey)) in keys_from_text(&app.draft).iter().enumerate() {
|
||||
let rendered = if let Some(person) = GLOBALS.people.get(&pubkey.as_hex_string().into()) {
|
||||
match person.name {
|
||||
Some(name) => name,
|
||||
None => npub.to_string(),
|
||||
match person.name() {
|
||||
Some(name) => name.to_owned(),
|
||||
None => npub.to_owned(),
|
||||
}
|
||||
} else {
|
||||
npub.to_string()
|
||||
npub.to_owned()
|
||||
};
|
||||
|
||||
ui.label(format!("{}: {}", i, rendered));
|
||||
@ -357,9 +357,9 @@ fn render_post_actual(
|
||||
// name
|
||||
// about
|
||||
// picture
|
||||
// dns_id
|
||||
// dns_id_valid
|
||||
// dns_id_last_checked
|
||||
// nip05
|
||||
// nip05_valid
|
||||
// nip05_last_checked
|
||||
// metadata_at
|
||||
// followed
|
||||
|
||||
@ -626,7 +626,7 @@ fn render_content(app: &mut GossipUi, ui: &mut Ui, tag_re: ®ex::Regex, event:
|
||||
match tag {
|
||||
Tag::Pubkey { pubkey, .. } => {
|
||||
let nam = match GLOBALS.people.get(pubkey) {
|
||||
Some(p) => match p.name {
|
||||
Some(p) => match p.name() {
|
||||
Some(n) => format!("@{}", n),
|
||||
None => format!("@{}", GossipUi::hex_pubkey_short(pubkey)),
|
||||
},
|
||||
|
@ -8,10 +8,10 @@ mod widgets;
|
||||
mod you;
|
||||
|
||||
use crate::about::About;
|
||||
use crate::db::DbPerson;
|
||||
use crate::error::Error;
|
||||
use crate::feed::FeedKind;
|
||||
use crate::globals::GLOBALS;
|
||||
use crate::people::DbPerson;
|
||||
use crate::settings::Settings;
|
||||
use crate::ui::widgets::CopyButton;
|
||||
use eframe::{egui, IconData, Theme};
|
||||
@ -377,7 +377,7 @@ impl GossipUi {
|
||||
pub fn render_person_name_line(ui: &mut Ui, maybe_person: Option<&DbPerson>) {
|
||||
ui.horizontal(|ui| {
|
||||
if let Some(person) = maybe_person {
|
||||
if let Some(name) = &person.name {
|
||||
if let Some(name) = person.name() {
|
||||
ui.label(RichText::new(name).strong());
|
||||
} else {
|
||||
ui.label(RichText::new(GossipUi::hex_pubkey_short(&person.pubkey)).weak());
|
||||
@ -387,15 +387,15 @@ impl GossipUi {
|
||||
ui.label("🚶");
|
||||
}
|
||||
|
||||
if let Some(mut dns_id) = person.dns_id.clone() {
|
||||
if dns_id.starts_with("_@") {
|
||||
dns_id = dns_id.get(2..).unwrap().to_string();
|
||||
if let Some(mut nip05) = person.nip05().map(|s| s.to_owned()) {
|
||||
if nip05.starts_with("_@") {
|
||||
nip05 = nip05.get(2..).unwrap().to_string();
|
||||
}
|
||||
|
||||
if person.dns_id_valid > 0 {
|
||||
ui.label(RichText::new(dns_id).monospace().small());
|
||||
if person.nip05_valid > 0 {
|
||||
ui.label(RichText::new(nip05).monospace().small());
|
||||
} else {
|
||||
ui.label(RichText::new(dns_id).monospace().small().strikethrough());
|
||||
ui.label(RichText::new(nip05).monospace().small().strikethrough());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{GossipUi, Page};
|
||||
use crate::comms::ToOverlordMessage;
|
||||
use crate::db::DbPerson;
|
||||
use crate::globals::GLOBALS;
|
||||
use crate::people::DbPerson;
|
||||
use crate::AVATAR_SIZE_F32;
|
||||
use eframe::egui;
|
||||
use egui::{Context, Image, RichText, ScrollArea, Sense, Ui, Vec2};
|
||||
@ -107,7 +107,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
}
|
||||
|
||||
fn get_name(person: &DbPerson) -> String {
|
||||
if let Some(name) = &person.name {
|
||||
if let Some(name) = person.name() {
|
||||
name.to_owned()
|
||||
} else {
|
||||
GossipUi::hex_pubkey_short(&person.pubkey)
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::{GossipUi, Page};
|
||||
use crate::comms::ToOverlordMessage;
|
||||
use crate::db::DbPerson;
|
||||
use crate::feed::FeedKind;
|
||||
use crate::globals::GLOBALS;
|
||||
use crate::people::DbPerson;
|
||||
use crate::AVATAR_SIZE_F32;
|
||||
use eframe::egui;
|
||||
use egui::{Context, RichText, Ui, Vec2};
|
||||
@ -50,7 +50,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
ui.add_space(12.0);
|
||||
|
||||
if let Some(person) = &maybe_person {
|
||||
if let Some(about) = person.about.as_deref() {
|
||||
if let Some(about) = person.about() {
|
||||
ui.label(about);
|
||||
}
|
||||
}
|
||||
@ -82,7 +82,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
}
|
||||
|
||||
fn get_name(person: &DbPerson) -> String {
|
||||
if let Some(name) = &person.name {
|
||||
if let Some(name) = person.name() {
|
||||
name.to_owned()
|
||||
} else {
|
||||
GossipUi::hex_pubkey_short(&person.pubkey)
|
||||
|
Loading…
Reference in New Issue
Block a user