Enable search by wallet address

This commit is contained in:
silverpill 2022-01-31 00:35:10 +00:00
parent 4797bacf32
commit 7e5917a821
3 changed files with 48 additions and 4 deletions

View file

@ -10,13 +10,18 @@ use crate::errors::{ValidationError, HttpError};
use crate::mastodon_api::accounts::types::Account; use crate::mastodon_api::accounts::types::Account;
use crate::mastodon_api::statuses::types::Status; use crate::mastodon_api::statuses::types::Status;
use crate::models::posts::types::Post; 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::profiles::types::DbActorProfile;
use crate::models::users::types::validate_wallet_address;
use super::types::SearchResults; use super::types::SearchResults;
enum SearchQuery { enum SearchQuery {
ProfileQuery(String, Option<String>), ProfileQuery(String, Option<String>),
Url(String), Url(String),
WalletAddress(String),
Unknown, Unknown,
} }
@ -39,6 +44,9 @@ fn parse_search_query(search_query: &str) -> SearchQuery {
if Url::parse(search_query).is_ok() { if Url::parse(search_query).is_ok() {
return SearchQuery::Url(search_query.to_string()); 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) { match parse_profile_query(search_query) {
Ok((username, instance)) => { Ok((username, instance)) => {
return SearchQuery::ProfileQuery(username, instance); return SearchQuery::ProfileQuery(username, instance);
@ -122,6 +130,10 @@ pub async fn search(
posts = vec![post]; posts = vec![post];
}; };
}, },
SearchQuery::WalletAddress(address) => {
// Search is case insensitive
profiles = search_profile_by_wallet_address(db_client, "ETH", &address).await?;
},
SearchQuery::Unknown => (), // ignore SearchQuery::Unknown => (), // ignore
}; };
let accounts: Vec<Account> = profiles.into_iter() let accounts: Vec<Account> = profiles.into_iter()

View file

@ -10,6 +10,7 @@ use crate::models::cleanup::{
}; };
use crate::utils::id::new_uuid; use crate::utils::id::new_uuid;
use super::types::{ use super::types::{
get_currency_field_name,
ExtraFields, ExtraFields,
DbActorProfile, DbActorProfile,
ProfileCreateData, ProfileCreateData,
@ -303,12 +304,11 @@ pub async fn search_profile(
) -> Result<Vec<DbActorProfile>, DatabaseError> { ) -> Result<Vec<DbActorProfile>, DatabaseError> {
let db_search_query = match instance { let db_search_query = match instance {
Some(instance) => { Some(instance) => {
// Search for exact profile name. // Search for exact actor address
// Fetch from remote server if not found
format!("{}@{}", username, instance) format!("{}@{}", username, instance)
}, },
None => { None => {
// Search for username // Fuzzy search for username
format!("%{}%", username) format!("%{}%", username)
}, },
}; };
@ -326,6 +326,34 @@ pub async fn search_profile(
Ok(profiles) Ok(profiles)
} }
pub async fn search_profile_by_wallet_address(
db_client: &impl GenericClient,
currency_code: &str,
wallet_address: &str,
) -> Result<Vec<DbActorProfile>, 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<DbActorProfile> = rows.iter()
.map(|row| row.try_get("actor_profile"))
.collect::<Result<_, _>>()?;
Ok(profiles)
}
pub async fn update_follower_count( pub async fn update_follower_count(
db_client: &impl GenericClient, db_client: &impl GenericClient,
profile_id: &Uuid, profile_id: &Uuid,

View file

@ -34,6 +34,10 @@ impl ExtraFields {
} }
} }
pub fn get_currency_field_name(currency_code: &str) -> String {
format!("${}", currency_code.to_uppercase())
}
type SqlError = Box<dyn std::error::Error + Sync + Send>; type SqlError = Box<dyn std::error::Error + Sync + Send>;
impl<'a> FromSql<'a> for ExtraFields { impl<'a> FromSql<'a> for ExtraFields {