Add API method for searching profiles by username or acct

This commit is contained in:
silverpill 2022-09-05 23:42:23 +00:00
parent 6accf8ac2e
commit 982a8e8bc2
5 changed files with 80 additions and 3 deletions

View file

@ -169,6 +169,32 @@ paths:
type: array type: array
items: items:
$ref: '#/components/schemas/Relationship' $ref: '#/components/schemas/Relationship'
/api/v1/accounts/search:
get:
summary: Search for matching profiles by username.
parameters:
- name: q
in: query
description: What to search for
required: true
schema:
type: string
- name: limit
in: query
description: Maximum number of results. Defaults to 40.
required: false
schema:
type: number
responses:
200:
description: Successful operation
content:
application/json:
schema:
description: Profile list
type: array
items:
$ref: '#/components/schemas/Account'
/api/v1/accounts/search_did: /api/v1/accounts/search_did:
get: get:
summary: Search profile by DID summary: Search profile by DID

View file

@ -325,6 +325,16 @@ impl Default for RelationshipMap {
} }
} }
fn default_search_limit() -> i64 { 40 }
#[derive(Deserialize)]
pub struct SearchAcctQueryParams {
pub q: String,
#[serde(default = "default_search_limit")]
pub limit: i64,
}
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct SearchDidQueryParams { pub struct SearchDidQueryParams {
pub did: String, pub did: String,

View file

@ -24,6 +24,7 @@ use crate::ethereum::identity::{
}; };
use crate::mastodon_api::oauth::auth::get_current_user; use crate::mastodon_api::oauth::auth::get_current_user;
use crate::mastodon_api::pagination::get_paginated_response; use crate::mastodon_api::pagination::get_paginated_response;
use crate::mastodon_api::search::helpers::search_profiles_only;
use crate::mastodon_api::statuses::helpers::build_status_list; use crate::mastodon_api::statuses::helpers::build_status_list;
use crate::mastodon_api::statuses::types::Status; use crate::mastodon_api::statuses::types::Status;
use crate::mastodon_api::subscriptions::views::{ use crate::mastodon_api::subscriptions::views::{
@ -76,6 +77,7 @@ use super::types::{
IdentityClaimQueryParams, IdentityClaimQueryParams,
IdentityProofData, IdentityProofData,
RelationshipQueryParams, RelationshipQueryParams,
SearchAcctQueryParams,
SearchDidQueryParams, SearchDidQueryParams,
StatusListQueryParams, StatusListQueryParams,
ApiSubscription, ApiSubscription,
@ -313,6 +315,22 @@ async fn get_relationships_view(
Ok(HttpResponse::Ok().json(vec![relationship])) Ok(HttpResponse::Ok().json(vec![relationship]))
} }
#[get("/search")]
async fn search_by_acct(
config: web::Data<Config>,
db_pool: web::Data<Pool>,
query_params: web::Query<SearchAcctQueryParams>,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let accounts = search_profiles_only(
&config,
db_client,
&query_params.q,
query_params.limit,
).await?;
Ok(HttpResponse::Ok().json(accounts))
}
#[get("/search_did")] #[get("/search_did")]
async fn search_by_did( async fn search_by_did(
config: web::Data<Config>, config: web::Data<Config>,
@ -577,6 +595,7 @@ pub fn account_api_scope() -> Scope {
.service(get_identity_claim) .service(get_identity_claim)
.service(create_identity_proof) .service(create_identity_proof)
.service(get_relationships_view) .service(get_relationships_view)
.service(search_by_acct)
.service(search_by_did) .service(search_by_did)
.route("/authorize_subscription", web::get().to(authorize_subscription)) .route("/authorize_subscription", web::get().to(authorize_subscription))
.route("/subscriptions_enabled", web::post().to(subscriptions_enabled)) .route("/subscriptions_enabled", web::post().to(subscriptions_enabled))

View file

@ -75,7 +75,7 @@ fn parse_search_query(search_query: &str) -> SearchQuery {
} }
} }
async fn search_profiles( async fn search_profiles_or_import(
config: &Config, config: &Config,
db_client: &impl GenericClient, db_client: &impl GenericClient,
username: String, username: String,
@ -148,7 +148,7 @@ pub async fn search(
let mut posts = vec![]; let mut posts = vec![];
match parse_search_query(search_query) { match parse_search_query(search_query) {
SearchQuery::ProfileQuery(username, instance) => { SearchQuery::ProfileQuery(username, instance) => {
profiles = search_profiles( profiles = search_profiles_or_import(
config, config,
db_client, db_client,
username, username,
@ -194,3 +194,25 @@ pub async fn search(
).await?; ).await?;
Ok(SearchResults { accounts, statuses }) Ok(SearchResults { accounts, statuses })
} }
pub async fn search_profiles_only(
config: &Config,
db_client: &impl GenericClient,
search_query: &str,
limit: i64,
) -> Result<Vec<Account>, HttpError> {
let (username, maybe_instance) = match parse_profile_query(search_query) {
Ok(result) => result,
Err(_) => return Ok(vec![]),
};
let profiles = search_profile(
db_client,
&username,
maybe_instance.as_ref(),
limit,
).await?;
let accounts: Vec<Account> = profiles.into_iter()
.map(|profile| Account::from_profile(profile, &config.instance_url()))
.collect();
Ok(accounts)
}

View file

@ -1,3 +1,3 @@
mod helpers; pub mod helpers;
mod types; mod types;
pub mod views; pub mod views;