mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 09:28:11 +00:00
search endpoint + docs
This commit is contained in:
1 parent
47a3c7935a
commit
6f4e780c7d
14 files changed
+303
-14
No files matched your search
@@ -80,6 +80,7 @@ use crate::http_server::endpoints::media_files::list::list_media_files_by_batch_
|
||||
use crate::http_server::endpoints::media_files::list::list_media_files_for_user_handler::*;
|
||||
use crate::http_server::endpoints::media_files::list::list_media_files_handler::*;
|
||||
use crate::http_server::endpoints::media_files::list::list_pinned_media_files_handler::*;
|
||||
use crate::http_server::endpoints::media_files::search::search_media_files_handler::*;
|
||||
use crate::http_server::endpoints::media_files::upload::upload_audio_media_file_handler::*;
|
||||
use crate::http_server::endpoints::media_files::upload::upload_engine_asset::upload_engine_asset_media_file_handler::*;
|
||||
use crate::http_server::endpoints::media_files::upload::upload_error::MediaFileUploadError;
|
||||
@@ -157,6 +158,7 @@ use crate::http_server::web_utils::response_success_helpers::*;
|
||||
crate::http_server::endpoints::media_files::list::list_media_files_for_user_handler::list_media_files_for_user_handler,
|
||||
crate::http_server::endpoints::media_files::list::list_media_files_handler::list_media_files_handler,
|
||||
crate::http_server::endpoints::media_files::list::list_pinned_media_files_handler::list_pinned_media_files_handler,
|
||||
crate::http_server::endpoints::media_files::search::search_media_files_handler::search_media_files_handler,
|
||||
crate::http_server::endpoints::media_files::upload::upload_audio_media_file_handler::upload_audio_media_file_handler,
|
||||
crate::http_server::endpoints::media_files::upload::upload_engine_asset::upload_engine_asset_media_file_handler::upload_engine_asset_media_file_handler,
|
||||
crate::http_server::endpoints::media_files::upload::upload_generic::upload_media_file_handler::upload_media_file_handler,
|
||||
@@ -293,6 +295,10 @@ use crate::http_server::web_utils::response_success_helpers::*;
|
||||
CreateFeaturedItemSuccessResponse,
|
||||
CreateSceneError,
|
||||
CreateSceneSuccessResponse,
|
||||
SearchMediaFilesError,
|
||||
SearchMediaFilesSuccessResponse,
|
||||
SearchMediaFilesQueryParams,
|
||||
SearchMediaFileListItem,
|
||||
CreateUserBookmarkError,
|
||||
CreateUserBookmarkRequest,
|
||||
CreateUserBookmarkSuccessResponse,
|
||||
|
||||
-3
@@ -35,9 +35,6 @@ use crate::http_server::common_responses::pagination_page::PaginationPage;
|
||||
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
|
||||
use crate::http_server::endpoints::beta_keys::create_beta_keys_handler::CreateBetaKeysError;
|
||||
use crate::http_server::endpoints::events::list_events::ListEventsError;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_media_classes::get_scoped_media_classes;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_media_types::get_scoped_media_types;
|
||||
use crate::http_server::web_utils::require_moderator::{require_moderator, RequireModeratorError};
|
||||
use crate::http_server::web_utils::require_user_session::{require_user_session, RequireUserSessionError};
|
||||
use crate::server_state::ServerState;
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-3
@@ -28,9 +28,9 @@ use crate::http_server::common_responses::media_file_cover_image_details::{Media
|
||||
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
|
||||
use crate::http_server::common_responses::pagination_cursors::PaginationCursors;
|
||||
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_media_classes::get_scoped_media_classes;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_media_types::get_scoped_media_types;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_classes::get_scoped_media_classes;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_types::get_scoped_media_types;
|
||||
use crate::server_state::ServerState;
|
||||
use crate::util::allowed_explore_media_access::allowed_explore_media_access;
|
||||
|
||||
|
||||
+3
-3
@@ -27,9 +27,9 @@ use crate::http_server::common_responses::media_file_cover_image_details::{Media
|
||||
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
|
||||
use crate::http_server::common_responses::pagination_page::PaginationPage;
|
||||
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_media_classes::get_scoped_media_classes;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_media_types::get_scoped_media_types;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_classes::get_scoped_media_classes;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_types::get_scoped_media_types;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::server_state::ServerState;
|
||||
use crate::util::allowed_studio_access::allowed_studio_access;
|
||||
|
||||
+3
-3
@@ -27,9 +27,9 @@ use crate::http_server::common_responses::media_file_cover_image_details::{Media
|
||||
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
|
||||
use crate::http_server::common_responses::pagination_cursors::PaginationCursors;
|
||||
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_media_classes::get_scoped_media_classes;
|
||||
use crate::http_server::endpoints::media_files::list::helpers::get_scoped_media_types::get_scoped_media_types;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_classes::get_scoped_media_classes;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_types::get_scoped_media_types;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::server_state::ServerState;
|
||||
use crate::util::allowed_explore_media_access::allowed_explore_media_access;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod helpers;
|
||||
pub mod list_featured_media_files_handler;
|
||||
pub mod list_media_files_by_batch_token_handler;
|
||||
pub mod list_media_files_for_user_handler;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
pub mod delete;
|
||||
pub mod edit;
|
||||
pub mod get;
|
||||
pub mod helpers;
|
||||
pub mod list;
|
||||
pub mod search;
|
||||
pub mod upload;
|
||||
pub mod upsert_upload;
|
||||
pub mod upsert_upload;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod search_media_files_handler;
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::{HttpMessage, HttpRequest, HttpResponse, web};
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Query;
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
use buckets::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use elasticsearch_schema::searches::search_media_files::{search_media_files, SearchArgs};
|
||||
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
|
||||
use enums::by_table::media_files::media_file_class::MediaFileClass;
|
||||
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
|
||||
use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory;
|
||||
use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType;
|
||||
use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory;
|
||||
use enums::by_table::media_files::media_file_type::MediaFileType;
|
||||
use enums::common::view_as::ViewAs;
|
||||
use enums::common::visibility::Visibility;
|
||||
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use users_component::common_responses::user_details_lite::UserDetailsLight;
|
||||
|
||||
use crate::http_server::common_responses::media_file_cover_image_details::{MediaFileCoverImageDetails, MediaFileDefaultCover};
|
||||
use crate::http_server::common_responses::media_file_origin_details::MediaFileOriginDetails;
|
||||
use crate::http_server::common_responses::pagination_cursors::PaginationCursors;
|
||||
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_engine_categories::get_scoped_engine_categories;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_classes::get_scoped_media_classes;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_scoped_media_types::get_scoped_media_types;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::server_state::ServerState;
|
||||
use crate::util::allowed_explore_media_access::allowed_explore_media_access;
|
||||
use crate::util::allowed_studio_access::allowed_studio_access;
|
||||
|
||||
#[derive(Deserialize, ToSchema, IntoParams)]
|
||||
pub struct SearchMediaFilesQueryParams {
|
||||
/// REQUIRED: The search term.
|
||||
///
|
||||
/// This supports typeahead, but the request should still be debounced.
|
||||
pub search_term: String,
|
||||
|
||||
/// NB: This can be one (or more comma-separated values) from `MediaFileClass`,
|
||||
/// which are the broad category of media files: image, video, etc.
|
||||
///
|
||||
/// Usage:
|
||||
/// - `?filter_media_classes=audio`
|
||||
/// - `?filter_media_classes=image,video`
|
||||
/// - etc.
|
||||
pub filter_media_classes: Option<String>,
|
||||
|
||||
/// NB: This can be one (or more comma-separated values) from `MediaFileType`,
|
||||
/// which are mimetype-like / format-like categories of media files: glb, gltf,
|
||||
/// scene_json, etc.
|
||||
///
|
||||
/// Usage:
|
||||
/// - `?filter_media_type=scene_json`
|
||||
/// - `?filter_media_type=glb,gltf`
|
||||
/// - etc.
|
||||
pub filter_media_type: Option<String>,
|
||||
|
||||
/// NB: This can be one (or more comma-separated values) from `MediaFileEngineCategory`.
|
||||
///
|
||||
/// Usage:
|
||||
/// - `?filter_engine_categories=scene`
|
||||
/// - `?filter_engine_categories=animation,character,object`
|
||||
/// - etc.
|
||||
pub filter_engine_categories: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct SearchMediaFilesSuccessResponse {
|
||||
pub success: bool,
|
||||
pub results: Vec<SearchMediaFileListItem>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct SearchMediaFileListItem {
|
||||
pub token: MediaFileToken,
|
||||
|
||||
/// The coarse-grained class of media file: image, video, etc.
|
||||
pub media_class: MediaFileClass,
|
||||
|
||||
/// Type of media will dictate which fields are populated and what
|
||||
/// the frontend should display (eg. video player vs audio player).
|
||||
/// This is closer in meaning to a "mime type".
|
||||
pub media_type: MediaFileType,
|
||||
|
||||
/// If this is an engine/3D asset, this is the broad category (scene,
|
||||
/// animation, etc.) of that object.
|
||||
/// This can also be used for filtering in list/batch endpoints.
|
||||
pub maybe_engine_category: Option<MediaFileEngineCategory>,
|
||||
|
||||
/// If this is an engine/3D asset for an animation or a rig that can
|
||||
/// be animated with either (or both) skeletal or blend shape animations,
|
||||
/// this describes the animation regime used or supported.
|
||||
pub maybe_animation_type: Option<MediaFileAnimationType>,
|
||||
|
||||
// #[deprecated(note="Use MediaFileOriginDetails instead")]
|
||||
// pub origin_category: MediaFileOriginCategory,
|
||||
|
||||
// #[deprecated(note="Use MediaFileOriginDetails instead")]
|
||||
// pub origin_product_category: MediaFileOriginProductCategory,
|
||||
|
||||
// #[deprecated(note="Use MediaFileOriginDetails instead")]
|
||||
// pub maybe_origin_model_type: Option<MediaFileOriginModelType>,
|
||||
|
||||
// #[deprecated(note="Use MediaFileOriginDetails instead")]
|
||||
// pub maybe_origin_model_token: Option<String>,
|
||||
|
||||
// /// Details where the media file came from.
|
||||
// pub origin: MediaFileOriginDetails,
|
||||
|
||||
/// URL to the media file.
|
||||
pub public_bucket_path: String,
|
||||
|
||||
/// Information about the cover image. Many media files do not require a cover image,
|
||||
/// e.g. image files, video files with thumbnails, audio files, etc.
|
||||
/// 3D files require them.
|
||||
pub cover_image: MediaFileCoverImageDetails,
|
||||
|
||||
pub maybe_creator: Option<UserDetailsLight>,
|
||||
|
||||
// /// Statistics about the media file
|
||||
// pub stats: SimpleEntityStats,
|
||||
|
||||
pub creator_set_visibility: Visibility,
|
||||
|
||||
/// The name or title of the media file (optional)
|
||||
pub maybe_title: Option<String>,
|
||||
|
||||
// /// Text transcripts for TTS, etc.
|
||||
// pub maybe_text_transcript: Option<String>,
|
||||
|
||||
// /// For Comfy / Video Style Transfer jobs, this might include
|
||||
// /// the name of the selected style.
|
||||
// pub maybe_style_name: Option<StyleTransferName>,
|
||||
|
||||
// /// Duration for audio and video files, if available.
|
||||
// /// Measured in milliseconds.
|
||||
// pub maybe_duration_millis: Option<u64>,
|
||||
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum SearchMediaFilesError {
|
||||
ServerError,
|
||||
NotAuthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for SearchMediaFilesError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SearchMediaFilesError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
SearchMediaFilesError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
SearchMediaFilesError::ServerError => "server error".to_string(),
|
||||
SearchMediaFilesError::NotAuthorized => "not authorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SearchMediaFilesError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for media files based on various criteria.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
tag = "Media Files",
|
||||
path = "/v1/media_files/search",
|
||||
params(SearchMediaFilesQueryParams),
|
||||
responses(
|
||||
(status = 200, description = "List Featured Media Files", body = SearchMediaFilesSuccessResponse),
|
||||
(status = 500, description = "Server error", body = SearchMediaFilesError),
|
||||
),
|
||||
)]
|
||||
pub async fn search_media_files_handler(
|
||||
http_request: HttpRequest,
|
||||
query: Query<SearchMediaFilesQueryParams>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, SearchMediaFilesError>
|
||||
{
|
||||
let mut maybe_filter_media_types = get_scoped_media_types(query.filter_media_type.as_deref());
|
||||
let mut maybe_filter_media_classes = get_scoped_media_classes(query.filter_media_classes.as_deref());
|
||||
let mut maybe_filter_engine_categories = get_scoped_engine_categories(query.filter_engine_categories.as_deref());
|
||||
|
||||
let results = search_media_files(SearchArgs {
|
||||
search_term: &query.search_term,
|
||||
maybe_media_classes: maybe_filter_media_classes,
|
||||
maybe_media_types: maybe_filter_media_types,
|
||||
maybe_engine_categories: maybe_filter_engine_categories,
|
||||
client: &server_state.elasticsearch,
|
||||
}).await;
|
||||
|
||||
let results = match results {
|
||||
Ok(results) => results,
|
||||
Err(err) => {
|
||||
warn!("Searching error: {:?}", err);
|
||||
return Err(SearchMediaFilesError::ServerError);
|
||||
}
|
||||
};
|
||||
|
||||
let results = results.into_iter()
|
||||
.map(|result| SearchMediaFileListItem {
|
||||
token: result.token.clone(),
|
||||
media_class: result.media_class,
|
||||
media_type: result.media_type,
|
||||
maybe_engine_category: result.maybe_engine_category,
|
||||
maybe_animation_type: result.maybe_animation_type,
|
||||
// origin: MediaFileOriginDetails::from_db_fields_str(
|
||||
// result.origin_category,
|
||||
// result.origin_product_category,
|
||||
// result.maybe_origin_model_type,
|
||||
// result.maybe_origin_model_token.as_deref(),
|
||||
// result.maybe_origin_model_title.as_deref()),
|
||||
// origin_category: result.origin_category,
|
||||
// origin_product_category: result.origin_product_category,
|
||||
// maybe_origin_model_type: result.maybe_origin_model_type,
|
||||
// maybe_origin_model_token: result.maybe_origin_model_token,
|
||||
public_bucket_path: MediaFileBucketPath::from_object_hash(
|
||||
&result.public_bucket_directory_hash,
|
||||
result.maybe_public_bucket_prefix.as_deref(),
|
||||
result.maybe_public_bucket_extension.as_deref())
|
||||
.get_full_object_path_str()
|
||||
.to_string(),
|
||||
cover_image: MediaFileCoverImageDetails::from_optional_db_fields(
|
||||
&result.token,
|
||||
result.maybe_cover_image_public_bucket_hash.as_deref(),
|
||||
result.maybe_cover_image_public_bucket_prefix.as_deref(),
|
||||
result.maybe_cover_image_public_bucket_extension.as_deref(),
|
||||
),
|
||||
maybe_creator: UserDetailsLight::from_optional_db_fields_owned(
|
||||
result.maybe_creator_user_token,
|
||||
result.maybe_creator_username,
|
||||
result.maybe_creator_display_name,
|
||||
result.maybe_creator_gravatar_hash,
|
||||
),
|
||||
// stats: SimpleEntityStats {
|
||||
// positive_rating_count: result.maybe_ratings_positive_count.unwrap_or(0),
|
||||
// bookmark_count: result.maybe_bookmark_count.unwrap_or(0),
|
||||
// },
|
||||
creator_set_visibility: result.creator_set_visibility,
|
||||
maybe_title: result.maybe_title,
|
||||
// maybe_text_transcript: result.maybe_text_transcript,
|
||||
// maybe_style_name: result.maybe_prompt_args
|
||||
// .as_ref()
|
||||
// .and_then(|args| args.style_name.as_ref())
|
||||
// .and_then(|style| style.to_style_name()),
|
||||
// maybe_duration_millis: result.maybe_duration_millis,
|
||||
created_at: result.created_at,
|
||||
updated_at: result.updated_at,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let response = SearchMediaFilesSuccessResponse {
|
||||
success: true,
|
||||
results,
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| SearchMediaFilesError::ServerError)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
}
|
||||
@@ -15,6 +15,7 @@ use crate::http_server::endpoints::media_files::list::list_media_files_by_batch_
|
||||
use crate::http_server::endpoints::media_files::list::list_media_files_for_user_handler::list_media_files_for_user_handler;
|
||||
use crate::http_server::endpoints::media_files::list::list_media_files_handler::list_media_files_handler;
|
||||
use crate::http_server::endpoints::media_files::list::list_pinned_media_files_handler::list_pinned_media_files_handler;
|
||||
use crate::http_server::endpoints::media_files::search::search_media_files_handler::search_media_files_handler;
|
||||
use crate::http_server::endpoints::media_files::upload::upload_audio_media_file_handler::upload_audio_media_file_handler;
|
||||
use crate::http_server::endpoints::media_files::upload::upload_engine_asset::upload_engine_asset_media_file_handler::upload_engine_asset_media_file_handler;
|
||||
use crate::http_server::endpoints::media_files::upload::upload_generic::upload_media_file_handler::upload_media_file_handler;
|
||||
@@ -85,6 +86,10 @@ pub fn add_media_file_routes<T, B> (app: App<T>) -> App<T>
|
||||
.route(web::get().to(list_media_files_for_user_handler))
|
||||
.route(web::head().to(|| HttpResponse::Ok()))
|
||||
)
|
||||
.service(web::resource("/search")
|
||||
.route(web::get().to(search_media_files_handler))
|
||||
.route(web::head().to(|| HttpResponse::Ok()))
|
||||
)
|
||||
.service(web::resource("/upload")
|
||||
.route(web::post().to(upload_media_file_handler))
|
||||
.route(web::head().to(|| HttpResponse::Ok()))
|
||||
|
||||
Reference in new issue
Block a user