Merge branch 'master' into codex/frontend-error-dialogs
# Conflicts: # .hermes/shared-memory/decision-log.md # server-rs/crates/api-server/src/generated_asset_sheets.rs
This commit is contained in:
@@ -47,8 +47,8 @@ pub use mapper::{
|
||||
Match3DRunClickRecordInput, Match3DRunRecord, Match3DRunRestartRecordInput,
|
||||
Match3DRunStartRecordInput, Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput,
|
||||
Match3DTraySlotRecord, Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput,
|
||||
NpcBattleInteractionRecord, NpcInteractionRecord, NpcStateRecord,
|
||||
PuzzleAgentMessageFinalizeRecordInput, PuzzleAgentMessageRecord,
|
||||
NpcBattleInteractionRecord, NpcInteractionRecord, NpcStateRecord, PublicWorkDetailEntryRecord,
|
||||
PublicWorkGalleryEntryRecord, PuzzleAgentMessageFinalizeRecordInput, PuzzleAgentMessageRecord,
|
||||
PuzzleAgentMessageSubmitRecordInput, PuzzleAgentSessionCreateRecordInput,
|
||||
PuzzleAgentSessionRecord, PuzzleAgentSuggestedActionRecord, PuzzleAnchorItemRecord,
|
||||
PuzzleAnchorPackRecord, PuzzleAudioAssetRecord, PuzzleBoardRecord, PuzzleCellPositionRecord,
|
||||
@@ -107,6 +107,7 @@ pub mod inventory;
|
||||
pub mod jump_hop;
|
||||
pub mod match3d;
|
||||
pub mod npc;
|
||||
pub mod public_work;
|
||||
pub mod puzzle;
|
||||
pub mod runtime;
|
||||
pub mod square_hole;
|
||||
@@ -570,6 +571,8 @@ impl SpacetimeClient {
|
||||
) -> Result<Vec<SubscriptionHandle>, SpacetimeClientError> {
|
||||
let mut subscriptions = Vec::new();
|
||||
for query in [
|
||||
"SELECT * FROM public_work_gallery_entry",
|
||||
"SELECT * FROM public_work_detail_entry",
|
||||
"SELECT * FROM bark_battle_gallery_view",
|
||||
"SELECT * FROM puzzle_gallery_card_view",
|
||||
"SELECT * FROM jump_hop_gallery_card_view",
|
||||
|
||||
@@ -12,6 +12,7 @@ mod inventory;
|
||||
mod jump_hop;
|
||||
mod match3d;
|
||||
mod npc;
|
||||
mod public_work;
|
||||
mod puzzle;
|
||||
mod runtime;
|
||||
mod runtime_profile;
|
||||
@@ -94,6 +95,7 @@ pub use self::npc::{
|
||||
CustomWorldWorkSummaryRecord, NpcBattleInteractionRecord, NpcInteractionRecord, NpcStateRecord,
|
||||
ResolveNpcBattleInteractionInput,
|
||||
};
|
||||
pub use self::public_work::{PublicWorkDetailEntryRecord, PublicWorkGalleryEntryRecord};
|
||||
pub use self::puzzle::{
|
||||
PuzzleAgentMessageFinalizeRecordInput, PuzzleAgentMessageRecord,
|
||||
PuzzleAgentMessageSubmitRecordInput, PuzzleAgentSessionCreateRecordInput,
|
||||
@@ -181,6 +183,9 @@ pub(crate) use self::npc::{
|
||||
build_battle_state_record, map_battle_state_snapshot, map_inventory_item_source_kind,
|
||||
map_npc_battle_interaction_procedure_result, validate_npc_battle_interaction_input,
|
||||
};
|
||||
pub(crate) use self::public_work::{
|
||||
map_public_work_gallery_entry, map_public_work_gallery_entry_to_detail_entry,
|
||||
};
|
||||
pub(crate) use self::puzzle::{
|
||||
map_puzzle_agent_session_procedure_result, map_puzzle_gallery_card_view_row,
|
||||
map_puzzle_run_procedure_result, map_puzzle_work_procedure_result,
|
||||
|
||||
115
server-rs/crates/spacetime-client/src/mapper/public_work.rs
Normal file
115
server-rs/crates/spacetime-client/src/mapper/public_work.rs
Normal file
@@ -0,0 +1,115 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PublicWorkGalleryEntryRecord {
|
||||
pub source_type: String,
|
||||
pub work_id: String,
|
||||
pub profile_id: String,
|
||||
pub source_session_id: Option<String>,
|
||||
pub public_work_code: String,
|
||||
pub owner_user_id: String,
|
||||
pub author_display_name: String,
|
||||
pub world_name: String,
|
||||
pub subtitle: String,
|
||||
pub summary_text: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub cover_asset_id: Option<String>,
|
||||
pub theme_tags: Vec<String>,
|
||||
pub play_count: u32,
|
||||
pub remix_count: u32,
|
||||
pub like_count: u32,
|
||||
pub recent_play_count_7d: u32,
|
||||
pub published_at: Option<String>,
|
||||
pub updated_at: String,
|
||||
pub sort_time_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PublicWorkDetailEntryRecord {
|
||||
pub entry: PublicWorkGalleryEntryRecord,
|
||||
pub detail_payload_json: String,
|
||||
}
|
||||
|
||||
pub(crate) fn map_public_work_gallery_entry(
|
||||
snapshot: PublicWorkGalleryEntry,
|
||||
recent_play_count_7d: u32,
|
||||
) -> PublicWorkGalleryEntryRecord {
|
||||
PublicWorkGalleryEntryRecord {
|
||||
source_type: snapshot.source_type,
|
||||
work_id: snapshot.work_id,
|
||||
profile_id: snapshot.profile_id,
|
||||
source_session_id: snapshot.source_session_id,
|
||||
public_work_code: snapshot.public_work_code,
|
||||
owner_user_id: snapshot.owner_user_id,
|
||||
author_display_name: snapshot.author_display_name,
|
||||
world_name: snapshot.world_name,
|
||||
subtitle: snapshot.subtitle,
|
||||
summary_text: snapshot.summary_text,
|
||||
cover_image_src: snapshot.cover_image_src,
|
||||
cover_asset_id: snapshot.cover_asset_id,
|
||||
theme_tags: snapshot.theme_tags,
|
||||
play_count: snapshot.play_count,
|
||||
remix_count: snapshot.remix_count,
|
||||
like_count: snapshot.like_count,
|
||||
recent_play_count_7d,
|
||||
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
|
||||
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
|
||||
sort_time_micros: snapshot.sort_time_micros,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_public_work_gallery_entry_to_detail_entry(
|
||||
snapshot: PublicWorkDetailEntry,
|
||||
recent_play_count_7d: u32,
|
||||
) -> PublicWorkDetailEntryRecord {
|
||||
let PublicWorkDetailEntry {
|
||||
source_type,
|
||||
work_id,
|
||||
profile_id,
|
||||
source_session_id,
|
||||
public_work_code,
|
||||
owner_user_id,
|
||||
author_display_name,
|
||||
world_name,
|
||||
subtitle,
|
||||
summary_text,
|
||||
cover_image_src,
|
||||
cover_asset_id,
|
||||
theme_tags,
|
||||
play_count,
|
||||
remix_count,
|
||||
like_count,
|
||||
published_at_micros,
|
||||
updated_at_micros,
|
||||
sort_time_micros,
|
||||
detail_payload_json,
|
||||
} = snapshot;
|
||||
|
||||
PublicWorkDetailEntryRecord {
|
||||
entry: map_public_work_gallery_entry(
|
||||
PublicWorkGalleryEntry {
|
||||
source_type,
|
||||
work_id,
|
||||
profile_id,
|
||||
source_session_id,
|
||||
public_work_code,
|
||||
owner_user_id,
|
||||
author_display_name,
|
||||
world_name,
|
||||
subtitle,
|
||||
summary_text,
|
||||
cover_image_src,
|
||||
cover_asset_id,
|
||||
theme_tags,
|
||||
play_count,
|
||||
remix_count,
|
||||
like_count,
|
||||
published_at_micros,
|
||||
updated_at_micros,
|
||||
sort_time_micros,
|
||||
},
|
||||
recent_play_count_7d,
|
||||
),
|
||||
detail_payload_json,
|
||||
}
|
||||
}
|
||||
@@ -758,6 +758,7 @@ pub struct PuzzleRunNextLevelRecordInput {
|
||||
pub run_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub target_profile_id: Option<String>,
|
||||
pub prefer_similar_work: bool,
|
||||
pub advanced_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
@@ -560,6 +560,10 @@ pub mod profile_task_reward_claim_table;
|
||||
pub mod profile_task_reward_claim_type;
|
||||
pub mod profile_wallet_ledger_table;
|
||||
pub mod profile_wallet_ledger_type;
|
||||
pub mod public_work_detail_entry_table;
|
||||
pub mod public_work_detail_entry_type;
|
||||
pub mod public_work_gallery_entry_table;
|
||||
pub mod public_work_gallery_entry_type;
|
||||
pub mod public_work_like_table;
|
||||
pub mod public_work_like_type;
|
||||
pub mod public_work_play_daily_stat_table;
|
||||
@@ -1591,6 +1595,10 @@ pub use profile_task_reward_claim_table::*;
|
||||
pub use profile_task_reward_claim_type::ProfileTaskRewardClaim;
|
||||
pub use profile_wallet_ledger_table::*;
|
||||
pub use profile_wallet_ledger_type::ProfileWalletLedger;
|
||||
pub use public_work_detail_entry_table::*;
|
||||
pub use public_work_detail_entry_type::PublicWorkDetailEntry;
|
||||
pub use public_work_gallery_entry_table::*;
|
||||
pub use public_work_gallery_entry_type::PublicWorkGalleryEntry;
|
||||
pub use public_work_like_table::*;
|
||||
pub use public_work_like_type::PublicWorkLike;
|
||||
pub use public_work_play_daily_stat_table::*;
|
||||
@@ -2408,6 +2416,8 @@ pub struct DbUpdate {
|
||||
profile_task_progress: __sdk::TableUpdate<ProfileTaskProgress>,
|
||||
profile_task_reward_claim: __sdk::TableUpdate<ProfileTaskRewardClaim>,
|
||||
profile_wallet_ledger: __sdk::TableUpdate<ProfileWalletLedger>,
|
||||
public_work_detail_entry: __sdk::TableUpdate<PublicWorkDetailEntry>,
|
||||
public_work_gallery_entry: __sdk::TableUpdate<PublicWorkGalleryEntry>,
|
||||
public_work_like: __sdk::TableUpdate<PublicWorkLike>,
|
||||
public_work_play_daily_stat: __sdk::TableUpdate<PublicWorkPlayDailyStat>,
|
||||
puzzle_agent_message: __sdk::TableUpdate<PuzzleAgentMessageRow>,
|
||||
@@ -2670,6 +2680,12 @@ impl TryFrom<__ws::v2::TransactionUpdate> for DbUpdate {
|
||||
"profile_wallet_ledger" => db_update.profile_wallet_ledger.append(
|
||||
profile_wallet_ledger_table::parse_table_update(table_update)?,
|
||||
),
|
||||
"public_work_detail_entry" => db_update.public_work_detail_entry.append(
|
||||
public_work_detail_entry_table::parse_table_update(table_update)?,
|
||||
),
|
||||
"public_work_gallery_entry" => db_update.public_work_gallery_entry.append(
|
||||
public_work_gallery_entry_table::parse_table_update(table_update)?,
|
||||
),
|
||||
"public_work_like" => db_update
|
||||
.public_work_like
|
||||
.append(public_work_like_table::parse_table_update(table_update)?),
|
||||
@@ -3332,6 +3348,14 @@ impl __sdk::DbUpdate for DbUpdate {
|
||||
"match_3_d_gallery_view",
|
||||
&self.match_3_d_gallery_view,
|
||||
);
|
||||
diff.public_work_detail_entry = cache.apply_diff_to_table::<PublicWorkDetailEntry>(
|
||||
"public_work_detail_entry",
|
||||
&self.public_work_detail_entry,
|
||||
);
|
||||
diff.public_work_gallery_entry = cache.apply_diff_to_table::<PublicWorkGalleryEntry>(
|
||||
"public_work_gallery_entry",
|
||||
&self.public_work_gallery_entry,
|
||||
);
|
||||
diff.puzzle_gallery_card_view = cache.apply_diff_to_table::<PuzzleGalleryCardViewRow>(
|
||||
"puzzle_gallery_card_view",
|
||||
&self.puzzle_gallery_card_view,
|
||||
@@ -3568,6 +3592,12 @@ impl __sdk::DbUpdate for DbUpdate {
|
||||
"profile_wallet_ledger" => db_update
|
||||
.profile_wallet_ledger
|
||||
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"public_work_detail_entry" => db_update
|
||||
.public_work_detail_entry
|
||||
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"public_work_gallery_entry" => db_update
|
||||
.public_work_gallery_entry
|
||||
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"public_work_like" => db_update
|
||||
.public_work_like
|
||||
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
@@ -3905,6 +3935,12 @@ impl __sdk::DbUpdate for DbUpdate {
|
||||
"profile_wallet_ledger" => db_update
|
||||
.profile_wallet_ledger
|
||||
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"public_work_detail_entry" => db_update
|
||||
.public_work_detail_entry
|
||||
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"public_work_gallery_entry" => db_update
|
||||
.public_work_gallery_entry
|
||||
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"public_work_like" => db_update
|
||||
.public_work_like
|
||||
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
@@ -4110,6 +4146,8 @@ pub struct AppliedDiff<'r> {
|
||||
profile_task_progress: __sdk::TableAppliedDiff<'r, ProfileTaskProgress>,
|
||||
profile_task_reward_claim: __sdk::TableAppliedDiff<'r, ProfileTaskRewardClaim>,
|
||||
profile_wallet_ledger: __sdk::TableAppliedDiff<'r, ProfileWalletLedger>,
|
||||
public_work_detail_entry: __sdk::TableAppliedDiff<'r, PublicWorkDetailEntry>,
|
||||
public_work_gallery_entry: __sdk::TableAppliedDiff<'r, PublicWorkGalleryEntry>,
|
||||
public_work_like: __sdk::TableAppliedDiff<'r, PublicWorkLike>,
|
||||
public_work_play_daily_stat: __sdk::TableAppliedDiff<'r, PublicWorkPlayDailyStat>,
|
||||
puzzle_agent_message: __sdk::TableAppliedDiff<'r, PuzzleAgentMessageRow>,
|
||||
@@ -4492,6 +4530,16 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> {
|
||||
&self.profile_wallet_ledger,
|
||||
event,
|
||||
);
|
||||
callbacks.invoke_table_row_callbacks::<PublicWorkDetailEntry>(
|
||||
"public_work_detail_entry",
|
||||
&self.public_work_detail_entry,
|
||||
event,
|
||||
);
|
||||
callbacks.invoke_table_row_callbacks::<PublicWorkGalleryEntry>(
|
||||
"public_work_gallery_entry",
|
||||
&self.public_work_gallery_entry,
|
||||
event,
|
||||
);
|
||||
callbacks.invoke_table_row_callbacks::<PublicWorkLike>(
|
||||
"public_work_like",
|
||||
&self.public_work_like,
|
||||
@@ -5412,6 +5460,8 @@ impl __sdk::SpacetimeModule for RemoteModule {
|
||||
profile_task_progress_table::register_table(client_cache);
|
||||
profile_task_reward_claim_table::register_table(client_cache);
|
||||
profile_wallet_ledger_table::register_table(client_cache);
|
||||
public_work_detail_entry_table::register_table(client_cache);
|
||||
public_work_gallery_entry_table::register_table(client_cache);
|
||||
public_work_like_table::register_table(client_cache);
|
||||
public_work_play_daily_stat_table::register_table(client_cache);
|
||||
puzzle_agent_message_table::register_table(client_cache);
|
||||
@@ -5522,6 +5572,8 @@ impl __sdk::SpacetimeModule for RemoteModule {
|
||||
"profile_task_progress",
|
||||
"profile_task_reward_claim",
|
||||
"profile_wallet_ledger",
|
||||
"public_work_detail_entry",
|
||||
"public_work_gallery_entry",
|
||||
"public_work_like",
|
||||
"public_work_play_daily_stat",
|
||||
"puzzle_agent_message",
|
||||
|
||||
@@ -9,6 +9,7 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
pub struct BarkBattleGalleryViewRow {
|
||||
pub work_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub author_display_name: String,
|
||||
pub source_draft_id: Option<String>,
|
||||
pub config_version: u64,
|
||||
pub ruleset_version: String,
|
||||
@@ -38,6 +39,7 @@ impl __sdk::InModule for BarkBattleGalleryViewRow {
|
||||
pub struct BarkBattleGalleryViewRowCols {
|
||||
pub work_id: __sdk::__query_builder::Col<BarkBattleGalleryViewRow, String>,
|
||||
pub owner_user_id: __sdk::__query_builder::Col<BarkBattleGalleryViewRow, String>,
|
||||
pub author_display_name: __sdk::__query_builder::Col<BarkBattleGalleryViewRow, String>,
|
||||
pub source_draft_id: __sdk::__query_builder::Col<BarkBattleGalleryViewRow, Option<String>>,
|
||||
pub config_version: __sdk::__query_builder::Col<BarkBattleGalleryViewRow, u64>,
|
||||
pub ruleset_version: __sdk::__query_builder::Col<BarkBattleGalleryViewRow, String>,
|
||||
@@ -66,6 +68,10 @@ impl __sdk::__query_builder::HasCols for BarkBattleGalleryViewRow {
|
||||
BarkBattleGalleryViewRowCols {
|
||||
work_id: __sdk::__query_builder::Col::new(table_name, "work_id"),
|
||||
owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"),
|
||||
author_display_name: __sdk::__query_builder::Col::new(
|
||||
table_name,
|
||||
"author_display_name",
|
||||
),
|
||||
source_draft_id: __sdk::__query_builder::Col::new(table_name, "source_draft_id"),
|
||||
config_version: __sdk::__query_builder::Col::new(table_name, "config_version"),
|
||||
ruleset_version: __sdk::__query_builder::Col::new(table_name, "ruleset_version"),
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// 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::public_work_detail_entry_type::PublicWorkDetailEntry;
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
/// Table handle for the table `public_work_detail_entry`.
|
||||
///
|
||||
/// Obtain a handle from the [`PublicWorkDetailEntryTableAccess::public_work_detail_entry`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.public_work_detail_entry()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.public_work_detail_entry().on_insert(...)`.
|
||||
pub struct PublicWorkDetailEntryTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<PublicWorkDetailEntry>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `public_work_detail_entry`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait PublicWorkDetailEntryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`PublicWorkDetailEntryTableHandle`], which mediates access to the table `public_work_detail_entry`.
|
||||
fn public_work_detail_entry(&self) -> PublicWorkDetailEntryTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl PublicWorkDetailEntryTableAccess for super::RemoteTables {
|
||||
fn public_work_detail_entry(&self) -> PublicWorkDetailEntryTableHandle<'_> {
|
||||
PublicWorkDetailEntryTableHandle {
|
||||
imp: self
|
||||
.imp
|
||||
.get_table::<PublicWorkDetailEntry>("public_work_detail_entry"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PublicWorkDetailEntryInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct PublicWorkDetailEntryDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::Table for PublicWorkDetailEntryTableHandle<'ctx> {
|
||||
type Row = PublicWorkDetailEntry;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 {
|
||||
self.imp.count()
|
||||
}
|
||||
fn iter(&self) -> impl Iterator<Item = PublicWorkDetailEntry> + '_ {
|
||||
self.imp.iter()
|
||||
}
|
||||
|
||||
type InsertCallbackId = PublicWorkDetailEntryInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> PublicWorkDetailEntryInsertCallbackId {
|
||||
PublicWorkDetailEntryInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: PublicWorkDetailEntryInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = PublicWorkDetailEntryDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> PublicWorkDetailEntryDeleteCallbackId {
|
||||
PublicWorkDetailEntryDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: PublicWorkDetailEntryDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
let _table =
|
||||
client_cache.get_or_make_table::<PublicWorkDetailEntry>("public_work_detail_entry");
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::v2::TableUpdate,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<PublicWorkDetailEntry>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse("TableUpdate<PublicWorkDetailEntry>", "TableUpdate")
|
||||
.with_cause(e)
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for query builder access to the table `PublicWorkDetailEntry`.
|
||||
///
|
||||
/// Implemented for [`__sdk::QueryTableAccessor`].
|
||||
pub trait public_work_detail_entryQueryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Get a query builder for the table `PublicWorkDetailEntry`.
|
||||
fn public_work_detail_entry(&self) -> __sdk::__query_builder::Table<PublicWorkDetailEntry>;
|
||||
}
|
||||
|
||||
impl public_work_detail_entryQueryTableAccess for __sdk::QueryTableAccessor {
|
||||
fn public_work_detail_entry(&self) -> __sdk::__query_builder::Table<PublicWorkDetailEntry> {
|
||||
__sdk::__query_builder::Table::new("public_work_detail_entry")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// 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 PublicWorkDetailEntry {
|
||||
pub source_type: String,
|
||||
pub work_id: String,
|
||||
pub profile_id: String,
|
||||
pub source_session_id: Option<String>,
|
||||
pub public_work_code: String,
|
||||
pub owner_user_id: String,
|
||||
pub author_display_name: String,
|
||||
pub world_name: String,
|
||||
pub subtitle: String,
|
||||
pub summary_text: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub cover_asset_id: Option<String>,
|
||||
pub theme_tags: Vec<String>,
|
||||
pub play_count: u32,
|
||||
pub remix_count: u32,
|
||||
pub like_count: u32,
|
||||
pub published_at_micros: Option<i64>,
|
||||
pub updated_at_micros: i64,
|
||||
pub sort_time_micros: i64,
|
||||
pub detail_payload_json: String,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for PublicWorkDetailEntry {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
/// Column accessor struct for the table `PublicWorkDetailEntry`.
|
||||
///
|
||||
/// Provides typed access to columns for query building.
|
||||
pub struct PublicWorkDetailEntryCols {
|
||||
pub source_type: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub work_id: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub profile_id: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub source_session_id: __sdk::__query_builder::Col<PublicWorkDetailEntry, Option<String>>,
|
||||
pub public_work_code: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub owner_user_id: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub author_display_name: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub world_name: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub subtitle: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub summary_text: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
pub cover_image_src: __sdk::__query_builder::Col<PublicWorkDetailEntry, Option<String>>,
|
||||
pub cover_asset_id: __sdk::__query_builder::Col<PublicWorkDetailEntry, Option<String>>,
|
||||
pub theme_tags: __sdk::__query_builder::Col<PublicWorkDetailEntry, Vec<String>>,
|
||||
pub play_count: __sdk::__query_builder::Col<PublicWorkDetailEntry, u32>,
|
||||
pub remix_count: __sdk::__query_builder::Col<PublicWorkDetailEntry, u32>,
|
||||
pub like_count: __sdk::__query_builder::Col<PublicWorkDetailEntry, u32>,
|
||||
pub published_at_micros: __sdk::__query_builder::Col<PublicWorkDetailEntry, Option<i64>>,
|
||||
pub updated_at_micros: __sdk::__query_builder::Col<PublicWorkDetailEntry, i64>,
|
||||
pub sort_time_micros: __sdk::__query_builder::Col<PublicWorkDetailEntry, i64>,
|
||||
pub detail_payload_json: __sdk::__query_builder::Col<PublicWorkDetailEntry, String>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for PublicWorkDetailEntry {
|
||||
type Cols = PublicWorkDetailEntryCols;
|
||||
fn cols(table_name: &'static str) -> Self::Cols {
|
||||
PublicWorkDetailEntryCols {
|
||||
source_type: __sdk::__query_builder::Col::new(table_name, "source_type"),
|
||||
work_id: __sdk::__query_builder::Col::new(table_name, "work_id"),
|
||||
profile_id: __sdk::__query_builder::Col::new(table_name, "profile_id"),
|
||||
source_session_id: __sdk::__query_builder::Col::new(table_name, "source_session_id"),
|
||||
public_work_code: __sdk::__query_builder::Col::new(table_name, "public_work_code"),
|
||||
owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"),
|
||||
author_display_name: __sdk::__query_builder::Col::new(
|
||||
table_name,
|
||||
"author_display_name",
|
||||
),
|
||||
world_name: __sdk::__query_builder::Col::new(table_name, "world_name"),
|
||||
subtitle: __sdk::__query_builder::Col::new(table_name, "subtitle"),
|
||||
summary_text: __sdk::__query_builder::Col::new(table_name, "summary_text"),
|
||||
cover_image_src: __sdk::__query_builder::Col::new(table_name, "cover_image_src"),
|
||||
cover_asset_id: __sdk::__query_builder::Col::new(table_name, "cover_asset_id"),
|
||||
theme_tags: __sdk::__query_builder::Col::new(table_name, "theme_tags"),
|
||||
play_count: __sdk::__query_builder::Col::new(table_name, "play_count"),
|
||||
remix_count: __sdk::__query_builder::Col::new(table_name, "remix_count"),
|
||||
like_count: __sdk::__query_builder::Col::new(table_name, "like_count"),
|
||||
published_at_micros: __sdk::__query_builder::Col::new(
|
||||
table_name,
|
||||
"published_at_micros",
|
||||
),
|
||||
updated_at_micros: __sdk::__query_builder::Col::new(table_name, "updated_at_micros"),
|
||||
sort_time_micros: __sdk::__query_builder::Col::new(table_name, "sort_time_micros"),
|
||||
detail_payload_json: __sdk::__query_builder::Col::new(
|
||||
table_name,
|
||||
"detail_payload_json",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
// 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::public_work_gallery_entry_type::PublicWorkGalleryEntry;
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
/// Table handle for the table `public_work_gallery_entry`.
|
||||
///
|
||||
/// Obtain a handle from the [`PublicWorkGalleryEntryTableAccess::public_work_gallery_entry`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.public_work_gallery_entry()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.public_work_gallery_entry().on_insert(...)`.
|
||||
pub struct PublicWorkGalleryEntryTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<PublicWorkGalleryEntry>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `public_work_gallery_entry`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait PublicWorkGalleryEntryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`PublicWorkGalleryEntryTableHandle`], which mediates access to the table `public_work_gallery_entry`.
|
||||
fn public_work_gallery_entry(&self) -> PublicWorkGalleryEntryTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl PublicWorkGalleryEntryTableAccess for super::RemoteTables {
|
||||
fn public_work_gallery_entry(&self) -> PublicWorkGalleryEntryTableHandle<'_> {
|
||||
PublicWorkGalleryEntryTableHandle {
|
||||
imp: self
|
||||
.imp
|
||||
.get_table::<PublicWorkGalleryEntry>("public_work_gallery_entry"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PublicWorkGalleryEntryInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct PublicWorkGalleryEntryDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::Table for PublicWorkGalleryEntryTableHandle<'ctx> {
|
||||
type Row = PublicWorkGalleryEntry;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 {
|
||||
self.imp.count()
|
||||
}
|
||||
fn iter(&self) -> impl Iterator<Item = PublicWorkGalleryEntry> + '_ {
|
||||
self.imp.iter()
|
||||
}
|
||||
|
||||
type InsertCallbackId = PublicWorkGalleryEntryInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> PublicWorkGalleryEntryInsertCallbackId {
|
||||
PublicWorkGalleryEntryInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: PublicWorkGalleryEntryInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = PublicWorkGalleryEntryDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> PublicWorkGalleryEntryDeleteCallbackId {
|
||||
PublicWorkGalleryEntryDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: PublicWorkGalleryEntryDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
let _table =
|
||||
client_cache.get_or_make_table::<PublicWorkGalleryEntry>("public_work_gallery_entry");
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::v2::TableUpdate,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<PublicWorkGalleryEntry>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse("TableUpdate<PublicWorkGalleryEntry>", "TableUpdate")
|
||||
.with_cause(e)
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for query builder access to the table `PublicWorkGalleryEntry`.
|
||||
///
|
||||
/// Implemented for [`__sdk::QueryTableAccessor`].
|
||||
pub trait public_work_gallery_entryQueryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Get a query builder for the table `PublicWorkGalleryEntry`.
|
||||
fn public_work_gallery_entry(&self) -> __sdk::__query_builder::Table<PublicWorkGalleryEntry>;
|
||||
}
|
||||
|
||||
impl public_work_gallery_entryQueryTableAccess for __sdk::QueryTableAccessor {
|
||||
fn public_work_gallery_entry(&self) -> __sdk::__query_builder::Table<PublicWorkGalleryEntry> {
|
||||
__sdk::__query_builder::Table::new("public_work_gallery_entry")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// 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 PublicWorkGalleryEntry {
|
||||
pub source_type: String,
|
||||
pub work_id: String,
|
||||
pub profile_id: String,
|
||||
pub source_session_id: Option<String>,
|
||||
pub public_work_code: String,
|
||||
pub owner_user_id: String,
|
||||
pub author_display_name: String,
|
||||
pub world_name: String,
|
||||
pub subtitle: String,
|
||||
pub summary_text: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub cover_asset_id: Option<String>,
|
||||
pub theme_tags: Vec<String>,
|
||||
pub play_count: u32,
|
||||
pub remix_count: u32,
|
||||
pub like_count: u32,
|
||||
pub published_at_micros: Option<i64>,
|
||||
pub updated_at_micros: i64,
|
||||
pub sort_time_micros: i64,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for PublicWorkGalleryEntry {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
/// Column accessor struct for the table `PublicWorkGalleryEntry`.
|
||||
///
|
||||
/// Provides typed access to columns for query building.
|
||||
pub struct PublicWorkGalleryEntryCols {
|
||||
pub source_type: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub work_id: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub profile_id: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub source_session_id: __sdk::__query_builder::Col<PublicWorkGalleryEntry, Option<String>>,
|
||||
pub public_work_code: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub owner_user_id: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub author_display_name: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub world_name: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub subtitle: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub summary_text: __sdk::__query_builder::Col<PublicWorkGalleryEntry, String>,
|
||||
pub cover_image_src: __sdk::__query_builder::Col<PublicWorkGalleryEntry, Option<String>>,
|
||||
pub cover_asset_id: __sdk::__query_builder::Col<PublicWorkGalleryEntry, Option<String>>,
|
||||
pub theme_tags: __sdk::__query_builder::Col<PublicWorkGalleryEntry, Vec<String>>,
|
||||
pub play_count: __sdk::__query_builder::Col<PublicWorkGalleryEntry, u32>,
|
||||
pub remix_count: __sdk::__query_builder::Col<PublicWorkGalleryEntry, u32>,
|
||||
pub like_count: __sdk::__query_builder::Col<PublicWorkGalleryEntry, u32>,
|
||||
pub published_at_micros: __sdk::__query_builder::Col<PublicWorkGalleryEntry, Option<i64>>,
|
||||
pub updated_at_micros: __sdk::__query_builder::Col<PublicWorkGalleryEntry, i64>,
|
||||
pub sort_time_micros: __sdk::__query_builder::Col<PublicWorkGalleryEntry, i64>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for PublicWorkGalleryEntry {
|
||||
type Cols = PublicWorkGalleryEntryCols;
|
||||
fn cols(table_name: &'static str) -> Self::Cols {
|
||||
PublicWorkGalleryEntryCols {
|
||||
source_type: __sdk::__query_builder::Col::new(table_name, "source_type"),
|
||||
work_id: __sdk::__query_builder::Col::new(table_name, "work_id"),
|
||||
profile_id: __sdk::__query_builder::Col::new(table_name, "profile_id"),
|
||||
source_session_id: __sdk::__query_builder::Col::new(table_name, "source_session_id"),
|
||||
public_work_code: __sdk::__query_builder::Col::new(table_name, "public_work_code"),
|
||||
owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"),
|
||||
author_display_name: __sdk::__query_builder::Col::new(
|
||||
table_name,
|
||||
"author_display_name",
|
||||
),
|
||||
world_name: __sdk::__query_builder::Col::new(table_name, "world_name"),
|
||||
subtitle: __sdk::__query_builder::Col::new(table_name, "subtitle"),
|
||||
summary_text: __sdk::__query_builder::Col::new(table_name, "summary_text"),
|
||||
cover_image_src: __sdk::__query_builder::Col::new(table_name, "cover_image_src"),
|
||||
cover_asset_id: __sdk::__query_builder::Col::new(table_name, "cover_asset_id"),
|
||||
theme_tags: __sdk::__query_builder::Col::new(table_name, "theme_tags"),
|
||||
play_count: __sdk::__query_builder::Col::new(table_name, "play_count"),
|
||||
remix_count: __sdk::__query_builder::Col::new(table_name, "remix_count"),
|
||||
like_count: __sdk::__query_builder::Col::new(table_name, "like_count"),
|
||||
published_at_micros: __sdk::__query_builder::Col::new(
|
||||
table_name,
|
||||
"published_at_micros",
|
||||
),
|
||||
updated_at_micros: __sdk::__query_builder::Col::new(table_name, "updated_at_micros"),
|
||||
sort_time_micros: __sdk::__query_builder::Col::new(table_name, "sort_time_micros"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ pub struct PuzzleRunNextLevelInput {
|
||||
pub run_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub target_profile_id: Option<String>,
|
||||
pub prefer_similar_work: bool,
|
||||
pub advanced_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
171
server-rs/crates/spacetime-client/src/public_work.rs
Normal file
171
server-rs/crates/spacetime-client/src/public_work.rs
Normal file
@@ -0,0 +1,171 @@
|
||||
use super::*;
|
||||
use crate::mapper::*;
|
||||
|
||||
impl SpacetimeClient {
|
||||
pub async fn list_public_work_gallery_entries(
|
||||
&self,
|
||||
) -> Result<Vec<PublicWorkGalleryEntryRecord>, SpacetimeClientError> {
|
||||
self.read_after_connect("list_public_work_gallery_entries", move |connection| {
|
||||
let recent_play_counts = public_work_recent_play_counts_by_source(connection);
|
||||
let mut entries = connection
|
||||
.db()
|
||||
.public_work_gallery_entry()
|
||||
.iter()
|
||||
.collect::<Vec<_>>();
|
||||
sort_public_work_gallery_entries(&mut entries);
|
||||
|
||||
Ok(entries
|
||||
.into_iter()
|
||||
.map(|entry| {
|
||||
let recent_play_count_7d = recent_play_counts
|
||||
.get(&(entry.source_type.clone(), entry.profile_id.clone()))
|
||||
.copied()
|
||||
.unwrap_or(0);
|
||||
map_public_work_gallery_entry(entry, recent_play_count_7d)
|
||||
})
|
||||
.collect())
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_public_work_detail_entries(
|
||||
&self,
|
||||
) -> Result<Vec<PublicWorkDetailEntryRecord>, SpacetimeClientError> {
|
||||
self.read_after_connect("list_public_work_detail_entries", move |connection| {
|
||||
let recent_play_counts = public_work_recent_play_counts_by_source(connection);
|
||||
let mut entries = connection
|
||||
.db()
|
||||
.public_work_detail_entry()
|
||||
.iter()
|
||||
.collect::<Vec<_>>();
|
||||
sort_public_work_detail_entries(&mut entries);
|
||||
|
||||
Ok(entries
|
||||
.into_iter()
|
||||
.map(|entry| {
|
||||
let recent_play_count_7d = recent_play_counts
|
||||
.get(&(entry.source_type.clone(), entry.profile_id.clone()))
|
||||
.copied()
|
||||
.unwrap_or(0);
|
||||
map_public_work_gallery_entry_to_detail_entry(entry, recent_play_count_7d)
|
||||
})
|
||||
.collect())
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_public_work_detail_by_code(
|
||||
&self,
|
||||
public_work_code: String,
|
||||
) -> Result<PublicWorkDetailEntryRecord, SpacetimeClientError> {
|
||||
let public_work_code = public_work_code.trim().to_string();
|
||||
if public_work_code.is_empty() {
|
||||
return Err(SpacetimeClientError::validation_failed(
|
||||
"publicWorkCode 不能为空",
|
||||
));
|
||||
}
|
||||
|
||||
self.read_after_connect("get_public_work_detail_by_code", move |connection| {
|
||||
let recent_play_counts = public_work_recent_play_counts_by_source(connection);
|
||||
let entry = connection
|
||||
.db()
|
||||
.public_work_detail_entry()
|
||||
.iter()
|
||||
.find(|entry| {
|
||||
entry
|
||||
.public_work_code
|
||||
.eq_ignore_ascii_case(&public_work_code)
|
||||
})
|
||||
.ok_or_else(|| SpacetimeClientError::Procedure("公开作品不存在".to_string()))?;
|
||||
let recent_play_count_7d = recent_play_counts
|
||||
.get(&(entry.source_type.clone(), entry.profile_id.clone()))
|
||||
.copied()
|
||||
.unwrap_or(0);
|
||||
|
||||
Ok(map_public_work_gallery_entry_to_detail_entry(
|
||||
entry,
|
||||
recent_play_count_7d,
|
||||
))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_public_work_detail_by_source_profile(
|
||||
&self,
|
||||
source_type: String,
|
||||
profile_id: String,
|
||||
) -> Result<PublicWorkDetailEntryRecord, SpacetimeClientError> {
|
||||
let source_type = source_type.trim().to_string();
|
||||
let profile_id = profile_id.trim().to_string();
|
||||
if source_type.is_empty() || profile_id.is_empty() {
|
||||
return Err(SpacetimeClientError::validation_failed(
|
||||
"sourceType 和 profileId 不能为空",
|
||||
));
|
||||
}
|
||||
|
||||
self.read_after_connect(
|
||||
"get_public_work_detail_by_source_profile",
|
||||
move |connection| {
|
||||
let recent_play_counts = public_work_recent_play_counts_by_source(connection);
|
||||
let entry = connection
|
||||
.db()
|
||||
.public_work_detail_entry()
|
||||
.iter()
|
||||
.find(|entry| {
|
||||
entry.source_type == source_type && entry.profile_id == profile_id
|
||||
})
|
||||
.ok_or_else(|| SpacetimeClientError::Procedure("公开作品不存在".to_string()))?;
|
||||
let recent_play_count_7d = recent_play_counts
|
||||
.get(&(entry.source_type.clone(), entry.profile_id.clone()))
|
||||
.copied()
|
||||
.unwrap_or(0);
|
||||
|
||||
Ok(map_public_work_gallery_entry_to_detail_entry(
|
||||
entry,
|
||||
recent_play_count_7d,
|
||||
))
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
fn sort_public_work_gallery_entries(entries: &mut [PublicWorkGalleryEntry]) {
|
||||
entries.sort_by(|left, right| {
|
||||
right
|
||||
.sort_time_micros
|
||||
.cmp(&left.sort_time_micros)
|
||||
.then_with(|| left.source_type.cmp(&right.source_type))
|
||||
.then_with(|| left.profile_id.cmp(&right.profile_id))
|
||||
});
|
||||
}
|
||||
|
||||
fn sort_public_work_detail_entries(entries: &mut [PublicWorkDetailEntry]) {
|
||||
entries.sort_by(|left, right| {
|
||||
right
|
||||
.sort_time_micros
|
||||
.cmp(&left.sort_time_micros)
|
||||
.then_with(|| left.source_type.cmp(&right.source_type))
|
||||
.then_with(|| left.profile_id.cmp(&right.profile_id))
|
||||
});
|
||||
}
|
||||
|
||||
fn public_work_recent_play_counts_by_source(
|
||||
connection: &DbConnection,
|
||||
) -> HashMap<(String, String), u32> {
|
||||
let current_day = current_public_work_day();
|
||||
let first_day = current_day - (PUBLIC_WORK_RECENT_PLAY_WINDOW_DAYS - 1);
|
||||
let mut counts = HashMap::new();
|
||||
|
||||
for row in connection.db().public_work_play_daily_stat().iter() {
|
||||
if row.played_day < first_day || row.played_day > current_day {
|
||||
continue;
|
||||
}
|
||||
let entry = counts
|
||||
.entry((row.source_type, row.profile_id))
|
||||
.or_insert(0_u32);
|
||||
*entry = entry.saturating_add(row.play_count);
|
||||
}
|
||||
|
||||
counts
|
||||
}
|
||||
@@ -640,6 +640,7 @@ impl SpacetimeClient {
|
||||
run_id: input.run_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
target_profile_id: input.target_profile_id,
|
||||
prefer_similar_work: input.prefer_similar_work,
|
||||
advanced_at_micros: input.advanced_at_micros,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user