Enable search by wallet address
This commit is contained in:
parent
4797bacf32
commit
7e5917a821
3 changed files with 48 additions and 4 deletions
|
@ -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()
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue