Allow anonymous jump-hop recommend play

This commit is contained in:
kdletters
2026-05-24 16:02:49 +08:00
parent 2ba4691bc0
commit 2c6fb2e81a
12 changed files with 209 additions and 67 deletions

View File

@@ -17,8 +17,12 @@ use spacetime_client::SpacetimeClientError;
use std::time::{SystemTime, UNIX_EPOCH};
use crate::{
api_response::json_success_body, auth::AuthenticatedAccessToken, http_error::AppError,
request_context::RequestContext, state::AppState,
api_response::json_success_body,
auth::AuthenticatedAccessToken,
http_error::AppError,
request_context::RequestContext,
state::AppState,
work_play_tracking::{record_work_play_start_after_success, WorkPlayTrackingDraft},
};
const JUMP_HOP_PROVIDER: &str = "jump-hop";
@@ -26,6 +30,8 @@ const JUMP_HOP_CREATION_PROVIDER: &str = "jump-hop-creation";
const JUMP_HOP_RUNTIME_PROVIDER: &str = "jump-hop-runtime";
const JUMP_HOP_TEMPLATE_ID: &str = "jump-hop";
const JUMP_HOP_TEMPLATE_NAME: &str = "跳一跳";
const JUMP_HOP_ANONYMOUS_RUNTIME_OWNER_ID: &str = "anonymous-runtime";
const JUMP_HOP_RUNTIME_RUNS_ROUTE: &str = "/api/runtime/jump-hop/runs";
pub async fn create_jump_hop_session(
State(state): State<AppState>,
@@ -170,14 +176,18 @@ pub async fn get_jump_hop_runtime_work(
pub async fn start_jump_hop_run(
State(state): State<AppState>,
Extension(request_context): Extension<RequestContext>,
Extension(authenticated): Extension<AuthenticatedAccessToken>,
maybe_authenticated: Option<Extension<AuthenticatedAccessToken>>,
payload: Result<Json<JumpHopStartRunRequest>, JsonRejection>,
) -> Result<Json<Value>, Response> {
let Json(payload) = jump_hop_json(payload, &request_context, JUMP_HOP_RUNTIME_PROVIDER)?;
ensure_non_empty(&request_context, &payload.profile_id, "profileId")?;
let authenticated = maybe_authenticated.as_ref().map(|Extension(authenticated)| authenticated);
let owner_user_id = authenticated
.map(|authenticated| authenticated.claims().user_id().to_string())
.unwrap_or_else(|| JUMP_HOP_ANONYMOUS_RUNTIME_OWNER_ID.to_string());
let run = state
.spacetime_client()
.start_jump_hop_run(payload, authenticated.claims().user_id().to_string())
.start_jump_hop_run(payload, owner_user_id.clone())
.await
.map_err(|error| {
jump_hop_error_response(
@@ -187,6 +197,24 @@ pub async fn start_jump_hop_run(
)
})?;
record_work_play_start_after_success(
&state,
&request_context,
build_jump_hop_work_play_tracking_draft(
authenticated,
run.profile_id.clone(),
JUMP_HOP_RUNTIME_RUNS_ROUTE,
)
.owner_user_id(run.owner_user_id.clone())
.run_id(run.run_id.clone())
.profile_id(run.profile_id.clone())
.extra(json!({
"runStatus": run.status,
"isAnonymous": maybe_authenticated.is_none(),
})),
)
.await;
Ok(json_success_body(
Some(&request_context),
JumpHopRunResponse { run },
@@ -197,18 +225,18 @@ pub async fn jump_hop_run_jump(
State(state): State<AppState>,
Path(run_id): Path<String>,
Extension(request_context): Extension<RequestContext>,
Extension(authenticated): Extension<AuthenticatedAccessToken>,
maybe_authenticated: Option<Extension<AuthenticatedAccessToken>>,
payload: Result<Json<JumpHopJumpRequest>, JsonRejection>,
) -> Result<Json<Value>, Response> {
ensure_non_empty(&request_context, &run_id, "runId")?;
let Json(payload) = jump_hop_json(payload, &request_context, JUMP_HOP_RUNTIME_PROVIDER)?;
let owner_user_id = maybe_authenticated
.as_ref()
.map(|Extension(authenticated)| authenticated.claims().user_id().to_string())
.unwrap_or_else(|| JUMP_HOP_ANONYMOUS_RUNTIME_OWNER_ID.to_string());
let run = state
.spacetime_client()
.jump_hop_run_jump(
run_id,
authenticated.claims().user_id().to_string(),
payload,
)
.jump_hop_run_jump(run_id, owner_user_id, payload)
.await
.map_err(|error| {
jump_hop_error_response(
@@ -228,18 +256,18 @@ pub async fn restart_jump_hop_run(
State(state): State<AppState>,
Path(run_id): Path<String>,
Extension(request_context): Extension<RequestContext>,
Extension(authenticated): Extension<AuthenticatedAccessToken>,
maybe_authenticated: Option<Extension<AuthenticatedAccessToken>>,
payload: Result<Json<JumpHopRestartRunRequest>, JsonRejection>,
) -> Result<Json<Value>, Response> {
ensure_non_empty(&request_context, &run_id, "runId")?;
let Json(payload) = jump_hop_json(payload, &request_context, JUMP_HOP_RUNTIME_PROVIDER)?;
let owner_user_id = maybe_authenticated
.as_ref()
.map(|Extension(authenticated)| authenticated.claims().user_id().to_string())
.unwrap_or_else(|| JUMP_HOP_ANONYMOUS_RUNTIME_OWNER_ID.to_string());
let run = state
.spacetime_client()
.restart_jump_hop_run(
run_id,
authenticated.claims().user_id().to_string(),
payload,
)
.restart_jump_hop_run(run_id, owner_user_id, payload)
.await
.map_err(|error| {
jump_hop_error_response(
@@ -298,6 +326,19 @@ pub async fn get_jump_hop_gallery_detail(
))
}
fn build_jump_hop_work_play_tracking_draft(
authenticated: Option<&AuthenticatedAccessToken>,
work_id: impl Into<String>,
source_route: &'static str,
) -> WorkPlayTrackingDraft {
match authenticated {
Some(authenticated) => {
WorkPlayTrackingDraft::new("jump-hop", work_id, authenticated, source_route)
}
None => WorkPlayTrackingDraft::anonymous("jump-hop", work_id, source_route),
}
}
fn build_jump_hop_draft(payload: &JumpHopWorkspaceCreateRequest) -> JumpHopDraftResponse {
JumpHopDraftResponse {
template_id: JUMP_HOP_TEMPLATE_ID.to_string(),