use super::*; pub use shared_contracts::wooden_fish::{ WoodenFishActionRequest, WoodenFishActionResponse, WoodenFishActionType, WoodenFishAudioAsset, WoodenFishCheckpointRunRequest, WoodenFishDraftResponse, WoodenFishFinishRunRequest, WoodenFishGalleryCardResponse, WoodenFishGalleryDetailResponse, WoodenFishGalleryResponse, WoodenFishGenerationStatus, WoodenFishImageAsset, WoodenFishRunResponse, WoodenFishRunStatus, WoodenFishRuntimeRunSnapshotResponse, WoodenFishSessionResponse, WoodenFishSessionSnapshotResponse, WoodenFishStartRunRequest, WoodenFishWordCounter, WoodenFishWorkDetailResponse, WoodenFishWorkMutationResponse, WoodenFishWorkProfileResponse, WoodenFishWorkSummaryResponse, WoodenFishWorkspaceCreateRequest, }; pub(crate) fn map_wooden_fish_agent_session_procedure_result( result: WoodenFishAgentSessionProcedureResult, ) -> Result { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } let session = result .session .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish agent session 快照"))?; Ok(map_wooden_fish_session_snapshot(session)) } pub(crate) fn map_wooden_fish_work_procedure_result( result: WoodenFishWorkProcedureResult, ) -> Result { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } let work = result .work .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish work 快照"))?; map_wooden_fish_work_snapshot(work) } pub(crate) fn map_wooden_fish_works_procedure_result( result: WoodenFishWorksProcedureResult, ) -> Result, SpacetimeClientError> { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } result .items .into_iter() .map(map_wooden_fish_work_snapshot) .collect() } pub(crate) fn map_wooden_fish_run_procedure_result( result: WoodenFishRunProcedureResult, ) -> Result { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } let run = result .run .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish run 快照"))?; Ok(map_wooden_fish_run_snapshot(run)) } pub(crate) fn map_wooden_fish_gallery_card_view_row( row: WoodenFishGalleryCardViewRow, ) -> WoodenFishGalleryCardResponse { WoodenFishGalleryCardResponse { public_work_code: row.public_work_code, work_id: row.work_id, profile_id: row.profile_id, owner_user_id: row.owner_user_id, author_display_name: row.author_display_name, work_title: row.work_title, work_description: row.work_description, cover_image_src: empty_string_to_none(row.cover_image_src), theme_tags: row.theme_tags, publication_status: normalize_publication_status(&row.publication_status).to_string(), play_count: row.play_count, updated_at: format_timestamp_micros(row.updated_at_micros), published_at: row.published_at_micros.map(format_timestamp_micros), generation_status: parse_generation_status(&row.generation_status), } } fn map_wooden_fish_session_snapshot( snapshot: WoodenFishAgentSessionSnapshot, ) -> WoodenFishSessionSnapshotResponse { WoodenFishSessionSnapshotResponse { session_id: snapshot.session_id, owner_user_id: snapshot.owner_user_id, status: snapshot .draft .as_ref() .map(|draft| parse_generation_status(&draft.generation_status)) .unwrap_or(WoodenFishGenerationStatus::Draft), draft: snapshot.draft.map(map_wooden_fish_draft_snapshot), created_at: format_timestamp_micros(snapshot.created_at_micros), updated_at: format_timestamp_micros(snapshot.updated_at_micros), } } fn map_wooden_fish_work_snapshot( snapshot: WoodenFishWorkSnapshot, ) -> Result { let draft = WoodenFishDraftResponse { template_id: "wooden-fish".to_string(), template_name: "敲木鱼".to_string(), profile_id: Some(snapshot.profile_id.clone()), work_title: snapshot.work_title.clone(), work_description: snapshot.work_description.clone(), theme_tags: snapshot.theme_tags.clone(), hit_object_prompt: snapshot.hit_object_prompt.clone(), hit_object_reference_image_src: snapshot.hit_object_reference_image_src.clone(), hit_sound_prompt: snapshot.hit_sound_prompt.clone(), floating_words: snapshot.floating_words.clone(), hit_object_asset: snapshot.hit_object_asset.clone().map(map_image_asset), background_asset: snapshot.background_asset.clone().map(map_image_asset), hit_sound_asset: snapshot.hit_sound_asset.clone().map(map_audio_asset), cover_image_src: empty_string_to_none(snapshot.cover_image_src.clone()), generation_status: parse_generation_status(&snapshot.generation_status), }; let hit_object_asset = draft .hit_object_asset .clone() .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish hit object asset"))?; let hit_sound_asset = draft .hit_sound_asset .clone() .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish hit sound asset"))?; Ok(WoodenFishWorkProfileResponse { summary: WoodenFishWorkSummaryResponse { runtime_kind: "wooden-fish".to_string(), work_id: snapshot.work_id, profile_id: snapshot.profile_id, owner_user_id: snapshot.owner_user_id, source_session_id: empty_string_to_none(snapshot.source_session_id), work_title: snapshot.work_title, work_description: snapshot.work_description, theme_tags: snapshot.theme_tags, cover_image_src: empty_string_to_none(snapshot.cover_image_src), publication_status: normalize_publication_status(&snapshot.publication_status) .to_string(), play_count: snapshot.play_count, updated_at: format_timestamp_micros(snapshot.updated_at_micros), published_at: snapshot.published_at_micros.map(format_timestamp_micros), publish_ready: snapshot.publish_ready, generation_status: parse_generation_status(&snapshot.generation_status), }, draft, hit_object_asset, background_asset: snapshot.background_asset.map(map_image_asset), hit_sound_asset, floating_words: snapshot.floating_words, }) } fn map_wooden_fish_draft_snapshot(snapshot: WoodenFishDraftSnapshot) -> WoodenFishDraftResponse { WoodenFishDraftResponse { template_id: snapshot.template_id, template_name: snapshot.template_name, profile_id: snapshot.profile_id, work_title: snapshot.work_title, work_description: snapshot.work_description, theme_tags: snapshot.theme_tags, hit_object_prompt: snapshot.hit_object_prompt, hit_object_reference_image_src: snapshot.hit_object_reference_image_src, hit_sound_prompt: snapshot.hit_sound_prompt, floating_words: snapshot.floating_words, hit_object_asset: snapshot.hit_object_asset.map(map_image_asset), background_asset: snapshot.background_asset.map(map_image_asset), hit_sound_asset: snapshot.hit_sound_asset.map(map_audio_asset), cover_image_src: snapshot.cover_image_src, generation_status: parse_generation_status(&snapshot.generation_status), } } fn map_image_asset(snapshot: WoodenFishImageAssetSnapshot) -> WoodenFishImageAsset { WoodenFishImageAsset { asset_id: snapshot.asset_id, image_src: snapshot.image_src, image_object_key: snapshot.image_object_key, asset_object_id: snapshot.asset_object_id, generation_provider: snapshot.generation_provider, prompt: snapshot.prompt, width: snapshot.width, height: snapshot.height, } } fn map_audio_asset(snapshot: WoodenFishAudioAssetSnapshot) -> WoodenFishAudioAsset { WoodenFishAudioAsset { asset_id: snapshot.asset_id, audio_src: snapshot.audio_src, audio_object_key: snapshot.audio_object_key, asset_object_id: snapshot.asset_object_id, source: snapshot.source, prompt: snapshot.prompt, duration_ms: snapshot.duration_ms, } } fn map_wooden_fish_run_snapshot( snapshot: crate::module_bindings::WoodenFishRunSnapshot, ) -> WoodenFishRuntimeRunSnapshotResponse { WoodenFishRuntimeRunSnapshotResponse { run_id: snapshot.run_id, profile_id: snapshot.profile_id, owner_user_id: snapshot.owner_user_id, status: match snapshot.status { crate::module_bindings::WoodenFishRunStatus::Playing => WoodenFishRunStatus::Playing, crate::module_bindings::WoodenFishRunStatus::Finished => WoodenFishRunStatus::Finished, }, total_tap_count: snapshot.total_tap_count, word_counters: snapshot .word_counters .into_iter() .map(|counter| WoodenFishWordCounter { text: counter.text, count: counter.count, }) .collect(), started_at_ms: snapshot.started_at_ms, updated_at_ms: snapshot.updated_at_ms, finished_at_ms: snapshot.finished_at_ms, } } fn parse_generation_status(value: &str) -> WoodenFishGenerationStatus { match value { "generating" => WoodenFishGenerationStatus::Generating, "ready" => WoodenFishGenerationStatus::Ready, "failed" => WoodenFishGenerationStatus::Failed, _ => WoodenFishGenerationStatus::Draft, } } fn normalize_publication_status(value: &str) -> &str { match value { "Published" | "published" => "published", _ => "draft", } }