diff --git a/rc_core/src/persist/user/account_json.rs b/rc_core/src/persist/user/account_json.rs index f0805a8..f06ea97 100644 --- a/rc_core/src/persist/user/account_json.rs +++ b/rc_core/src/persist/user/account_json.rs @@ -1604,6 +1604,63 @@ impl super::User for UserData { Ok(true) } } + + async fn get_emotes(&self) -> Result, polariton_server::operations::SimpleOpError> { + let user_aux_opt = self.db.user_aux_by_user_id_and_descriptor(self.account.id, oj_rc_database::schema::user_aux::Descriptor::EmotigramWheel).await + .map_err(|e| { + log::error!("Failed to retrieve EmotigramWheel for user_id {}: {}", self.account.id, e); + polariton_server::operations::SimpleOpError::with_message( + crate::data::error_codes::WebServicesError::DatabaseError as i16, + "Failed to update EmotigramWheel".to_owned(), + ) + })?; + if let Some(data) = user_aux_opt { + let val: Vec = serde_json::from_str(&data.data) + .map_err(|e| { + log::error!("Failed to deserialize EmotigramWheel for user_id {}: {}", self.account.id, e); + polariton_server::operations::SimpleOpError::with_message( + crate::data::error_codes::WebServicesError::DatabaseError as i16, + "Failed to deserialize EmotigramWheel".to_owned(), + ) + })?; + Ok(val) + } else { + // database entry not created yet + Ok(Vec::default()) + } + } + + async fn set_emotes(&self, emotes: &[String]) -> Result<(), polariton_server::operations::SimpleOpError> { + let json_str = serde_json::to_string_pretty(emotes).expect("Bad emotes"); + //log::debug!("Settings emotes to {}", json_str); + let to_update = oj_rc_database::schema::user_aux::ActiveModel { + data: oj_rc_database::sea_orm::ActiveValue::Set(json_str), + ..Default::default() + }; + let is_update_missed = self.db.update_user_aux_by_user_id_and_descriptor(to_update.clone(), self.account.id, oj_rc_database::schema::user_aux::Descriptor::EmotigramWheel).await + .map_err(|e| { + log::error!("Failed to update EmotigramWheel for user_id {}: {}", self.account.id, e); + polariton_server::operations::SimpleOpError::with_message( + crate::data::error_codes::WebServicesError::DatabaseError as i16, + "Failed to update EmotigramWheel".to_owned(), + ) + })?.is_none(); + if is_update_missed { // needs to be created + let mut to_insert = to_update; + to_insert.user_id = oj_rc_database::sea_orm::ActiveValue::Set(self.account.id); + to_insert.creation_time = oj_rc_database::sea_orm::ActiveValue::Set(chrono::Utc::now().timestamp()); + to_insert.descriptor = oj_rc_database::sea_orm::ActiveValue::Set(oj_rc_database::schema::user_aux::Descriptor::EmotigramWheel); + self.db.insert_user_aux(vec![to_insert]).await + .map_err(|e| { + log::error!("Failed to insert EmotigramWheel for user_id {}: {}", self.account.id, e); + polariton_server::operations::SimpleOpError::with_message( + crate::data::error_codes::WebServicesError::DatabaseError as i16, + "Failed to insert EmotigramWheel".to_owned(), + ) + })?; + } + Ok(()) + } } struct GameEventSetterImpl { diff --git a/rc_core/src/persist/user/traits.rs b/rc_core/src/persist/user/traits.rs index ed3feb6..88e9f09 100644 --- a/rc_core/src/persist/user/traits.rs +++ b/rc_core/src/persist/user/traits.rs @@ -117,6 +117,8 @@ pub trait User: ChatUser + SocialUser + SocialUserC + LobbyUser + Multipla async fn apply_purchase(&self, action: &crate::persist::config::ShopAction) -> Result; async fn currency_debit(&self, ty: CurrencyType, to_sub: u64) -> Result<(), polariton_server::operations::SimpleOpError>; async fn mark_code_redeemed(&self, code: String) -> Result; + async fn get_emotes(&self) -> Result, polariton_server::operations::SimpleOpError>; + async fn set_emotes(&self, emotes: &[String]) -> Result<(), polariton_server::operations::SimpleOpError>; } #[async_trait::async_trait] diff --git a/rc_database/src/schema/user_aux.rs b/rc_database/src/schema/user_aux.rs index 330ad35..90556d2 100644 --- a/rc_database/src/schema/user_aux.rs +++ b/rc_database/src/schema/user_aux.rs @@ -45,4 +45,5 @@ pub enum Descriptor { AvatarId, // u32, u32::MAX means custom avatar RedeemedPromoCodes, // Vec, JSON Federation, // oj_rc_Core::persist::user::Federation, JSON + EmotigramWheel, // Vec, JSON } diff --git a/rc_services_room/src/operations/all_customisations_info.rs b/rc_services_room/src/operations/all_customisations_info.rs index 13c56e7..20ccd4c 100644 --- a/rc_services_room/src/operations/all_customisations_info.rs +++ b/rc_services_room/src/operations/all_customisations_info.rs @@ -209,7 +209,7 @@ pub(super) fn all_customisations_provider() -> SimpleFunc<216, crate::UserTy, im params.insert(OWNED_SKINS_KEY, Typed::StrArr(all_skins().into_iter().map(|x| x.id.into()).collect::>().into())); params.insert(OWNED_SPAWNS_KEY, Typed::StrArr(all_spawns().into_iter().map(|x| x.id.into()).collect::>().into())); params.insert(OWNED_DEATHS_KEY, Typed::StrArr(all_deaths().into_iter().map(|x| x.id.into()).collect::>().into())); - params.insert(OWNED_EMOTES_KEY, Typed::StrArr(vec![].into())); + params.insert(OWNED_EMOTES_KEY, Typed::StrArr(vec![].into())); // this isn't used??? (see owned_cosmetics) Ok(params.into()) }) } diff --git a/rc_services_room/src/operations/mod.rs b/rc_services_room/src/operations/mod.rs index 316adb3..172016d 100644 --- a/rc_services_room/src/operations/mod.rs +++ b/rc_services_room/src/operations/mod.rs @@ -258,4 +258,5 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler .add(custom_game_player_state::game_player_status_update_provider(init_ctx)) .add(custom_game_can_join_queue::game_can_queue_provider(init_ctx)) .add(custom_game_team::game_team_change_provider(init_ctx)) + .add(owned_cosmetics::save_selected_cosmetics_provider()) } diff --git a/rc_services_room/src/operations/owned_cosmetics.rs b/rc_services_room/src/operations/owned_cosmetics.rs index a4b6723..7c63f23 100644 --- a/rc_services_room/src/operations/owned_cosmetics.rs +++ b/rc_services_room/src/operations/owned_cosmetics.rs @@ -1,21 +1,30 @@ -use polariton_server::operations::SimpleFunc; -use polariton::{operation::{Arr, ParameterTable, Typed}, serdes::TypePrefix}; +use polariton_server::operations::{SimpleFunc, SimpleOperation, SimpleOpError, SimpleOpImpl}; +use polariton::operation::{ParameterTable, Typed}; const PARAM_KEY: u8 = 50; +fn all_emotes() -> Vec { + vec![ + // for future reference: part of EmotigramsConfigurableData (-2824383771674178305) + "Craywave".to_owned(), + "Chicken".to_owned(), + "Heart".to_owned(), + "Lol".to_owned(), + "Thumbsdown".to_owned(), + "Thumbsup".to_owned(), + "Facepalm".to_owned(), + ] +} + pub(super) fn owned_cosmetics_provider() -> SimpleFunc<23, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, _| { let mut params = params.to_dict(); - params.insert(PARAM_KEY, Typed::Arr(Arr { - ty: TypePrefix::Str, // str - custom_ty: None, - items: vec![Typed::Str("1".into())], - })); + params.insert(PARAM_KEY, Typed::StrArr(all_emotes().into_iter().map(|x| x.into()).collect::>().into())); Ok(params.into()) }) } -pub(super) fn selected_cosmetics_provider() -> SimpleFunc<21, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { +/*pub(super) fn selected_cosmetics_provider() -> SimpleFunc<21, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, _| { let mut params = params.to_dict(); params.insert(PARAM_KEY, Typed::Arr(Arr { @@ -25,4 +34,57 @@ pub(super) fn selected_cosmetics_provider() -> SimpleFunc<21, crate::UserTy, imp })); Ok(params.into()) }) +}*/ + +pub(super) struct EmoteListSelected; + +#[async_trait::async_trait] +impl SimpleOperation for EmoteListSelected { + type User = crate::UserTy; + const CODE: u8 = 21; + + async fn handle(&self, mut params: ParameterTable, user: &Self::User) -> Result, SimpleOpError> { + let user_info = user.user()?; + let emotes_list = user_info.get_emotes().await?; + params.insert(PARAM_KEY, Typed::StrArr(emotes_list.into_iter().map(|x| x.into()).collect::>().into())); + Ok(params) + } +} + +pub(super) fn selected_cosmetics_provider() -> SimpleOpImpl { + SimpleOpImpl::new(EmoteListSelected) +} + +pub(super) struct EmoteListSaver; + +#[async_trait::async_trait] +impl SimpleOperation for EmoteListSaver { + type User = crate::UserTy; + const CODE: u8 = 22; + + async fn handle(&self, mut params: ParameterTable, user: &Self::User) -> Result, SimpleOpError> { + if let Some(emotes) = params.remove(&PARAM_KEY) { + if let Typed::StrArr(str_arr) = emotes { + // unused? code path + let user_info = user.user()?; + let emotes_list: Vec = str_arr.vec.into_iter().map(|x| x.string).collect(); + user_info.set_emotes(&emotes_list).await?; + } else if let Typed::Arr(reg_arr) = emotes { + let user_info = user.user()?; + let emotes_list: Vec = reg_arr.items.into_iter().filter_map(|x| { + if let Typed::Str(s) = x { + Some(s.string) + } else { + None + } + }).collect(); + user_info.set_emotes(&emotes_list).await?; + } + } + Ok(params) + } +} + +pub(super) fn save_selected_cosmetics_provider() -> SimpleOpImpl { + SimpleOpImpl::new(EmoteListSaver) }