合并 origin/master:网站游戏评分与评价

This commit is contained in:
kdletters
2026-10-01 19:41:30 +08:00
81 changed files with 8594 additions and 60 deletions
+1
View File
@@ -5472,6 +5472,7 @@ dependencies = [
"module-ai",
"module-assets",
"module-editor-agent",
"module-game-distribution",
"module-runtime",
"serde",
"serde_json",
+67
View File
@@ -2215,6 +2215,12 @@ fn admin_permission_requirement(_method: &Method, path: &str) -> AdminPermission
"/admin/api/editor-assets" => AnyTab(&["editor-assets"]),
"/admin/api/assets/read-url" => AnyTab(&["editor-assets", "editor-showcase"]),
path if path.starts_with("/admin/api/editor-showcase/") => AnyTab(&["editor-showcase"]),
"/admin/api/game-distribution/user-review-games" => AnyTab(&["game-reviews"]),
path if path == "/admin/api/game-distribution/user-reviews"
|| path.starts_with("/admin/api/game-distribution/user-reviews/") =>
{
AnyTab(&["game-reviews"])
}
path if path.starts_with("/admin/api/game-distribution/reviews") => {
AnyTab(&["editor-showcase"])
}
@@ -7502,6 +7508,67 @@ mod tests {
);
}
#[test]
fn game_reviews_tab_authorizes_all_user_review_routes_only() {
for (method, path) in [
(
Method::GET,
"/admin/api/game-distribution/user-review-games",
),
(Method::GET, "/admin/api/game-distribution/user-reviews"),
(
Method::GET,
"/admin/api/game-distribution/user-reviews/review_1",
),
(
Method::POST,
"/admin/api/game-distribution/user-reviews/review_1/moderation",
),
] {
assert!(enforce_admin_request_permission("owner", &[], &[], &method, path).is_ok());
assert!(
enforce_admin_request_permission(
"member",
&["game-reviews".into()],
&[],
&method,
path
)
.is_ok()
);
for permissions in [
vec![],
vec!["game-management".into()],
vec!["editor-showcase".into()],
] {
assert_eq!(
enforce_admin_request_permission("member", &permissions, &[], &method, path)
.unwrap_err()
.status_code(),
StatusCode::FORBIDDEN
);
}
}
for path in [
"/admin/api/game-distribution/reviews",
"/admin/api/game-distribution/games",
"/admin/api/game-distribution/versions/version_1/review",
] {
assert_eq!(
enforce_admin_request_permission(
"member",
&["game-reviews".into()],
&[],
&Method::GET,
path
)
.unwrap_err()
.status_code(),
StatusCode::FORBIDDEN
);
}
}
#[test]
fn wallet_consumption_reconcile_requires_its_standalone_action_permission() {
assert!(
File diff suppressed because it is too large Load Diff
@@ -5,6 +5,14 @@ mod errors;
mod events;
mod package;
mod release;
mod reviews;
pub use reviews::{
ReviewModerationValidationError, UserReviewValidationError, normalize_review_comment,
normalize_review_moderation_reason, review_id, review_matches_filters,
review_moderation_operation_id, review_order, review_summary, validate_review_list_status,
visible_review_summary,
};
pub use application::{
GameDistributionService, GameOperationResult, InMemoryGameDistributionStore,
@@ -0,0 +1,300 @@
use std::{cmp::Ordering, fmt};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UserReviewValidationError {
InvalidScore,
CommentTooLong,
}
impl fmt::Display for UserReviewValidationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::InvalidScore => "评分必须为 1–10 的整数",
Self::CommentTooLong => "评论最多 4000 字符",
})
}
}
pub fn normalize_review_comment(
score: i64,
comment: &str,
) -> Result<String, UserReviewValidationError> {
if !(1..=10).contains(&score) {
return Err(UserReviewValidationError::InvalidScore);
}
let comment = comment.replace("\r\n", "\n").replace('\r', "\n");
if comment.chars().count() > 4000 {
return Err(UserReviewValidationError::CommentTooLong);
}
Ok(if comment.trim().is_empty() {
String::new()
} else {
comment
})
}
/// 长度前缀使任意游戏和账号组合都只有一个无歧义的主键。
pub fn review_id(game_id: &str, user_id: &str) -> String {
format!("{}:{game_id}{user_id}", game_id.len())
}
pub fn review_summary(scores: impl Iterator<Item = i64>) -> (Option<f64>, u64) {
let (sum, count) = scores.fold((0u64, 0u64), |(sum, count), score| {
(sum + score as u64, count + 1)
});
let average = (count > 0).then(|| ((sum as f64 / count as f64) * 10.0).round() / 10.0);
(average, count)
}
pub fn visible_review_summary(reviews: impl Iterator<Item = (i64, bool)>) -> (Option<f64>, u64) {
review_summary(
reviews
.filter(|(_, is_hidden)| !is_hidden)
.map(|(score, _)| score),
)
}
pub fn review_order(
left_created: i64,
left_id: &str,
right_created: i64,
right_id: &str,
) -> Ordering {
right_created
.cmp(&left_created)
.then_with(|| right_id.cmp(left_id))
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ReviewModerationValidationError {
InvalidAction,
InvalidStatus,
InvalidReason,
}
impl fmt::Display for ReviewModerationValidationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::InvalidAction => "REVIEW_BAD_REQUEST: 管理动作须为 hide、restore 或 delete",
Self::InvalidStatus => "REVIEW_BAD_REQUEST: 状态须为 all、visible 或 hidden",
Self::InvalidReason => "REVIEW_VALIDATION: 原因去除首尾空白后须为 1–4000 字符",
})
}
}
pub fn normalize_review_moderation_reason(
action: &str,
reason: Option<&str>,
) -> Result<Option<String>, ReviewModerationValidationError> {
match action {
"restore" => Ok(None),
"hide" | "delete" => {
let reason = reason.unwrap_or("").trim();
if !(1..=4000).contains(&reason.chars().count()) {
return Err(ReviewModerationValidationError::InvalidReason);
}
Ok(Some(reason.to_string()))
}
_ => Err(ReviewModerationValidationError::InvalidAction),
}
}
pub fn validate_review_list_status(status: &str) -> Result<(), ReviewModerationValidationError> {
match status {
"all" | "visible" | "hidden" => Ok(()),
_ => Err(ReviewModerationValidationError::InvalidStatus),
}
}
pub fn review_matches_filters(
review_game_id: &str,
review_user_id: &str,
comment: &str,
is_hidden: bool,
game_id: Option<&str>,
user_id: Option<&str>,
keyword: Option<&str>,
status: &str,
) -> bool {
game_id.is_none_or(|value| value == review_game_id)
&& user_id.is_none_or(|value| value == review_user_id)
&& keyword.is_none_or(|value| comment.contains(value))
&& match status {
"all" => true,
"visible" => !is_hidden,
"hidden" => is_hidden,
_ => false,
}
}
pub fn review_moderation_operation_id(admin_user_id: &str, idempotency_key: &str) -> String {
format!("{}:{admin_user_id}{idempotency_key}", admin_user_id.len())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn review_score_and_comment_follow_unicode_contract() {
for score in [1, 10] {
assert_eq!(normalize_review_comment(score, ""), Ok(String::new()));
}
for score in [0, 11, -1] {
assert_eq!(
normalize_review_comment(score, ""),
Err(UserReviewValidationError::InvalidScore)
);
}
assert_eq!(
normalize_review_comment(7, " 中文😀\r\n英文\r "),
Ok(" 中文😀\n英文\n ".into())
);
assert!(normalize_review_comment(7, &"😀".repeat(4000)).is_ok());
assert_eq!(
normalize_review_comment(7, &"😀".repeat(4001)),
Err(UserReviewValidationError::CommentTooLong)
);
assert_eq!(
normalize_review_comment(7, &" ".repeat(4000)),
Ok(String::new())
);
assert_eq!(
normalize_review_comment(7, &" ".repeat(4001)),
Err(UserReviewValidationError::CommentTooLong)
);
assert_eq!(
normalize_review_comment(7, &"\r\n".repeat(4000)),
Ok(String::new())
);
}
#[test]
fn review_identity_sort_and_summary_are_stable() {
assert_ne!(review_id("a", "bc"), review_id("ab", "c"));
assert_ne!(review_id("a:", "b"), review_id("a", ":b"));
assert_eq!(review_summary([].into_iter()), (None, 0));
assert_eq!(review_summary([8, 8, 9].into_iter()), (Some(8.3), 3));
assert_eq!(review_summary([10, 1].into_iter()), (Some(5.5), 2));
assert_eq!(review_order(1, "z", 2, "a"), Ordering::Greater);
assert_eq!(review_order(2, "b", 2, "a"), Ordering::Less);
}
#[test]
fn moderation_reason_and_action_follow_contract() {
for action in ["hide", "delete"] {
assert_eq!(
normalize_review_moderation_reason(action, None),
Err(ReviewModerationValidationError::InvalidReason)
);
assert_eq!(
normalize_review_moderation_reason(action, Some(" \n ")),
Err(ReviewModerationValidationError::InvalidReason)
);
assert_eq!(
normalize_review_moderation_reason(action, Some(" 原因😀 \n")),
Ok(Some("原因😀".into()))
);
assert!(normalize_review_moderation_reason(action, Some(&"😀".repeat(4000))).is_ok());
assert_eq!(
normalize_review_moderation_reason(action, Some(&"😀".repeat(4001))),
Err(ReviewModerationValidationError::InvalidReason)
);
}
assert_eq!(
normalize_review_moderation_reason("restore", None),
Ok(None)
);
assert_eq!(
normalize_review_moderation_reason("restore", Some("忽略")),
Ok(None)
);
assert_eq!(
normalize_review_moderation_reason("edit", Some("原因")),
Err(ReviewModerationValidationError::InvalidAction)
);
assert_ne!(
review_moderation_operation_id("a", "bc"),
review_moderation_operation_id("ab", "c")
);
assert_ne!(
review_moderation_operation_id("admin1", "key"),
review_moderation_operation_id("admin2", "key")
);
}
#[test]
fn review_filters_combine_exact_ids_case_sensitive_text_and_visibility() {
assert!(review_matches_filters(
"game1",
"user1",
"Text 中文",
true,
Some("game1"),
Some("user1"),
Some("Text"),
"hidden"
));
assert!(!review_matches_filters(
"game1",
"user1",
"Text 中文",
true,
Some("game1"),
Some("user1"),
Some("text"),
"hidden"
));
assert!(!review_matches_filters(
"game1",
"user1",
"Text",
true,
Some("game2"),
None,
None,
"all"
));
assert!(!review_matches_filters(
"game1",
"user1",
"",
false,
None,
None,
Some("Text"),
"visible"
));
assert!(!review_matches_filters(
"game1", "user1", "", true, None, None, None, "visible"
));
assert!(review_matches_filters(
"game1", "user1", "", false, None, None, None, "visible"
));
assert_eq!(validate_review_list_status("all"), Ok(()));
assert_eq!(
validate_review_list_status("published"),
Err(ReviewModerationValidationError::InvalidStatus)
);
}
#[test]
fn hidden_reviews_never_contribute_to_public_rating_summary() {
assert_eq!(
visible_review_summary([(10, true), (1, true)].into_iter()),
(None, 0)
);
assert_eq!(
visible_review_summary([(10, true), (1, false), (9, false)].into_iter()),
(Some(5.0), 2)
);
assert_eq!(
visible_review_summary([(1, true), (1, false), (9, false)].into_iter()),
(Some(5.0), 2)
);
assert_eq!(
visible_review_summary([(10, false), (1, false), (9, false)].into_iter()),
(Some(6.7), 3)
);
}
}
+162 -1
View File
@@ -10,7 +10,7 @@ use crate::creation_entry_config::{
};
/// 后台 member 可被授予的一级 Tab 权限;账号管理仅 owner 可见,不进入该集合。
pub const ADMIN_TAB_PERMISSIONS: [&str; 20] = [
pub const ADMIN_TAB_PERMISSIONS: [&str; 21] = [
"dashboard",
"overview",
"tables",
@@ -27,12 +27,124 @@ pub const ADMIN_TAB_PERMISSIONS: [&str; 20] = [
"editor-generation-pricing",
"editor-showcase",
"game-management",
"game-reviews",
"editor-assets",
"agc-templates",
"error-reports",
"project-snapshots",
];
/// 后台游戏评价的游戏选择查询,覆盖全部游戏可见状态。
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewGamesQuery {
pub query: Option<String>,
pub page: Option<u32>,
pub page_size: Option<u32>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewGame {
pub game_id: String,
pub title: String,
pub status: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewGamesResponse {
pub games: Vec<AdminGameReviewGame>,
pub page: u32,
pub page_size: u32,
pub total: u64,
pub total_pages: u64,
}
/// 用户 ID 精确匹配;关键词与其他条件由后端按 AND 组合筛选。
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewsQuery {
pub game_id: Option<String>,
pub user_id: Option<String>,
pub keyword: Option<String>,
pub status: Option<String>,
pub page: Option<u32>,
pub page_size: Option<u32>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewGameInfo {
pub title: String,
pub status: String,
}
/// 后台完整评价;管理原因只保存在后台操作记录,不进入普通用户投影。
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReview {
pub id: String,
pub game_id: String,
pub game: AdminGameReviewGameInfo,
pub author: crate::game_distribution::GameDistributionAuthor,
pub score: i64,
pub comment: String,
pub is_hidden: bool,
pub created_at: String,
pub updated_at: String,
}
/// 管理操作记录不复制评论正文;删除后依旧保留目标身份与原创建时间。
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewOperation {
pub id: String,
pub review_id: String,
pub game_id: String,
pub user_id: String,
pub review_created_at: String,
pub action: String,
pub admin_user_id: String,
pub reason: Option<String>,
pub created_at: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewsResponse {
pub reviews: Vec<AdminGameReview>,
pub page: u32,
pub page_size: u32,
pub total: u64,
pub total_pages: u64,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewDetailResponse {
pub review: AdminGameReview,
pub operations: Vec<AdminGameReviewOperation>,
}
/// 原创建时间保护删除后重新评价的实例;管理员身份来自会话。
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewModerationRequest {
pub action: String,
pub expected_created_at: String,
#[serde(default)]
pub reason: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct AdminGameReviewModerationResponse {
pub review: Option<AdminGameReview>,
pub operation: AdminGameReviewOperation,
pub replayed: bool,
}
/// 私有工程快照的后台分页查询。
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
@@ -1298,6 +1410,55 @@ mod tests {
AdminUpdateAgcTemplateRequest,
};
#[test]
fn game_review_contract_uses_camel_case_and_nullable_operation_result() {
use super::{
AdminGameReviewModerationRequest, AdminGameReviewModerationResponse,
AdminGameReviewOperation,
};
let request: AdminGameReviewModerationRequest = serde_json::from_value(json!({
"action":"restore", "expectedCreatedAt":"2026-10-01T00:00:00Z",
}))
.unwrap();
assert!(request.reason.is_none());
assert_eq!(
serde_json::to_value(request).unwrap()["expectedCreatedAt"],
"2026-10-01T00:00:00Z"
);
for value in [
json!({"action":1,"expectedCreatedAt":"2026-10-01T00:00:00Z"}),
json!({"action":"restore","expectedCreatedAt":1}),
json!({"action":"hide","expectedCreatedAt":"2026-10-01T00:00:00Z","reason":123}),
] {
assert!(serde_json::from_value::<AdminGameReviewModerationRequest>(value).is_err());
}
let response = serde_json::to_value(AdminGameReviewModerationResponse {
review: None,
replayed: true,
operation: AdminGameReviewOperation {
id: "operation-1".into(),
review_id: "review-1".into(),
game_id: "game-1".into(),
user_id: "user-1".into(),
review_created_at: "2026-10-01T00:00:00Z".into(),
action: "restore".into(),
admin_user_id: "admin-1".into(),
reason: None,
created_at: "2026-10-01T00:00:01Z".into(),
},
})
.unwrap();
assert!(response["review"].is_null());
assert!(response["operation"]["reason"].is_null());
assert_eq!(
response["operation"]["reviewCreatedAt"],
"2026-10-01T00:00:00Z"
);
assert_eq!(response["operation"]["adminUserId"], "admin-1");
assert!(response["operation"].get("comment").is_none());
assert!(ADMIN_TAB_PERMISSIONS.contains(&"game-reviews"));
}
#[test]
fn agc_template_snapshot_uses_camel_case_and_assignable_tab_permission() {
let value = serde_json::to_value(AdminAgcTemplateListResponse {
@@ -90,6 +90,59 @@ pub struct GameDistributionAuthor {
pub avatar_url: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionReview {
pub id: String,
pub game_id: String,
pub author: GameDistributionAuthor,
pub score: i64,
pub comment: String,
#[serde(default)]
pub is_hidden: bool,
pub created_at: String,
pub updated_at: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionRatingSummary {
pub average_score: Option<f64>,
pub rating_count: u64,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionReviewsResponse {
pub reviews: Vec<GameDistributionReview>,
pub page: u32,
pub page_size: u32,
pub total: u64,
pub total_pages: u64,
pub rating_summary: GameDistributionRatingSummary,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionMyReviewResponse {
pub review: Option<GameDistributionReview>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionSaveReviewRequest {
pub score: i64,
#[serde(default)]
pub comment: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionSaveReviewResponse {
pub review: GameDistributionReview,
pub rating_summary: GameDistributionRatingSummary,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionVersionSummary {
@@ -102,7 +155,7 @@ pub struct GameDistributionVersionSummary {
pub controls: Vec<String>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionGameSummary {
pub id: String,
@@ -131,9 +184,12 @@ pub struct GameDistributionGameSummary {
pub current_version: Option<GameDistributionVersionSummary>,
pub play_count: u64,
pub created_at: String,
/// 公开列表/详情保证返回;作者侧及旧响应可省略。
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rating_summary: Option<GameDistributionRatingSummary>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GameDistributionListResponse {
pub games: Vec<GameDistributionGameSummary>,
@@ -196,6 +252,34 @@ pub struct GameDistributionPrivateVersion {
mod tests {
use super::*;
#[test]
fn save_review_request_requires_integer_score_and_defaults_comment() {
let request: GameDistributionSaveReviewRequest =
serde_json::from_value(serde_json::json!({"score": 10})).unwrap();
assert_eq!(request.comment, "");
for payload in [
serde_json::json!({}),
serde_json::json!({"score": 8.5}),
serde_json::json!({"score": "8"}),
serde_json::json!({"score": 8, "comment": null}),
serde_json::json!({"score": 8, "comment": 123}),
] {
assert!(serde_json::from_value::<GameDistributionSaveReviewRequest>(payload).is_err());
}
let response =
serde_json::to_value(GameDistributionMyReviewResponse { review: None }).unwrap();
assert_eq!(response, serde_json::json!({"review": null}));
let summary = serde_json::to_value(GameDistributionRatingSummary {
average_score: None,
rating_count: 0,
})
.unwrap();
assert_eq!(
summary,
serde_json::json!({"averageScore": null, "ratingCount": 0})
);
}
#[test]
fn create_game_request_round_trips_local_project_id() {
let payload: GameDistributionCreateGameRequest =
@@ -22,14 +22,15 @@ mod error_reports;
pub mod external_api_key;
pub mod game_distribution;
pub use game_distribution::{
GameDistributionAdminGameListRecordInput, GameDistributionApproveRecordInput,
GameDistributionCancelVersionRecordInput, GameDistributionConfirmPackageRecordInput,
GameDistributionCreateGameRecordInput, GameDistributionCreateVersionRecordInput,
GameDistributionFailUploadRecordInput, GameDistributionGetGameRecordInput,
GameDistributionOwnerGameListRecordInput, GameDistributionPublicGameListRecordInput,
GameDistributionRejectRecordInput, GameDistributionRestoreRecordInput,
GameDistributionSubmitReviewRecordInput, GameDistributionSuspendRecordInput,
GameDistributionUnpublishRecordInput,
GameDistributionAdminGameListRecordInput, GameDistributionAdminUserReviewListRecordInput,
GameDistributionApproveRecordInput, GameDistributionCancelVersionRecordInput,
GameDistributionConfirmPackageRecordInput, GameDistributionCreateGameRecordInput,
GameDistributionCreateVersionRecordInput, GameDistributionFailUploadRecordInput,
GameDistributionGetGameRecordInput, GameDistributionOwnerGameListRecordInput,
GameDistributionPublicGameListRecordInput, GameDistributionRejectRecordInput,
GameDistributionRestoreRecordInput, GameDistributionReviewGameListRecordInput,
GameDistributionReviewModerationRecordInput, GameDistributionSubmitReviewRecordInput,
GameDistributionSuspendRecordInput, GameDistributionUnpublishRecordInput,
};
#[path = "active/external_generation.rs"]
pub mod external_generation;
@@ -92,8 +92,14 @@ pub use self::external_generation::{
ExternalGenerationQueueStatsRecord,
};
pub use self::game_distribution::{
GameDistributionAdminGameRecord, GameDistributionAdminVersionRecord,
GameDistributionGameRecord, GameDistributionOwnerGameRecord, GameDistributionPublicGameRecord,
GameDistributionAdminGameRecord, GameDistributionAdminUserReviewDetailRecord,
GameDistributionAdminUserReviewListRecord, GameDistributionAdminUserReviewRecord,
GameDistributionAdminVersionRecord, GameDistributionGameRecord,
GameDistributionOwnerGameRecord, GameDistributionPublicGameRecord,
GameDistributionRatingSummaryRecord, GameDistributionReviewGameListRecord,
GameDistributionReviewGameRecord, GameDistributionReviewModerationOperationRecord,
GameDistributionReviewModerationRecord, GameDistributionUserReviewListRecord,
GameDistributionUserReviewRecord, GameDistributionUserReviewSaveRecord,
GameDistributionVersionRecord,
};
pub use self::llm_router_account::{LlmRouterAccountRecord, LlmRouterAccountUpsertRecordInput};
@@ -149,10 +155,11 @@ pub(crate) use self::external_generation::{
map_external_generation_queue_stats_result,
};
pub(crate) use self::game_distribution::{
ensure_admin_user_review_result, ensure_user_review_result, map_admin_user_review,
map_game_distribution_admin_game_list_result, map_game_distribution_game_result,
map_game_distribution_owner_game_list_result, map_game_distribution_public_game_list_result,
map_game_distribution_public_game_result, map_game_distribution_review_list_result,
map_game_distribution_version_result,
map_game_distribution_version_result, map_review_moderation_operation, map_user_review,
};
pub(crate) use self::runtime::{
map_feature_gate_config_procedure_result, map_runtime_setting_procedure_result,
@@ -1,5 +1,160 @@
use super::*;
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionUserReviewRecord {
pub review_id: String,
pub game_id: String,
pub author_id: String,
pub author_name: String,
pub author_avatar_url: Option<String>,
pub score: i64,
pub comment: String,
pub created_at_micros: i64,
pub updated_at_micros: i64,
pub is_hidden: bool,
}
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct GameDistributionRatingSummaryRecord {
pub average_score: Option<f64>,
pub rating_count: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionUserReviewListRecord {
pub reviews: Vec<GameDistributionUserReviewRecord>,
pub page: u32,
pub page_size: u32,
pub total: u64,
pub total_pages: u64,
pub rating_summary: GameDistributionRatingSummaryRecord,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionUserReviewSaveRecord {
pub review: GameDistributionUserReviewRecord,
pub rating_summary: GameDistributionRatingSummaryRecord,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionAdminUserReviewRecord {
pub review: GameDistributionUserReviewRecord,
pub game_title: String,
pub game_status: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionReviewModerationOperationRecord {
pub operation_id: String,
pub review_id: String,
pub game_id: String,
pub user_id: String,
pub review_created_at_micros: i64,
pub action: String,
pub admin_user_id: String,
pub reason: Option<String>,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionReviewGameRecord {
pub game_id: String,
pub title: String,
pub status: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionAdminUserReviewListRecord {
pub reviews: Vec<GameDistributionAdminUserReviewRecord>,
pub page: u32,
pub page_size: u32,
pub total: u64,
pub total_pages: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionReviewGameListRecord {
pub games: Vec<GameDistributionReviewGameRecord>,
pub page: u32,
pub page_size: u32,
pub total: u64,
pub total_pages: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionAdminUserReviewDetailRecord {
pub review: GameDistributionAdminUserReviewRecord,
pub operations: Vec<GameDistributionReviewModerationOperationRecord>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GameDistributionReviewModerationRecord {
pub review: Option<GameDistributionAdminUserReviewRecord>,
pub operation: GameDistributionReviewModerationOperationRecord,
pub replayed: bool,
}
pub(crate) fn map_admin_user_review(
snapshot: crate::module_bindings::GameDistributionAdminUserReviewSnapshot,
) -> GameDistributionAdminUserReviewRecord {
GameDistributionAdminUserReviewRecord {
review: map_user_review(snapshot.review),
game_title: snapshot.game_title,
game_status: snapshot.game_status,
}
}
pub(crate) fn map_review_moderation_operation(
snapshot: crate::module_bindings::GameDistributionReviewModerationOperationSnapshot,
) -> GameDistributionReviewModerationOperationRecord {
GameDistributionReviewModerationOperationRecord {
operation_id: snapshot.operation_id,
review_id: snapshot.review_id,
game_id: snapshot.game_id,
user_id: snapshot.user_id,
review_created_at_micros: snapshot.review_created_at_micros,
action: snapshot.action,
admin_user_id: snapshot.admin_user_id,
reason: snapshot.reason,
created_at_micros: snapshot.created_at_micros,
}
}
pub(crate) fn ensure_admin_user_review_result(
result: crate::module_bindings::GameDistributionAdminUserReviewResult,
) -> Result<crate::module_bindings::GameDistributionAdminUserReviewResult, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result)
}
pub(crate) fn map_user_review(
snapshot: crate::module_bindings::GameDistributionUserReviewSnapshot,
) -> GameDistributionUserReviewRecord {
GameDistributionUserReviewRecord {
review_id: snapshot.review_id,
game_id: snapshot.game_id,
author_id: snapshot.author_id,
author_name: snapshot.author_name,
author_avatar_url: snapshot.author_avatar_url,
score: snapshot.score,
comment: snapshot.comment,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
is_hidden: snapshot.is_hidden,
}
}
pub(crate) fn ensure_user_review_result(
result: crate::module_bindings::GameDistributionUserReviewResult,
) -> Result<crate::module_bindings::GameDistributionUserReviewResult, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result)
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct GameDistributionGameRecord {
pub game_id: String,
@@ -85,10 +240,11 @@ pub struct GameDistributionOwnerGameRecord {
pub versions: Vec<GameDistributionVersionRecord>,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct GameDistributionPublicGameRecord {
pub game: GameDistributionGameRecord,
pub current_version: Option<GameDistributionVersionRecord>,
pub rating_summary: GameDistributionRatingSummaryRecord,
}
fn map_game(
@@ -242,6 +398,10 @@ pub(crate) fn map_game_distribution_public_game_list_result(
.map(|value| GameDistributionPublicGameRecord {
game: map_game(value.game),
current_version: value.current_version.map(map_version),
rating_summary: GameDistributionRatingSummaryRecord {
average_score: value.average_score,
rating_count: value.rating_count,
},
})
.collect())
}
@@ -264,6 +424,10 @@ pub(crate) fn map_game_distribution_public_game_result(
Ok(result.game.map(|value| GameDistributionPublicGameRecord {
game: map_game(value.game),
current_version: value.current_version.map(map_version),
rating_summary: GameDistributionRatingSummaryRecord {
average_score: value.average_score,
rating_count: value.rating_count,
},
}))
}
@@ -1,5 +1,32 @@
use super::*;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GameDistributionAdminUserReviewListRecordInput {
pub game_id: Option<String>,
pub user_id: Option<String>,
pub keyword: Option<String>,
pub status: String,
pub page: u32,
pub page_size: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GameDistributionReviewGameListRecordInput {
pub query: Option<String>,
pub page: u32,
pub page_size: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GameDistributionReviewModerationRecordInput {
pub review_id: String,
pub admin_user_id: String,
pub action: String,
pub idempotency_key: String,
pub expected_created_at_micros: i64,
pub reason: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GameDistributionPublicGameListRecordInput {
pub search: Option<String>,
@@ -165,6 +192,284 @@ pub struct GameDistributionSuspendRecordInput {
}
impl SpacetimeClient {
pub async fn list_admin_game_distribution_user_reviews(
&self,
input: GameDistributionAdminUserReviewListRecordInput,
) -> Result<GameDistributionAdminUserReviewListRecord, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionAdminUserReviewListInput {
game_id: input.game_id,
user_id: input.user_id,
keyword: input.keyword,
status: input.status,
page: input.page,
page_size: input.page_size,
};
self.call_after_connect(
"list_admin_game_distribution_user_reviews",
move |connection, sender| {
connection
.procedures()
.list_admin_game_distribution_user_reviews_and_return_then(
input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(ensure_admin_user_review_result)
.map(|result| GameDistributionAdminUserReviewListRecord {
reviews: result
.reviews
.into_iter()
.map(map_admin_user_review)
.collect(),
page: result.page,
page_size: result.page_size,
total: result.total,
total_pages: result.total_pages,
});
send_once(&sender, mapped);
},
);
},
)
.await
}
pub async fn list_game_distribution_review_games(
&self,
input: GameDistributionReviewGameListRecordInput,
) -> Result<GameDistributionReviewGameListRecord, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionReviewGameListInput {
query: input.query,
page: input.page,
page_size: input.page_size,
};
self.call_after_connect(
"list_game_distribution_review_games",
move |connection, sender| {
connection
.procedures()
.list_game_distribution_review_games_and_return_then(
input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(ensure_admin_user_review_result)
.map(|result| GameDistributionReviewGameListRecord {
games: result
.games
.into_iter()
.map(|game| GameDistributionReviewGameRecord {
game_id: game.game_id,
title: game.title,
status: game.status,
})
.collect(),
page: result.page,
page_size: result.page_size,
total: result.total,
total_pages: result.total_pages,
});
send_once(&sender, mapped);
},
);
},
)
.await
}
pub async fn get_admin_game_distribution_user_review(
&self,
review_id: String,
) -> Result<GameDistributionAdminUserReviewDetailRecord, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionAdminUserReviewInput { review_id };
self.call_after_connect(
"get_admin_game_distribution_user_review",
move |connection, sender| {
connection
.procedures()
.get_admin_game_distribution_user_review_and_return_then(
input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(ensure_admin_user_review_result)
.and_then(|result| {
let review = result.review.ok_or_else(|| {
SpacetimeClientError::procedure_failed(Some(
"REVIEW_NOT_FOUND: 评价不存在".into(),
))
})?;
Ok(GameDistributionAdminUserReviewDetailRecord {
review: map_admin_user_review(review),
operations: result
.operations
.into_iter()
.map(map_review_moderation_operation)
.collect(),
})
});
send_once(&sender, mapped);
},
);
},
)
.await
}
pub async fn moderate_game_distribution_user_review(
&self,
input: GameDistributionReviewModerationRecordInput,
) -> Result<GameDistributionReviewModerationRecord, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionReviewModerationInput {
review_id: input.review_id,
admin_user_id: input.admin_user_id,
action: input.action,
idempotency_key: input.idempotency_key,
expected_created_at_micros: input.expected_created_at_micros,
reason: input.reason,
};
self.call_after_connect(
"moderate_game_distribution_user_review",
move |connection, sender| {
connection
.procedures()
.moderate_game_distribution_user_review_and_return_then(
input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(ensure_admin_user_review_result)
.and_then(|result| {
let operation = result.operation.ok_or_else(|| {
SpacetimeClientError::procedure_failed(Some(
"管理操作缺少结果".into(),
))
})?;
Ok(GameDistributionReviewModerationRecord {
review: result.review.map(map_admin_user_review),
operation: map_review_moderation_operation(operation),
replayed: result.replayed,
})
});
send_once(&sender, mapped);
},
);
},
)
.await
}
pub async fn list_game_distribution_user_reviews(
&self,
game_id: String,
page: u32,
page_size: u32,
) -> Result<GameDistributionUserReviewListRecord, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionUserReviewListInput {
game_id,
page,
page_size,
};
self.call_after_connect(
"list_game_distribution_user_reviews",
move |connection, sender| {
connection
.procedures()
.list_game_distribution_user_reviews_and_return_then(
input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(ensure_user_review_result)
.map(|result| GameDistributionUserReviewListRecord {
reviews: result
.reviews
.into_iter()
.map(map_user_review)
.collect(),
page: result.page,
page_size: result.page_size,
total: result.rating_count,
total_pages: result.total_pages,
rating_summary: GameDistributionRatingSummaryRecord {
average_score: result.average_score,
rating_count: result.rating_count,
},
});
send_once(&sender, mapped);
},
);
},
)
.await
}
pub async fn get_game_distribution_my_review(
&self,
game_id: String,
user_id: String,
) -> Result<Option<GameDistributionUserReviewRecord>, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionMyReviewInput { game_id, user_id };
self.call_after_connect(
"get_game_distribution_my_review",
move |connection, sender| {
connection
.procedures()
.get_game_distribution_my_review_and_return_then(input, move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(ensure_user_review_result)
.map(|result| result.review.map(map_user_review));
send_once(&sender, mapped);
});
},
)
.await
}
pub async fn save_game_distribution_my_review(
&self,
game_id: String,
user_id: String,
score: i64,
comment: String,
) -> Result<GameDistributionUserReviewSaveRecord, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionUserReviewInput {
game_id,
user_id,
score,
comment,
};
self.call_after_connect(
"save_game_distribution_my_review",
move |connection, sender| {
connection
.procedures()
.save_game_distribution_my_review_and_return_then(input, move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(ensure_user_review_result)
.and_then(|result| {
let review = result.review.ok_or_else(|| {
SpacetimeClientError::procedure_failed(Some(
"保存评价缺少结果".into(),
))
})?;
Ok(GameDistributionUserReviewSaveRecord {
review: map_user_review(review),
rating_summary: GameDistributionRatingSummaryRecord {
average_score: result.average_score,
rating_count: result.rating_count,
},
})
});
send_once(&sender, mapped);
});
},
)
.await
}
pub async fn list_game_distribution_games(
&self,
input: GameDistributionPublicGameListRecordInput,
@@ -401,6 +401,10 @@ pub mod find_editor_asset_group_source_and_return_procedure;
pub mod game_distribution_admin_game_list_input_type;
pub mod game_distribution_admin_game_list_result_type;
pub mod game_distribution_admin_game_snapshot_type;
pub mod game_distribution_admin_user_review_input_type;
pub mod game_distribution_admin_user_review_list_input_type;
pub mod game_distribution_admin_user_review_result_type;
pub mod game_distribution_admin_user_review_snapshot_type;
pub mod game_distribution_admin_version_snapshot_type;
pub mod game_distribution_approve_input_type;
pub mod game_distribution_cancel_version_input_type;
@@ -416,6 +420,7 @@ pub mod game_distribution_game_type;
pub mod game_distribution_get_game_input_type;
pub mod game_distribution_idempotency_receipt_table;
pub mod game_distribution_idempotency_receipt_type;
pub mod game_distribution_my_review_input_type;
pub mod game_distribution_owner_game_list_input_type;
pub mod game_distribution_owner_game_list_procedure_result_type;
pub mod game_distribution_owner_game_snapshot_type;
@@ -426,10 +431,22 @@ pub mod game_distribution_public_game_list_input_type;
pub mod game_distribution_public_game_snapshot_type;
pub mod game_distribution_reject_input_type;
pub mod game_distribution_restore_input_type;
pub mod game_distribution_review_game_list_input_type;
pub mod game_distribution_review_game_snapshot_type;
pub mod game_distribution_review_list_input_type;
pub mod game_distribution_review_moderation_input_type;
pub mod game_distribution_review_moderation_log_table;
pub mod game_distribution_review_moderation_log_type;
pub mod game_distribution_review_moderation_operation_snapshot_type;
pub mod game_distribution_review_table;
pub mod game_distribution_review_type;
pub mod game_distribution_submit_review_input_type;
pub mod game_distribution_suspend_input_type;
pub mod game_distribution_unpublish_input_type;
pub mod game_distribution_user_review_input_type;
pub mod game_distribution_user_review_list_input_type;
pub mod game_distribution_user_review_result_type;
pub mod game_distribution_user_review_snapshot_type;
pub mod game_distribution_version_lookup_input_type;
pub mod game_distribution_version_procedure_result_type;
pub mod game_distribution_version_snapshot_type;
@@ -438,6 +455,7 @@ pub mod game_distribution_version_type;
pub mod get_admin_account_by_id_and_return_procedure;
pub mod get_admin_account_by_username_and_return_procedure;
pub mod get_admin_dashboard_stats_and_return_procedure;
pub mod get_admin_game_distribution_user_review_and_return_procedure;
pub mod get_asset_object_by_id_and_return_procedure;
pub mod get_asset_object_by_location_and_return_procedure;
pub mod get_asset_read_access_by_location_and_return_procedure;
@@ -453,6 +471,7 @@ pub mod get_external_generation_job_summary_and_return_procedure;
pub mod get_external_generation_queue_stats_and_return_procedure;
pub mod get_feature_gate_config_procedure;
pub mod get_game_distribution_game_and_return_procedure;
pub mod get_game_distribution_my_review_and_return_procedure;
pub mod get_game_distribution_version_and_return_procedure;
pub mod get_llm_router_account_and_return_procedure;
pub mod get_owner_game_distribution_version_and_return_procedure;
@@ -474,6 +493,7 @@ pub mod import_database_migration_incremental_from_file_procedure;
pub mod initialize_editor_generation_pricing_config_if_missing_and_return_procedure;
pub mod list_admin_accounts_and_return_procedure;
pub mod list_admin_game_distribution_games_and_return_procedure;
pub mod list_admin_game_distribution_user_reviews_and_return_procedure;
pub mod list_agc_tracking_events_procedure;
pub mod list_asset_history_and_return_procedure;
pub mod list_editor_agent_conversations_and_return_procedure;
@@ -483,7 +503,9 @@ pub mod list_external_api_keys_and_return_procedure;
pub mod list_external_generation_job_summaries_and_return_procedure;
pub mod list_external_generation_jobs_and_return_procedure;
pub mod list_game_distribution_games_and_return_procedure;
pub mod list_game_distribution_review_games_and_return_procedure;
pub mod list_game_distribution_reviews_and_return_procedure;
pub mod list_game_distribution_user_reviews_and_return_procedure;
pub mod list_owner_game_distribution_games_and_return_procedure;
pub mod list_profile_recharge_refund_holds_for_reconciliation_procedure;
pub mod list_profile_recharge_refunds_for_reconciliation_procedure;
@@ -506,6 +528,7 @@ pub mod llm_router_quota_settlement_result_type;
pub mod mark_editor_showcase_asset_refunded_and_return_procedure;
pub mod mark_profile_recharge_order_expiration_checked_procedure;
pub mod mark_profile_recharge_order_paid_and_return_procedure;
pub mod moderate_game_distribution_user_review_and_return_procedure;
pub mod normalize_editor_character_animation_metadata_and_return_procedure;
pub mod persist_editor_generation_result_and_return_procedure;
pub mod persist_editor_pixel_art_result_and_return_procedure;
@@ -748,6 +771,7 @@ pub mod save_editor_project_layout_ack_procedure;
pub mod save_editor_project_layout_and_return_procedure;
pub mod save_editor_project_layout_v_2_ack_procedure;
pub mod save_editor_project_layout_v_2_and_return_procedure;
pub mod save_game_distribution_my_review_and_return_procedure;
pub mod seed_analytics_date_dimensions_reducer;
pub mod set_editor_showcase_asset_like_for_viewer_and_return_procedure;
pub mod settle_llm_router_quota_and_return_procedure;
@@ -1178,6 +1202,10 @@ pub use find_editor_asset_group_source_and_return_procedure::find_editor_asset_g
pub use game_distribution_admin_game_list_input_type::GameDistributionAdminGameListInput;
pub use game_distribution_admin_game_list_result_type::GameDistributionAdminGameListResult;
pub use game_distribution_admin_game_snapshot_type::GameDistributionAdminGameSnapshot;
pub use game_distribution_admin_user_review_input_type::GameDistributionAdminUserReviewInput;
pub use game_distribution_admin_user_review_list_input_type::GameDistributionAdminUserReviewListInput;
pub use game_distribution_admin_user_review_result_type::GameDistributionAdminUserReviewResult;
pub use game_distribution_admin_user_review_snapshot_type::GameDistributionAdminUserReviewSnapshot;
pub use game_distribution_admin_version_snapshot_type::GameDistributionAdminVersionSnapshot;
pub use game_distribution_approve_input_type::GameDistributionApproveInput;
pub use game_distribution_cancel_version_input_type::GameDistributionCancelVersionInput;
@@ -1193,6 +1221,7 @@ pub use game_distribution_game_type::GameDistributionGame;
pub use game_distribution_get_game_input_type::GameDistributionGetGameInput;
pub use game_distribution_idempotency_receipt_table::*;
pub use game_distribution_idempotency_receipt_type::GameDistributionIdempotencyReceipt;
pub use game_distribution_my_review_input_type::GameDistributionMyReviewInput;
pub use game_distribution_owner_game_list_input_type::GameDistributionOwnerGameListInput;
pub use game_distribution_owner_game_list_procedure_result_type::GameDistributionOwnerGameListProcedureResult;
pub use game_distribution_owner_game_snapshot_type::GameDistributionOwnerGameSnapshot;
@@ -1203,10 +1232,22 @@ pub use game_distribution_public_game_list_input_type::GameDistributionPublicGam
pub use game_distribution_public_game_snapshot_type::GameDistributionPublicGameSnapshot;
pub use game_distribution_reject_input_type::GameDistributionRejectInput;
pub use game_distribution_restore_input_type::GameDistributionRestoreInput;
pub use game_distribution_review_game_list_input_type::GameDistributionReviewGameListInput;
pub use game_distribution_review_game_snapshot_type::GameDistributionReviewGameSnapshot;
pub use game_distribution_review_list_input_type::GameDistributionReviewListInput;
pub use game_distribution_review_moderation_input_type::GameDistributionReviewModerationInput;
pub use game_distribution_review_moderation_log_table::*;
pub use game_distribution_review_moderation_log_type::GameDistributionReviewModerationLog;
pub use game_distribution_review_moderation_operation_snapshot_type::GameDistributionReviewModerationOperationSnapshot;
pub use game_distribution_review_table::*;
pub use game_distribution_review_type::GameDistributionReview;
pub use game_distribution_submit_review_input_type::GameDistributionSubmitReviewInput;
pub use game_distribution_suspend_input_type::GameDistributionSuspendInput;
pub use game_distribution_unpublish_input_type::GameDistributionUnpublishInput;
pub use game_distribution_user_review_input_type::GameDistributionUserReviewInput;
pub use game_distribution_user_review_list_input_type::GameDistributionUserReviewListInput;
pub use game_distribution_user_review_result_type::GameDistributionUserReviewResult;
pub use game_distribution_user_review_snapshot_type::GameDistributionUserReviewSnapshot;
pub use game_distribution_version_lookup_input_type::GameDistributionVersionLookupInput;
pub use game_distribution_version_procedure_result_type::GameDistributionVersionProcedureResult;
pub use game_distribution_version_snapshot_type::GameDistributionVersionSnapshot;
@@ -1215,6 +1256,7 @@ pub use game_distribution_version_type::GameDistributionVersion;
pub use get_admin_account_by_id_and_return_procedure::get_admin_account_by_id_and_return;
pub use get_admin_account_by_username_and_return_procedure::get_admin_account_by_username_and_return;
pub use get_admin_dashboard_stats_and_return_procedure::get_admin_dashboard_stats_and_return;
pub use get_admin_game_distribution_user_review_and_return_procedure::get_admin_game_distribution_user_review_and_return;
pub use get_asset_object_by_id_and_return_procedure::get_asset_object_by_id_and_return;
pub use get_asset_object_by_location_and_return_procedure::get_asset_object_by_location_and_return;
pub use get_asset_read_access_by_location_and_return_procedure::get_asset_read_access_by_location_and_return;
@@ -1230,6 +1272,7 @@ pub use get_external_generation_job_summary_and_return_procedure::get_external_g
pub use get_external_generation_queue_stats_and_return_procedure::get_external_generation_queue_stats_and_return;
pub use get_feature_gate_config_procedure::get_feature_gate_config;
pub use get_game_distribution_game_and_return_procedure::get_game_distribution_game_and_return;
pub use get_game_distribution_my_review_and_return_procedure::get_game_distribution_my_review_and_return;
pub use get_game_distribution_version_and_return_procedure::get_game_distribution_version_and_return;
pub use get_llm_router_account_and_return_procedure::get_llm_router_account_and_return;
pub use get_owner_game_distribution_version_and_return_procedure::get_owner_game_distribution_version_and_return;
@@ -1251,6 +1294,7 @@ pub use import_database_migration_incremental_from_file_procedure::import_databa
pub use initialize_editor_generation_pricing_config_if_missing_and_return_procedure::initialize_editor_generation_pricing_config_if_missing_and_return;
pub use list_admin_accounts_and_return_procedure::list_admin_accounts_and_return;
pub use list_admin_game_distribution_games_and_return_procedure::list_admin_game_distribution_games_and_return;
pub use list_admin_game_distribution_user_reviews_and_return_procedure::list_admin_game_distribution_user_reviews_and_return;
pub use list_agc_tracking_events_procedure::list_agc_tracking_events;
pub use list_asset_history_and_return_procedure::list_asset_history_and_return;
pub use list_editor_agent_conversations_and_return_procedure::list_editor_agent_conversations_and_return;
@@ -1260,7 +1304,9 @@ pub use list_external_api_keys_and_return_procedure::list_external_api_keys_and_
pub use list_external_generation_job_summaries_and_return_procedure::list_external_generation_job_summaries_and_return;
pub use list_external_generation_jobs_and_return_procedure::list_external_generation_jobs_and_return;
pub use list_game_distribution_games_and_return_procedure::list_game_distribution_games_and_return;
pub use list_game_distribution_review_games_and_return_procedure::list_game_distribution_review_games_and_return;
pub use list_game_distribution_reviews_and_return_procedure::list_game_distribution_reviews_and_return;
pub use list_game_distribution_user_reviews_and_return_procedure::list_game_distribution_user_reviews_and_return;
pub use list_owner_game_distribution_games_and_return_procedure::list_owner_game_distribution_games_and_return;
pub use list_profile_recharge_refund_holds_for_reconciliation_procedure::list_profile_recharge_refund_holds_for_reconciliation;
pub use list_profile_recharge_refunds_for_reconciliation_procedure::list_profile_recharge_refunds_for_reconciliation;
@@ -1283,6 +1329,7 @@ pub use llm_router_quota_settlement_result_type::LlmRouterQuotaSettlementResult;
pub use mark_editor_showcase_asset_refunded_and_return_procedure::mark_editor_showcase_asset_refunded_and_return;
pub use mark_profile_recharge_order_expiration_checked_procedure::mark_profile_recharge_order_expiration_checked;
pub use mark_profile_recharge_order_paid_and_return_procedure::mark_profile_recharge_order_paid_and_return;
pub use moderate_game_distribution_user_review_and_return_procedure::moderate_game_distribution_user_review_and_return;
pub use normalize_editor_character_animation_metadata_and_return_procedure::normalize_editor_character_animation_metadata_and_return;
pub use persist_editor_generation_result_and_return_procedure::persist_editor_generation_result_and_return;
pub use persist_editor_pixel_art_result_and_return_procedure::persist_editor_pixel_art_result_and_return;
@@ -1525,6 +1572,7 @@ pub use save_editor_project_layout_ack_procedure::save_editor_project_layout_ack
pub use save_editor_project_layout_and_return_procedure::save_editor_project_layout_and_return;
pub use save_editor_project_layout_v_2_ack_procedure::save_editor_project_layout_v_2_ack;
pub use save_editor_project_layout_v_2_and_return_procedure::save_editor_project_layout_v_2_and_return;
pub use save_game_distribution_my_review_and_return_procedure::save_game_distribution_my_review_and_return;
pub use seed_analytics_date_dimensions_reducer::seed_analytics_date_dimensions;
pub use set_editor_showcase_asset_like_for_viewer_and_return_procedure::set_editor_showcase_asset_like_for_viewer_and_return;
pub use settle_llm_router_quota_and_return_procedure::settle_llm_router_quota_and_return;
@@ -1714,6 +1762,9 @@ pub struct DbUpdate {
feature_gate_config: __sdk::TableUpdate<FeatureGateConfig>,
game_distribution_game: __sdk::TableUpdate<GameDistributionGame>,
game_distribution_idempotency_receipt: __sdk::TableUpdate<GameDistributionIdempotencyReceipt>,
game_distribution_review: __sdk::TableUpdate<GameDistributionReview>,
game_distribution_review_moderation_log:
__sdk::TableUpdate<GameDistributionReviewModerationLog>,
game_distribution_version: __sdk::TableUpdate<GameDistributionVersion>,
llm_router_account: __sdk::TableUpdate<LlmRouterAccount>,
llm_router_billing_checkpoint: __sdk::TableUpdate<LlmRouterBillingCheckpoint>,
@@ -1929,6 +1980,16 @@ impl TryFrom<__ws::v2::TransactionUpdate> for DbUpdate {
)?,
)
}
"game_distribution_review" => db_update.game_distribution_review.append(
game_distribution_review_table::parse_table_update(table_update)?,
),
"game_distribution_review_moderation_log" => {
db_update.game_distribution_review_moderation_log.append(
game_distribution_review_moderation_log_table::parse_table_update(
table_update,
)?,
)
}
"game_distribution_version" => db_update.game_distribution_version.append(
game_distribution_version_table::parse_table_update(table_update)?,
),
@@ -2322,6 +2383,18 @@ impl __sdk::DbUpdate for DbUpdate {
&self.game_distribution_idempotency_receipt,
)
.with_updates_by_pk(|row| &row.receipt_id);
diff.game_distribution_review = cache
.apply_diff_to_table::<GameDistributionReview>(
"game_distribution_review",
&self.game_distribution_review,
)
.with_updates_by_pk(|row| &row.review_id);
diff.game_distribution_review_moderation_log = cache
.apply_diff_to_table::<GameDistributionReviewModerationLog>(
"game_distribution_review_moderation_log",
&self.game_distribution_review_moderation_log,
)
.with_updates_by_pk(|row| &row.operation_id);
diff.game_distribution_version = cache
.apply_diff_to_table::<GameDistributionVersion>(
"game_distribution_version",
@@ -2683,6 +2756,12 @@ impl __sdk::DbUpdate for DbUpdate {
"game_distribution_idempotency_receipt" => db_update
.game_distribution_idempotency_receipt
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
"game_distribution_review" => db_update
.game_distribution_review
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
"game_distribution_review_moderation_log" => db_update
.game_distribution_review_moderation_log
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
"game_distribution_version" => db_update
.game_distribution_version
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
@@ -2951,6 +3030,12 @@ impl __sdk::DbUpdate for DbUpdate {
"game_distribution_idempotency_receipt" => db_update
.game_distribution_idempotency_receipt
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
"game_distribution_review" => db_update
.game_distribution_review
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
"game_distribution_review_moderation_log" => db_update
.game_distribution_review_moderation_log
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
"game_distribution_version" => db_update
.game_distribution_version
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
@@ -3134,6 +3219,9 @@ pub struct AppliedDiff<'r> {
game_distribution_game: __sdk::TableAppliedDiff<'r, GameDistributionGame>,
game_distribution_idempotency_receipt:
__sdk::TableAppliedDiff<'r, GameDistributionIdempotencyReceipt>,
game_distribution_review: __sdk::TableAppliedDiff<'r, GameDistributionReview>,
game_distribution_review_moderation_log:
__sdk::TableAppliedDiff<'r, GameDistributionReviewModerationLog>,
game_distribution_version: __sdk::TableAppliedDiff<'r, GameDistributionVersion>,
llm_router_account: __sdk::TableAppliedDiff<'r, LlmRouterAccount>,
llm_router_billing_checkpoint: __sdk::TableAppliedDiff<'r, LlmRouterBillingCheckpoint>,
@@ -3409,6 +3497,16 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> {
&self.game_distribution_idempotency_receipt,
event,
);
callbacks.invoke_table_row_callbacks::<GameDistributionReview>(
"game_distribution_review",
&self.game_distribution_review,
event,
);
callbacks.invoke_table_row_callbacks::<GameDistributionReviewModerationLog>(
"game_distribution_review_moderation_log",
&self.game_distribution_review_moderation_log,
event,
);
callbacks.invoke_table_row_callbacks::<GameDistributionVersion>(
"game_distribution_version",
&self.game_distribution_version,
@@ -4314,6 +4412,8 @@ impl __sdk::SpacetimeModule for RemoteModule {
feature_gate_config_table::register_table(client_cache);
game_distribution_game_table::register_table(client_cache);
game_distribution_idempotency_receipt_table::register_table(client_cache);
game_distribution_review_table::register_table(client_cache);
game_distribution_review_moderation_log_table::register_table(client_cache);
game_distribution_version_table::register_table(client_cache);
llm_router_account_table::register_table(client_cache);
llm_router_billing_checkpoint_table::register_table(client_cache);
@@ -4401,6 +4501,8 @@ impl __sdk::SpacetimeModule for RemoteModule {
"feature_gate_config",
"game_distribution_game",
"game_distribution_idempotency_receipt",
"game_distribution_review",
"game_distribution_review_moderation_log",
"game_distribution_version",
"llm_router_account",
"llm_router_billing_checkpoint",
@@ -0,0 +1,15 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionAdminUserReviewInput {
pub review_id: String,
}
impl __sdk::InModule for GameDistributionAdminUserReviewInput {
type Module = super::RemoteModule;
}
@@ -0,0 +1,20 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionAdminUserReviewListInput {
pub game_id: Option<String>,
pub user_id: Option<String>,
pub keyword: Option<String>,
pub status: String,
pub page: u32,
pub page_size: u32,
}
impl __sdk::InModule for GameDistributionAdminUserReviewListInput {
type Module = super::RemoteModule;
}
@@ -0,0 +1,30 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::game_distribution_admin_user_review_snapshot_type::GameDistributionAdminUserReviewSnapshot;
use super::game_distribution_review_game_snapshot_type::GameDistributionReviewGameSnapshot;
use super::game_distribution_review_moderation_operation_snapshot_type::GameDistributionReviewModerationOperationSnapshot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionAdminUserReviewResult {
pub ok: bool,
pub reviews: Vec<GameDistributionAdminUserReviewSnapshot>,
pub games: Vec<GameDistributionReviewGameSnapshot>,
pub review: Option<GameDistributionAdminUserReviewSnapshot>,
pub operations: Vec<GameDistributionReviewModerationOperationSnapshot>,
pub operation: Option<GameDistributionReviewModerationOperationSnapshot>,
pub page: u32,
pub page_size: u32,
pub total: u64,
pub total_pages: u64,
pub replayed: bool,
pub error_message: Option<String>,
}
impl __sdk::InModule for GameDistributionAdminUserReviewResult {
type Module = super::RemoteModule;
}
@@ -0,0 +1,19 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::game_distribution_user_review_snapshot_type::GameDistributionUserReviewSnapshot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionAdminUserReviewSnapshot {
pub review: GameDistributionUserReviewSnapshot,
pub game_title: String,
pub game_status: String,
}
impl __sdk::InModule for GameDistributionAdminUserReviewSnapshot {
type Module = super::RemoteModule;
}
@@ -0,0 +1,16 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionMyReviewInput {
pub game_id: String,
pub user_id: String,
}
impl __sdk::InModule for GameDistributionMyReviewInput {
type Module = super::RemoteModule;
}
@@ -12,6 +12,8 @@ use super::game_distribution_version_snapshot_type::GameDistributionVersionSnaps
pub struct GameDistributionPublicGameSnapshot {
pub game: GameDistributionGameSnapshot,
pub current_version: Option<GameDistributionVersionSnapshot>,
pub average_score: Option<f64>,
pub rating_count: u64,
}
impl __sdk::InModule for GameDistributionPublicGameSnapshot {
@@ -0,0 +1,17 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionReviewGameListInput {
pub query: Option<String>,
pub page: u32,
pub page_size: u32,
}
impl __sdk::InModule for GameDistributionReviewGameListInput {
type Module = super::RemoteModule;
}
@@ -0,0 +1,17 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionReviewGameSnapshot {
pub game_id: String,
pub title: String,
pub status: String,
}
impl __sdk::InModule for GameDistributionReviewGameSnapshot {
type Module = super::RemoteModule;
}
@@ -0,0 +1,20 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionReviewModerationInput {
pub review_id: String,
pub admin_user_id: String,
pub action: String,
pub idempotency_key: String,
pub expected_created_at_micros: i64,
pub reason: Option<String>,
}
impl __sdk::InModule for GameDistributionReviewModerationInput {
type Module = super::RemoteModule;
}
@@ -0,0 +1,245 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use super::game_distribution_review_moderation_log_type::GameDistributionReviewModerationLog;
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
/// Table handle for the table `game_distribution_review_moderation_log`.
///
/// Obtain a handle from the [`GameDistributionReviewModerationLogTableAccess::game_distribution_review_moderation_log`] method on [`super::RemoteTables`],
/// like `ctx.db.game_distribution_review_moderation_log()`.
///
/// Users are encouraged not to explicitly reference this type,
/// but to directly chain method calls,
/// like `ctx.db.game_distribution_review_moderation_log().on_insert(...)`.
pub struct GameDistributionReviewModerationLogTableHandle<'ctx> {
imp: __sdk::TableHandle<GameDistributionReviewModerationLog>,
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
}
/// Lifetime-aware accessor marker for the table `game_distribution_review_moderation_log`.
pub struct GameDistributionReviewModerationLogTableAccessor;
impl __sdk::TableAccessor<super::RemoteTables>
for GameDistributionReviewModerationLogTableAccessor
{
type Row = GameDistributionReviewModerationLog;
type Handle<'db> = GameDistributionReviewModerationLogTableHandle<'db>;
fn get<'db>(db: &'db super::RemoteTables) -> Self::Handle<'db> {
db.game_distribution_review_moderation_log()
}
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the table `game_distribution_review_moderation_log`.
///
/// Implemented for [`super::RemoteTables`].
pub trait GameDistributionReviewModerationLogTableAccess {
#[allow(non_snake_case)]
/// Obtain a [`GameDistributionReviewModerationLogTableHandle`], which mediates access to the table `game_distribution_review_moderation_log`.
fn game_distribution_review_moderation_log(
&self,
) -> GameDistributionReviewModerationLogTableHandle<'_>;
}
impl GameDistributionReviewModerationLogTableAccess for super::RemoteTables {
fn game_distribution_review_moderation_log(
&self,
) -> GameDistributionReviewModerationLogTableHandle<'_> {
GameDistributionReviewModerationLogTableHandle {
imp: self.imp.get_table::<GameDistributionReviewModerationLog>(
"game_distribution_review_moderation_log",
),
ctx: std::marker::PhantomData,
}
}
}
pub struct GameDistributionReviewModerationLogInsertCallbackId(__sdk::CallbackId);
pub struct GameDistributionReviewModerationLogDeleteCallbackId(__sdk::CallbackId);
impl<'ctx> __sdk::TableLike for GameDistributionReviewModerationLogTableHandle<'ctx> {
type Row = GameDistributionReviewModerationLog;
type EventContext = super::EventContext;
fn count(&self) -> u64 {
self.imp.count()
}
fn iter(&self) -> impl Iterator<Item = GameDistributionReviewModerationLog> + '_ {
self.imp.iter()
}
}
impl<'ctx> __sdk::Table for GameDistributionReviewModerationLogTableHandle<'ctx> {
type Row = GameDistributionReviewModerationLog;
type EventContext = super::EventContext;
fn count(&self) -> u64 {
self.imp.count()
}
fn iter(&self) -> impl Iterator<Item = GameDistributionReviewModerationLog> + '_ {
self.imp.iter()
}
type InsertCallbackId = GameDistributionReviewModerationLogInsertCallbackId;
fn on_insert(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> GameDistributionReviewModerationLogInsertCallbackId {
GameDistributionReviewModerationLogInsertCallbackId(self.imp.on_insert(Box::new(callback)))
}
fn remove_on_insert(&self, callback: GameDistributionReviewModerationLogInsertCallbackId) {
self.imp.remove_on_insert(callback.0)
}
type DeleteCallbackId = GameDistributionReviewModerationLogDeleteCallbackId;
fn on_delete(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> GameDistributionReviewModerationLogDeleteCallbackId {
GameDistributionReviewModerationLogDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
}
fn remove_on_delete(&self, callback: GameDistributionReviewModerationLogDeleteCallbackId) {
self.imp.remove_on_delete(callback.0)
}
}
impl<'ctx> __sdk::WithInsert for GameDistributionReviewModerationLogTableHandle<'ctx> {
type InsertCallbackId = GameDistributionReviewModerationLogInsertCallbackId;
fn on_insert(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> GameDistributionReviewModerationLogInsertCallbackId {
GameDistributionReviewModerationLogInsertCallbackId(self.imp.on_insert(Box::new(callback)))
}
fn remove_on_insert(&self, callback: GameDistributionReviewModerationLogInsertCallbackId) {
self.imp.remove_on_insert(callback.0)
}
}
impl<'ctx> __sdk::WithDelete for GameDistributionReviewModerationLogTableHandle<'ctx> {
type DeleteCallbackId = GameDistributionReviewModerationLogDeleteCallbackId;
fn on_delete(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> GameDistributionReviewModerationLogDeleteCallbackId {
GameDistributionReviewModerationLogDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
}
fn remove_on_delete(&self, callback: GameDistributionReviewModerationLogDeleteCallbackId) {
self.imp.remove_on_delete(callback.0)
}
}
pub struct GameDistributionReviewModerationLogUpdateCallbackId(__sdk::CallbackId);
impl<'ctx> __sdk::TableWithPrimaryKey for GameDistributionReviewModerationLogTableHandle<'ctx> {
type UpdateCallbackId = GameDistributionReviewModerationLogUpdateCallbackId;
fn on_update(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
) -> GameDistributionReviewModerationLogUpdateCallbackId {
GameDistributionReviewModerationLogUpdateCallbackId(self.imp.on_update(Box::new(callback)))
}
fn remove_on_update(&self, callback: GameDistributionReviewModerationLogUpdateCallbackId) {
self.imp.remove_on_update(callback.0)
}
}
impl<'ctx> __sdk::WithUpdate for GameDistributionReviewModerationLogTableHandle<'ctx> {
type UpdateCallbackId = GameDistributionReviewModerationLogUpdateCallbackId;
fn on_update(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
) -> GameDistributionReviewModerationLogUpdateCallbackId {
GameDistributionReviewModerationLogUpdateCallbackId(self.imp.on_update(Box::new(callback)))
}
fn remove_on_update(&self, callback: GameDistributionReviewModerationLogUpdateCallbackId) {
self.imp.remove_on_update(callback.0)
}
}
/// Access to the `operation_id` unique index on the table `game_distribution_review_moderation_log`,
/// which allows point queries on the field of the same name
/// via the [`GameDistributionReviewModerationLogOperationIdUnique::find`] method.
///
/// Users are encouraged not to explicitly reference this type,
/// but to directly chain method calls,
/// like `ctx.db.game_distribution_review_moderation_log().operation_id().find(...)`.
pub struct GameDistributionReviewModerationLogOperationIdUnique<'ctx> {
imp: __sdk::UniqueConstraintHandle<GameDistributionReviewModerationLog, String>,
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
}
impl<'ctx> GameDistributionReviewModerationLogTableHandle<'ctx> {
/// Get a handle on the `operation_id` unique index on the table `game_distribution_review_moderation_log`.
pub fn operation_id(&self) -> GameDistributionReviewModerationLogOperationIdUnique<'ctx> {
GameDistributionReviewModerationLogOperationIdUnique {
imp: self.imp.get_unique_constraint::<String>("operation_id"),
phantom: std::marker::PhantomData,
}
}
}
impl<'ctx> GameDistributionReviewModerationLogOperationIdUnique<'ctx> {
/// Find the subscribed row whose `operation_id` column value is equal to `col_val`,
/// if such a row is present in the client cache.
pub fn find(&self, col_val: &String) -> Option<GameDistributionReviewModerationLog> {
self.imp.find(col_val)
}
}
#[doc(hidden)]
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
let _table = client_cache.get_or_make_table::<GameDistributionReviewModerationLog>(
"game_distribution_review_moderation_log",
);
_table.add_unique_constraint::<String>("operation_id", |row| &row.operation_id);
}
#[doc(hidden)]
pub(super) fn parse_table_update(
raw_updates: __ws::v2::TableUpdate,
) -> __sdk::Result<__sdk::TableUpdate<GameDistributionReviewModerationLog>> {
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
__sdk::InternalError::failed_parse(
"TableUpdate<GameDistributionReviewModerationLog>",
"TableUpdate",
)
.with_cause(e)
.into()
})
}
#[allow(non_camel_case_types)]
/// Extension trait for query builder access to the table `GameDistributionReviewModerationLog`.
///
/// Implemented for [`__sdk::QueryTableAccessor`].
pub trait game_distribution_review_moderation_logQueryTableAccess {
#[allow(non_snake_case)]
/// Get a query builder for the table `GameDistributionReviewModerationLog`.
fn game_distribution_review_moderation_log(
&self,
) -> __sdk::__query_builder::Table<GameDistributionReviewModerationLog>;
}
impl game_distribution_review_moderation_logQueryTableAccess for __sdk::QueryTableAccessor {
fn game_distribution_review_moderation_log(
&self,
) -> __sdk::__query_builder::Table<GameDistributionReviewModerationLog> {
__sdk::__query_builder::Table::new("game_distribution_review_moderation_log")
}
}
@@ -0,0 +1,77 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionReviewModerationLog {
pub operation_id: String,
pub review_id: String,
pub game_id: String,
pub user_id: String,
pub review_created_at: __sdk::Timestamp,
pub action: String,
pub admin_user_id: String,
pub reason: Option<String>,
pub created_at: __sdk::Timestamp,
}
impl __sdk::InModule for GameDistributionReviewModerationLog {
type Module = super::RemoteModule;
}
/// Column accessor struct for the table `GameDistributionReviewModerationLog`.
///
/// Provides typed access to columns for query building.
pub struct GameDistributionReviewModerationLogCols {
pub operation_id: __sdk::__query_builder::Col<GameDistributionReviewModerationLog, String>,
pub review_id: __sdk::__query_builder::Col<GameDistributionReviewModerationLog, String>,
pub game_id: __sdk::__query_builder::Col<GameDistributionReviewModerationLog, String>,
pub user_id: __sdk::__query_builder::Col<GameDistributionReviewModerationLog, String>,
pub review_created_at:
__sdk::__query_builder::Col<GameDistributionReviewModerationLog, __sdk::Timestamp>,
pub action: __sdk::__query_builder::Col<GameDistributionReviewModerationLog, String>,
pub admin_user_id: __sdk::__query_builder::Col<GameDistributionReviewModerationLog, String>,
pub reason: __sdk::__query_builder::Col<GameDistributionReviewModerationLog, Option<String>>,
pub created_at:
__sdk::__query_builder::Col<GameDistributionReviewModerationLog, __sdk::Timestamp>,
}
impl __sdk::__query_builder::HasCols for GameDistributionReviewModerationLog {
type Cols = GameDistributionReviewModerationLogCols;
fn cols(table_name: &'static str) -> Self::Cols {
GameDistributionReviewModerationLogCols {
operation_id: __sdk::__query_builder::Col::new(table_name, "operation_id"),
review_id: __sdk::__query_builder::Col::new(table_name, "review_id"),
game_id: __sdk::__query_builder::Col::new(table_name, "game_id"),
user_id: __sdk::__query_builder::Col::new(table_name, "user_id"),
review_created_at: __sdk::__query_builder::Col::new(table_name, "review_created_at"),
action: __sdk::__query_builder::Col::new(table_name, "action"),
admin_user_id: __sdk::__query_builder::Col::new(table_name, "admin_user_id"),
reason: __sdk::__query_builder::Col::new(table_name, "reason"),
created_at: __sdk::__query_builder::Col::new(table_name, "created_at"),
}
}
}
/// Indexed column accessor struct for the table `GameDistributionReviewModerationLog`.
///
/// Provides typed access to indexed columns for query building.
pub struct GameDistributionReviewModerationLogIxCols {
pub operation_id: __sdk::__query_builder::IxCol<GameDistributionReviewModerationLog, String>,
pub review_id: __sdk::__query_builder::IxCol<GameDistributionReviewModerationLog, String>,
}
impl __sdk::__query_builder::HasIxCols for GameDistributionReviewModerationLog {
type IxCols = GameDistributionReviewModerationLogIxCols;
fn ix_cols(table_name: &'static str) -> Self::IxCols {
GameDistributionReviewModerationLogIxCols {
operation_id: __sdk::__query_builder::IxCol::new(table_name, "operation_id"),
review_id: __sdk::__query_builder::IxCol::new(table_name, "review_id"),
}
}
}
impl __sdk::__query_builder::CanBeLookupTable for GameDistributionReviewModerationLog {}
@@ -0,0 +1,23 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionReviewModerationOperationSnapshot {
pub operation_id: String,
pub review_id: String,
pub game_id: String,
pub user_id: String,
pub review_created_at_micros: i64,
pub action: String,
pub admin_user_id: String,
pub reason: Option<String>,
pub created_at_micros: i64,
}
impl __sdk::InModule for GameDistributionReviewModerationOperationSnapshot {
type Module = super::RemoteModule;
}
@@ -0,0 +1,231 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use super::game_distribution_review_type::GameDistributionReview;
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
/// Table handle for the table `game_distribution_review`.
///
/// Obtain a handle from the [`GameDistributionReviewTableAccess::game_distribution_review`] method on [`super::RemoteTables`],
/// like `ctx.db.game_distribution_review()`.
///
/// Users are encouraged not to explicitly reference this type,
/// but to directly chain method calls,
/// like `ctx.db.game_distribution_review().on_insert(...)`.
pub struct GameDistributionReviewTableHandle<'ctx> {
imp: __sdk::TableHandle<GameDistributionReview>,
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
}
/// Lifetime-aware accessor marker for the table `game_distribution_review`.
pub struct GameDistributionReviewTableAccessor;
impl __sdk::TableAccessor<super::RemoteTables> for GameDistributionReviewTableAccessor {
type Row = GameDistributionReview;
type Handle<'db> = GameDistributionReviewTableHandle<'db>;
fn get<'db>(db: &'db super::RemoteTables) -> Self::Handle<'db> {
db.game_distribution_review()
}
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the table `game_distribution_review`.
///
/// Implemented for [`super::RemoteTables`].
pub trait GameDistributionReviewTableAccess {
#[allow(non_snake_case)]
/// Obtain a [`GameDistributionReviewTableHandle`], which mediates access to the table `game_distribution_review`.
fn game_distribution_review(&self) -> GameDistributionReviewTableHandle<'_>;
}
impl GameDistributionReviewTableAccess for super::RemoteTables {
fn game_distribution_review(&self) -> GameDistributionReviewTableHandle<'_> {
GameDistributionReviewTableHandle {
imp: self
.imp
.get_table::<GameDistributionReview>("game_distribution_review"),
ctx: std::marker::PhantomData,
}
}
}
pub struct GameDistributionReviewInsertCallbackId(__sdk::CallbackId);
pub struct GameDistributionReviewDeleteCallbackId(__sdk::CallbackId);
impl<'ctx> __sdk::TableLike for GameDistributionReviewTableHandle<'ctx> {
type Row = GameDistributionReview;
type EventContext = super::EventContext;
fn count(&self) -> u64 {
self.imp.count()
}
fn iter(&self) -> impl Iterator<Item = GameDistributionReview> + '_ {
self.imp.iter()
}
}
impl<'ctx> __sdk::Table for GameDistributionReviewTableHandle<'ctx> {
type Row = GameDistributionReview;
type EventContext = super::EventContext;
fn count(&self) -> u64 {
self.imp.count()
}
fn iter(&self) -> impl Iterator<Item = GameDistributionReview> + '_ {
self.imp.iter()
}
type InsertCallbackId = GameDistributionReviewInsertCallbackId;
fn on_insert(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> GameDistributionReviewInsertCallbackId {
GameDistributionReviewInsertCallbackId(self.imp.on_insert(Box::new(callback)))
}
fn remove_on_insert(&self, callback: GameDistributionReviewInsertCallbackId) {
self.imp.remove_on_insert(callback.0)
}
type DeleteCallbackId = GameDistributionReviewDeleteCallbackId;
fn on_delete(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> GameDistributionReviewDeleteCallbackId {
GameDistributionReviewDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
}
fn remove_on_delete(&self, callback: GameDistributionReviewDeleteCallbackId) {
self.imp.remove_on_delete(callback.0)
}
}
impl<'ctx> __sdk::WithInsert for GameDistributionReviewTableHandle<'ctx> {
type InsertCallbackId = GameDistributionReviewInsertCallbackId;
fn on_insert(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> GameDistributionReviewInsertCallbackId {
GameDistributionReviewInsertCallbackId(self.imp.on_insert(Box::new(callback)))
}
fn remove_on_insert(&self, callback: GameDistributionReviewInsertCallbackId) {
self.imp.remove_on_insert(callback.0)
}
}
impl<'ctx> __sdk::WithDelete for GameDistributionReviewTableHandle<'ctx> {
type DeleteCallbackId = GameDistributionReviewDeleteCallbackId;
fn on_delete(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
) -> GameDistributionReviewDeleteCallbackId {
GameDistributionReviewDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
}
fn remove_on_delete(&self, callback: GameDistributionReviewDeleteCallbackId) {
self.imp.remove_on_delete(callback.0)
}
}
pub struct GameDistributionReviewUpdateCallbackId(__sdk::CallbackId);
impl<'ctx> __sdk::TableWithPrimaryKey for GameDistributionReviewTableHandle<'ctx> {
type UpdateCallbackId = GameDistributionReviewUpdateCallbackId;
fn on_update(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
) -> GameDistributionReviewUpdateCallbackId {
GameDistributionReviewUpdateCallbackId(self.imp.on_update(Box::new(callback)))
}
fn remove_on_update(&self, callback: GameDistributionReviewUpdateCallbackId) {
self.imp.remove_on_update(callback.0)
}
}
impl<'ctx> __sdk::WithUpdate for GameDistributionReviewTableHandle<'ctx> {
type UpdateCallbackId = GameDistributionReviewUpdateCallbackId;
fn on_update(
&self,
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
) -> GameDistributionReviewUpdateCallbackId {
GameDistributionReviewUpdateCallbackId(self.imp.on_update(Box::new(callback)))
}
fn remove_on_update(&self, callback: GameDistributionReviewUpdateCallbackId) {
self.imp.remove_on_update(callback.0)
}
}
/// Access to the `review_id` unique index on the table `game_distribution_review`,
/// which allows point queries on the field of the same name
/// via the [`GameDistributionReviewReviewIdUnique::find`] method.
///
/// Users are encouraged not to explicitly reference this type,
/// but to directly chain method calls,
/// like `ctx.db.game_distribution_review().review_id().find(...)`.
pub struct GameDistributionReviewReviewIdUnique<'ctx> {
imp: __sdk::UniqueConstraintHandle<GameDistributionReview, String>,
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
}
impl<'ctx> GameDistributionReviewTableHandle<'ctx> {
/// Get a handle on the `review_id` unique index on the table `game_distribution_review`.
pub fn review_id(&self) -> GameDistributionReviewReviewIdUnique<'ctx> {
GameDistributionReviewReviewIdUnique {
imp: self.imp.get_unique_constraint::<String>("review_id"),
phantom: std::marker::PhantomData,
}
}
}
impl<'ctx> GameDistributionReviewReviewIdUnique<'ctx> {
/// Find the subscribed row whose `review_id` column value is equal to `col_val`,
/// if such a row is present in the client cache.
pub fn find(&self, col_val: &String) -> Option<GameDistributionReview> {
self.imp.find(col_val)
}
}
#[doc(hidden)]
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
let _table =
client_cache.get_or_make_table::<GameDistributionReview>("game_distribution_review");
_table.add_unique_constraint::<String>("review_id", |row| &row.review_id);
}
#[doc(hidden)]
pub(super) fn parse_table_update(
raw_updates: __ws::v2::TableUpdate,
) -> __sdk::Result<__sdk::TableUpdate<GameDistributionReview>> {
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
__sdk::InternalError::failed_parse("TableUpdate<GameDistributionReview>", "TableUpdate")
.with_cause(e)
.into()
})
}
#[allow(non_camel_case_types)]
/// Extension trait for query builder access to the table `GameDistributionReview`.
///
/// Implemented for [`__sdk::QueryTableAccessor`].
pub trait game_distribution_reviewQueryTableAccess {
#[allow(non_snake_case)]
/// Get a query builder for the table `GameDistributionReview`.
fn game_distribution_review(&self) -> __sdk::__query_builder::Table<GameDistributionReview>;
}
impl game_distribution_reviewQueryTableAccess for __sdk::QueryTableAccessor {
fn game_distribution_review(&self) -> __sdk::__query_builder::Table<GameDistributionReview> {
__sdk::__query_builder::Table::new("game_distribution_review")
}
}

Some files were not shown because too many files have changed in this diff Show More