From 7e5917a821af1ddd7e35358eeaf2ad0c8ca3ee7a Mon Sep 17 00:00:00 2001 From: silverpill Date: Mon, 31 Jan 2022 00:35:10 +0000 Subject: [PATCH] Enable search by wallet address --- src/mastodon_api/search/helpers.rs | 14 +++++++++++- src/models/profiles/queries.rs | 34 +++++++++++++++++++++++++++--- src/models/profiles/types.rs | 4 ++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/mastodon_api/search/helpers.rs b/src/mastodon_api/search/helpers.rs index ec73211..51fd2d9 100644 --- a/src/mastodon_api/search/helpers.rs +++ b/src/mastodon_api/search/helpers.rs @@ -10,13 +10,18 @@ use crate::errors::{ValidationError, HttpError}; use crate::mastodon_api::accounts::types::Account; use crate::mastodon_api::statuses::types::Status; use crate::models::posts::types::Post; -use crate::models::profiles::queries::search_profile; +use crate::models::profiles::queries::{ + search_profile, + search_profile_by_wallet_address, +}; use crate::models::profiles::types::DbActorProfile; +use crate::models::users::types::validate_wallet_address; use super::types::SearchResults; enum SearchQuery { ProfileQuery(String, Option), Url(String), + WalletAddress(String), Unknown, } @@ -39,6 +44,9 @@ fn parse_search_query(search_query: &str) -> SearchQuery { if Url::parse(search_query).is_ok() { return SearchQuery::Url(search_query.to_string()); }; + if validate_wallet_address(&search_query.to_lowercase()).is_ok() { + return SearchQuery::WalletAddress(search_query.to_string()); + }; match parse_profile_query(search_query) { Ok((username, instance)) => { return SearchQuery::ProfileQuery(username, instance); @@ -122,6 +130,10 @@ pub async fn search( posts = vec![post]; }; }, + SearchQuery::WalletAddress(address) => { + // Search is case insensitive + profiles = search_profile_by_wallet_address(db_client, "ETH", &address).await?; + }, SearchQuery::Unknown => (), // ignore }; let accounts: Vec = profiles.into_iter() diff --git a/src/models/profiles/queries.rs b/src/models/profiles/queries.rs index 36586c6..b9cd701 100644 --- a/src/models/profiles/queries.rs +++ b/src/models/profiles/queries.rs @@ -10,6 +10,7 @@ use crate::models::cleanup::{ }; use crate::utils::id::new_uuid; use super::types::{ + get_currency_field_name, ExtraFields, DbActorProfile, ProfileCreateData, @@ -303,12 +304,11 @@ pub async fn search_profile( ) -> Result, DatabaseError> { let db_search_query = match instance { Some(instance) => { - // Search for exact profile name. - // Fetch from remote server if not found + // Search for exact actor address format!("{}@{}", username, instance) }, None => { - // Search for username + // Fuzzy search for username format!("%{}%", username) }, }; @@ -326,6 +326,34 @@ pub async fn search_profile( Ok(profiles) } +pub async fn search_profile_by_wallet_address( + db_client: &impl GenericClient, + currency_code: &str, + wallet_address: &str, +) -> Result, DatabaseError> { + let field_name = get_currency_field_name(currency_code); + let rows = db_client.query( + " + SELECT actor_profile + FROM actor_profile LEFT JOIN user_account USING (id) + WHERE + user_account.wallet_address ILIKE $2 + OR EXISTS ( + SELECT 1 + FROM jsonb_array_elements(actor_profile.extra_fields) AS field + WHERE + field ->> 'name' ILIKE $1 + AND field ->> 'value' ILIKE $2 + ) + ", + &[&field_name, &wallet_address], + ).await?; + let profiles: Vec = rows.iter() + .map(|row| row.try_get("actor_profile")) + .collect::>()?; + Ok(profiles) +} + pub async fn update_follower_count( db_client: &impl GenericClient, profile_id: &Uuid, diff --git a/src/models/profiles/types.rs b/src/models/profiles/types.rs index 6aeff80..308ea00 100644 --- a/src/models/profiles/types.rs +++ b/src/models/profiles/types.rs @@ -34,6 +34,10 @@ impl ExtraFields { } } +pub fn get_currency_field_name(currency_code: &str) -> String { + format!("${}", currency_code.to_uppercase()) +} + type SqlError = Box; impl<'a> FromSql<'a> for ExtraFields {