diff --git a/fern/definition/identity/common.yml b/fern/definition/identity/common.yml index 1c9d50f06b..d4eee8b4bb 100644 --- a/fern/definition/identity/common.yml +++ b/fern/definition/identity/common.yml @@ -82,7 +82,6 @@ types: avatar_url: type: string docs: The URL of this identity's avatar image. - presence: optional is_registered: type: boolean docs: Whether or not this identity is registered with a linked account. @@ -97,7 +96,6 @@ types: avatar_url: type: string docs: The URL of this identity's avatar image. - presence: optional is_registered: type: boolean docs: Whether or not this identity is registered with a linked account. @@ -120,7 +118,6 @@ types: avatar_url: docs: The URL of this identity's avatar image. type: string - presence: optional is_registered: docs: Whether or not this identity is registered with a linked account. type: boolean @@ -166,13 +163,6 @@ types: type: optional docs: A link to the Rivet settings page. - Presence: - docs: Information about the identity's current status, party, and active game. - properties: - update_ts: commons.Timestamp - status: Status - game_activity: optional - Status: docs: The current status of an identity. This helps players understand if another player is currently playing or has their game in the background. diff --git a/lib/chirp-workflow/core/src/ctx/activity.rs b/lib/chirp-workflow/core/src/ctx/activity.rs index 07b82c987d..ecc41df43b 100644 --- a/lib/chirp-workflow/core/src/ctx/activity.rs +++ b/lib/chirp-workflow/core/src/ctx/activity.rs @@ -162,10 +162,6 @@ impl ActivityCtx { self.conn.redis_mm().await } - pub async fn redis_user_presence(&self) -> Result { - self.conn.redis_user_presence().await - } - pub async fn clickhouse(&self) -> GlobalResult { self.conn.clickhouse().await } diff --git a/lib/chirp-workflow/core/src/ctx/api.rs b/lib/chirp-workflow/core/src/ctx/api.rs index 559aa6f3a3..362134abfd 100644 --- a/lib/chirp-workflow/core/src/ctx/api.rs +++ b/lib/chirp-workflow/core/src/ctx/api.rs @@ -232,10 +232,6 @@ impl ApiCtx { self.conn.redis_mm().await } - pub async fn redis_user_presence(&self) -> Result { - self.conn.redis_user_presence().await - } - pub async fn clickhouse(&self) -> GlobalResult { self.conn.clickhouse().await } diff --git a/lib/chirp-workflow/core/src/ctx/operation.rs b/lib/chirp-workflow/core/src/ctx/operation.rs index 923bc455c6..2685838e02 100644 --- a/lib/chirp-workflow/core/src/ctx/operation.rs +++ b/lib/chirp-workflow/core/src/ctx/operation.rs @@ -157,10 +157,6 @@ impl OperationCtx { self.conn.redis_mm().await } - pub async fn redis_user_presence(&self) -> Result { - self.conn.redis_user_presence().await - } - pub async fn clickhouse(&self) -> GlobalResult { self.conn.clickhouse().await } diff --git a/lib/chirp-workflow/core/src/ctx/standalone.rs b/lib/chirp-workflow/core/src/ctx/standalone.rs index 4ae0822baa..9debc9ceff 100644 --- a/lib/chirp-workflow/core/src/ctx/standalone.rs +++ b/lib/chirp-workflow/core/src/ctx/standalone.rs @@ -235,10 +235,6 @@ impl StandaloneCtx { self.conn.redis_mm().await } - pub async fn redis_user_presence(&self) -> Result { - self.conn.redis_user_presence().await - } - pub async fn clickhouse(&self) -> GlobalResult { self.conn.clickhouse().await } diff --git a/lib/chirp-workflow/core/src/ctx/test.rs b/lib/chirp-workflow/core/src/ctx/test.rs index e43a55b03d..0a96ab1bf1 100644 --- a/lib/chirp-workflow/core/src/ctx/test.rs +++ b/lib/chirp-workflow/core/src/ctx/test.rs @@ -254,10 +254,6 @@ impl TestCtx { self.conn.redis_mm().await } - pub async fn redis_user_presence(&self) -> Result { - self.conn.redis_user_presence().await - } - pub async fn clickhouse(&self) -> GlobalResult { self.conn.clickhouse().await } diff --git a/lib/chirp/worker/src/test.rs b/lib/chirp/worker/src/test.rs index f41199c914..c3a2dd9134 100644 --- a/lib/chirp/worker/src/test.rs +++ b/lib/chirp/worker/src/test.rs @@ -79,10 +79,6 @@ impl TestCtx { self.op_ctx.redis_mm().await } - pub async fn redis_user_presence(&self) -> Result { - self.op_ctx.redis_user_presence().await - } - pub async fn clickhouse(&self) -> GlobalResult { self.op_ctx.clickhouse().await } diff --git a/lib/connection/src/lib.rs b/lib/connection/src/lib.rs index d7198e8381..27c8a3a931 100644 --- a/lib/connection/src/lib.rs +++ b/lib/connection/src/lib.rs @@ -95,10 +95,6 @@ impl Connection { self.pools.redis("persistent") } - pub async fn redis_user_presence(&self) -> Result { - self.pools.redis("ephemeral") - } - pub async fn redis_chirp_ephemeral(&self) -> Result { self.pools.redis("ephemeral") } diff --git a/lib/convert/Cargo.toml b/lib/convert/Cargo.toml index eada7c5412..450df47900 100644 --- a/lib/convert/Cargo.toml +++ b/lib/convert/Cargo.toml @@ -42,7 +42,6 @@ user-follow-count = { path = "../../svc/pkg/user-follow/ops/count" } user-follow-get = { path = "../../svc/pkg/user-follow/ops/get" } user-get = { path = "../../svc/pkg/user/ops/get" } user-identity-get = { path = "../../svc/pkg/user-identity/ops/get" } -user-presence-get = { path = "../../svc/pkg/user-presence/ops/get" } user-team-list = { path = "../../svc/pkg/user/ops/team-list" } rivet-api = { path = "../../sdks/full/rust" } diff --git a/lib/convert/src/convert/identity.rs b/lib/convert/src/convert/identity.rs index 586ceab42e..2fe06a0279 100644 --- a/lib/convert/src/convert/identity.rs +++ b/lib/convert/src/convert/identity.rs @@ -10,51 +10,16 @@ use crate::{convert, fetch, ApiTryInto}; pub fn handle( current_user_id: Uuid, user: &backend::user::User, - presences_ctx: &fetch::identity::PresencesCtx, is_mutual_following: bool, ) -> GlobalResult { let user_id = unwrap_ref!(user.user_id).as_uuid(); let is_self = user_id == current_user_id; - let user_presence = unwrap!(presences_ctx - .res - .users - .iter() - .find(|presence| presence.user_id == user.user_id)); - let user_presence = unwrap_ref!(user_presence.presence); - let _status = unwrap!(backend::user::Status::from_i32(user_presence.status)); - Ok(models::IdentityHandle { identity_id: user_id, display_name: user.display_name.clone(), account_number: user.account_number as i32, avatar_url: util::route::user_avatar(&user), - presence: Some(Box::new(presence( - user_presence, - &presences_ctx.games, - is_self || is_mutual_following, - )?)), - is_registered: true, // TODO: - external: Box::new(models::IdentityExternalLinks { - profile: util::route::user_profile(user_id), - settings: None, - }), - }) -} - -pub fn handle_without_presence( - current_user_id: Uuid, - user: &backend::user::User, -) -> GlobalResult { - let user_id = unwrap_ref!(user.user_id).as_uuid(); - let _is_self = user_id == current_user_id; - - Ok(models::IdentityHandle { - identity_id: user_id, - display_name: user.display_name.to_owned(), - account_number: user.account_number as i32, - avatar_url: util::route::user_avatar(&user), - presence: None, is_registered: true, // TODO: external: Box::new(models::IdentityExternalLinks { profile: util::route::user_profile(user_id), @@ -66,20 +31,12 @@ pub fn handle_without_presence( pub fn summary( current_user_id: Uuid, user: &backend::user::User, - presences_ctx: &fetch::identity::PresencesCtx, mutual_follows: &[user_follow::get::response::Follow], ) -> GlobalResult { let user_id_proto = unwrap!(user.user_id); let user_id = user_id_proto.as_uuid(); let is_self = user_id == current_user_id; - let user_presence = unwrap!(presences_ctx - .res - .users - .iter() - .find(|presence| presence.user_id == user.user_id)); - let user_presence = unwrap_ref!(user_presence.presence); - let current_user_id = Into::::into(current_user_id); let following = mutual_follows.iter().any(|follow| { follow.follower_user_id.as_ref() == Some(¤t_user_id) @@ -96,11 +53,6 @@ pub fn summary( display_name: user.display_name.clone(), account_number: user.account_number as i32, avatar_url: util::route::user_avatar(&user), - presence: Some(Box::new(presence( - user_presence, - &presences_ctx.games, - is_self || is_mutual_following, - )?)), is_registered: true, // TODO: external: Box::new(models::IdentityExternalLinks { profile: util::route::user_profile(user_id), @@ -114,7 +66,6 @@ pub fn summary( #[derive(Debug)] pub struct ProfileCtx<'a> { - pub presences_ctx: &'a fetch::identity::PresencesCtx, pub teams_ctx: &'a fetch::identity::TeamsCtx, pub mutual_follows: &'a [user_follow::get::response::Follow], pub follower_counts: &'a [user_follow::count::response::Follows], @@ -172,15 +123,6 @@ pub fn profile( .collect::>>()? }; - let user_presence = unwrap!(pctx - .presences_ctx - .res - .users - .iter() - .find(|presence| presence.user_id == user.user_id)); - let user_presence = unwrap_ref!(user_presence.presence); - let _status = unwrap!(backend::user::Status::from_i32(user_presence.status)); - let current_user_id = Into::::into(current_user_id); let following = pctx.mutual_follows.iter().any(|follow| { follow.follower_user_id.as_ref() == Some(¤t_user_id) @@ -210,11 +152,6 @@ pub fn profile( display_name: user.display_name.to_owned(), account_number: user.account_number as i32, avatar_url: util::route::user_avatar(&user), - presence: Some(Box::new(presence( - user_presence, - &pctx.presences_ctx.games, - is_self || is_mutual_following, - )?)), is_registered, external: Box::new(models::IdentityExternalLinks { profile: util::route::user_profile(user_id), @@ -247,51 +184,3 @@ pub fn profile( games: Vec::new(), // TODO: }) } - -pub fn presence( - presence: &backend::user::Presence, - games: &[backend::game::Game], - is_mutual_following: bool, -) -> GlobalResult { - let status = unwrap!(backend::user::Status::from_i32(presence.status)); - - let game_activity = if let Some(game_activity) = &presence.game_activity { - let game_id = unwrap_ref!(game_activity.game_id); - - let game = unwrap!(games - .iter() - .find(|game| game.game_id.as_ref() == Some(game_id))); - - Some(Box::new(models::IdentityGameActivity { - game: Box::new(convert::game::handle(game)?), - message: game_activity.message.to_owned(), - public_metadata: game_activity - .public_metadata - .as_ref() - .and_then(|s| serde_json::from_str(s).ok()), - mutual_metadata: if is_mutual_following { - game_activity - .friend_metadata - .as_ref() - .and_then(|s| serde_json::from_str(s).ok()) - } else { - None - }, - })) - } else { - None - }; - - Ok(models::IdentityPresence { - update_ts: util::timestamp::to_string(presence.update_ts)?, - status: match status { - backend::user::Status::Offline => models::IdentityStatus::Offline, - backend::user::Status::Away => models::IdentityStatus::Away, - backend::user::Status::Online => models::IdentityStatus::Online, - }, - game_activity: match status { - backend::user::Status::Offline => None, - _ => game_activity, - }, - }) -} diff --git a/lib/convert/src/fetch/identity.rs b/lib/convert/src/fetch/identity.rs index 4df121b1ad..ef296e0e3b 100644 --- a/lib/convert/src/fetch/identity.rs +++ b/lib/convert/src/fetch/identity.rs @@ -15,13 +15,6 @@ pub struct TeamsCtx { pub teams: Vec, } -#[derive(Debug)] -pub struct PresencesCtx { - pub res: user_presence::get::Response, - pub games: Vec, - pub games_with_namespace_ids: Vec, -} - pub async fn handles( ctx: &OperationContext<()>, current_user_id: Uuid, @@ -37,9 +30,8 @@ pub async fn handles( .map(Into::into) .collect::>(); - let (users, presences_ctx, mutual_follows) = tokio::try_join!( + let (users, mutual_follows) = tokio::try_join!( users(ctx, user_ids.clone()), - presence_data(ctx, user_ids.clone(), false), mutual_follows(ctx, current_user_id, raw_user_ids), )?; @@ -56,7 +48,7 @@ pub async fn handles( && follow.following_user_id.as_ref() == Some(&raw_current_user_id) }); - convert::identity::handle(current_user_id, user, &presences_ctx, is_mutual_following) + convert::identity::handle(current_user_id, user, is_mutual_following) }) .collect::>>() } @@ -76,9 +68,8 @@ pub async fn summaries( .map(Into::into) .collect::>(); - let (users, presences_ctx, mutual_follows) = tokio::try_join!( + let (users, mutual_follows) = tokio::try_join!( users(ctx, user_ids.clone()), - presence_data(ctx, user_ids.clone(), false), mutual_follows(ctx, current_user_id, raw_user_ids), )?; @@ -90,7 +81,6 @@ pub async fn summaries( convert::identity::summary( current_user_id, user, - &presences_ctx, &mutual_follows.follows, ) }) @@ -119,7 +109,6 @@ pub async fn profiles( let ( users, - presences_ctx, teams_ctx, mutual_follows, (follower_counts, following_counts), @@ -127,7 +116,6 @@ pub async fn profiles( self_is_game_linked, ) = tokio::try_join!( users(ctx, user_ids.clone()), - presence_data(ctx, user_ids.clone(), true), teams(ctx, user_ids.clone()), mutual_follows(ctx, current_user_id, raw_user_ids), follows(ctx, user_ids.clone()), @@ -144,7 +132,6 @@ pub async fn profiles( current_user_id, user, convert::identity::ProfileCtx { - presences_ctx: &presences_ctx, teams_ctx: &teams_ctx, mutual_follows: &mutual_follows.follows, follower_counts: &follower_counts.follows, @@ -168,65 +155,6 @@ pub async fn users( .await } -pub async fn presence_data( - ctx: &OperationContext<()>, - user_ids: Vec, - _summary_info: bool, -) -> GlobalResult { - let ((presences_res, game_ids),) = tokio::try_join!(presences_and_game_ids(ctx, user_ids),)?; - - let (games, games_with_namespace_ids) = games( - ctx, - game_ids - .into_iter() - .map(Into::::into) - .collect::>(), - Vec::new(), - ) - .await?; - - Ok(PresencesCtx { - res: presences_res, - games, - games_with_namespace_ids, - }) -} - -async fn presences_and_game_ids( - ctx: &OperationContext<()>, - user_ids: Vec, -) -> GlobalResult<(user_presence::get::Response, Vec)> { - let user_presences_res = op!([ctx] user_presence_get { - user_ids: user_ids, - }) - .await?; - - // Fetch game ids from game activities - let game_ids = user_presences_res - .users - .iter() - .filter_map(|user_presence| { - if let Some(backend::user::Presence { - game_activity: - Some(backend::user::presence::GameActivity { - game_id: Some(game_id), - .. - }), - .. - }) = &user_presence.presence - { - Some(game_id.as_uuid()) - } else { - None - } - }) - .collect::>() - .into_iter() - .collect::>(); - - Ok((user_presences_res, game_ids)) -} - async fn games( ctx: &OperationContext<()>, game_ids: Vec, diff --git a/lib/convert/src/impls/identity.rs b/lib/convert/src/impls/identity.rs index 12a2ae2892..9b9a256efb 100644 --- a/lib/convert/src/impls/identity.rs +++ b/lib/convert/src/impls/identity.rs @@ -46,13 +46,3 @@ impl ApiFrom for models::Iden } } } - -impl ApiFrom for backend::user::Status { - fn api_from(value: models::IdentityStatus) -> Self { - match value { - models::IdentityStatus::Offline => backend::user::Status::Offline, - models::IdentityStatus::Online => backend::user::Status::Online, - models::IdentityStatus::Away => backend::user::Status::Away, - } - } -} diff --git a/lib/convert/src/impls/mod.rs b/lib/convert/src/impls/mod.rs index 9c981bf62c..f509ed984d 100644 --- a/lib/convert/src/impls/mod.rs +++ b/lib/convert/src/impls/mod.rs @@ -12,7 +12,6 @@ pub mod group; pub mod identity; pub mod kv; pub mod portal; -pub mod user; impl ApiFrom for new_models::ValidationError { fn api_from(value: common::ValidationError) -> new_models::ValidationError { diff --git a/lib/convert/src/impls/user.rs b/lib/convert/src/impls/user.rs deleted file mode 100644 index 85ad768a2a..0000000000 --- a/lib/convert/src/impls/user.rs +++ /dev/null @@ -1,34 +0,0 @@ -use proto::backend::{self, pkg::*}; -use rivet_operation::prelude::*; - -use crate::ApiFrom; - -impl ApiFrom - for backend::user::event::presence_update::Kind -{ - fn api_from(kind: user_presence::msg::update::message::Kind) -> Self { - match kind { - user_presence::msg::update::message::Kind::Status(status) => { - backend::user::event::presence_update::Kind::Status(status) - } - user_presence::msg::update::message::Kind::GameActivity(game_activity) => { - backend::user::event::presence_update::Kind::GameActivity(game_activity) - } - } - } -} - -impl ApiFrom - for backend::user::update::presence_update::Kind -{ - fn api_from(kind: user_presence::msg::update::message::Kind) -> Self { - match kind { - user_presence::msg::update::message::Kind::Status(status) => { - backend::user::update::presence_update::Kind::Status(status) - } - user_presence::msg::update::message::Kind::GameActivity(game_activity) => { - backend::user::update::presence_update::Kind::GameActivity(game_activity) - } - } - } -} diff --git a/lib/operation/core/src/lib.rs b/lib/operation/core/src/lib.rs index ca7c5b30bf..eedcbac0b6 100644 --- a/lib/operation/core/src/lib.rs +++ b/lib/operation/core/src/lib.rs @@ -256,10 +256,6 @@ where self.conn.redis_mm().await } - pub async fn redis_user_presence(&self) -> Result { - self.conn.redis_user_presence().await - } - pub fn perf(&self) -> &chirp_perf::PerfCtx { self.conn.perf() } diff --git a/proto/backend/user.proto b/proto/backend/user.proto index 9004b243e2..f10941e53d 100644 --- a/proto/backend/user.proto +++ b/proto/backend/user.proto @@ -22,24 +22,3 @@ message User { optional int64 delete_complete_ts = 13; } -message Presence { - reserved 3; // Party - - message GameActivity { - rivet.common.Uuid game_id = 1; - string message = 2; - optional string public_metadata = 3; - optional string friend_metadata = 4; - } - - int64 update_ts = 1; - Status status = 2; - optional GameActivity game_activity = 5; -} - -enum Status { - OFFLINE = 0; - ONLINE = 1; - AWAY = 2; -} - diff --git a/proto/backend/user/event.proto b/proto/backend/user/event.proto index 32103f4d31..62a90179ef 100644 --- a/proto/backend/user/event.proto +++ b/proto/backend/user/event.proto @@ -6,12 +6,11 @@ import "proto/common.proto"; import "proto/backend/user.proto"; message Event { - reserved 3; + reserved 3, 6; oneof kind { UserUpdate user_update = 5; MatchmakerLobbyJoin matchmaker_lobby_join = 4; - PresenceUpdate presence_update = 6; TeamMemberRemove team_member_remove = 7; } } @@ -28,13 +27,6 @@ message MatchmakerLobbyJoin { string player_token = 5; } -message PresenceUpdate { - oneof kind { - backend.user.Status status = 1; - backend.user.Presence.GameActivity game_activity = 2; - } -} - message TeamMemberRemove { rivet.common.Uuid team_id = 1; } diff --git a/proto/backend/user/update.proto b/proto/backend/user/update.proto index bedecb6ed1..2585ab1fb2 100644 --- a/proto/backend/user/update.proto +++ b/proto/backend/user/update.proto @@ -6,11 +6,10 @@ import "proto/common.proto"; import "proto/backend/user.proto"; message Update { - reserved 3; + reserved 2, 3; oneof kind { UserUpdate update = 1; - PresenceUpdate presence_update = 2; FollowCreate follow_create = 4; FollowDelete follow_delete = 5; } @@ -20,15 +19,6 @@ message UserUpdate { reserved 1; } -message PresenceUpdate { - reserved 1; - - oneof kind { - backend.user.Status status = 2; - backend.user.Presence.GameActivity game_activity = 3; - } -} - message FollowCreate { rivet.common.Uuid follower_user_id = 1; } diff --git a/sdks/full/go/common/identity/types.go b/sdks/full/go/common/identity/types.go index 563a53ab73..690be5da41 100644 --- a/sdks/full/go/common/identity/types.go +++ b/sdks/full/go/common/identity/types.go @@ -7,7 +7,6 @@ import ( fmt "fmt" uuid "github.com/google/uuid" sdk "sdk" - game "sdk/common/game" core "sdk/core" ) @@ -44,50 +43,13 @@ func (e *ExternalLinks) String() string { return fmt.Sprintf("%#v", e) } -// The game an identity is currently participating in. -type GameActivity struct { - Game *game.Handle `json:"game,omitempty"` - // A short activity message about the current game activity. - Message string `json:"message"` - // JSON data seen by anyone. - PublicMetadata interface{} `json:"public_metadata,omitempty"` - // JSON data seen only by the given identity and their mutual followers. - MutualMetadata interface{} `json:"mutual_metadata,omitempty"` - - _rawJSON json.RawMessage -} - -func (g *GameActivity) UnmarshalJSON(data []byte) error { - type unmarshaler GameActivity - var value unmarshaler - if err := json.Unmarshal(data, &value); err != nil { - return err - } - *g = GameActivity(value) - g._rawJSON = json.RawMessage(data) - return nil -} - -func (g *GameActivity) String() string { - if len(g._rawJSON) > 0 { - if value, err := core.StringifyJSON(g._rawJSON); err == nil { - return value - } - } - if value, err := core.StringifyJSON(g); err == nil { - return value - } - return fmt.Sprintf("%#v", g) -} - // An identity handle. type Handle struct { IdentityId uuid.UUID `json:"identity_id"` DisplayName sdk.DisplayName `json:"display_name"` AccountNumber sdk.AccountNumber `json:"account_number"` // The URL of this identity's avatar image. - AvatarUrl string `json:"avatar_url"` - Presence *Presence `json:"presence,omitempty"` + AvatarUrl string `json:"avatar_url"` // Whether or not this identity is registered with a linked account. IsRegistered bool `json:"is_registered"` External *ExternalLinks `json:"external,omitempty"` @@ -117,61 +79,3 @@ func (h *Handle) String() string { } return fmt.Sprintf("%#v", h) } - -// Information about the identity's current status, party, and active game. -type Presence struct { - UpdateTs sdk.Timestamp `json:"update_ts"` - Status Status `json:"status,omitempty"` - GameActivity *GameActivity `json:"game_activity,omitempty"` - - _rawJSON json.RawMessage -} - -func (p *Presence) UnmarshalJSON(data []byte) error { - type unmarshaler Presence - var value unmarshaler - if err := json.Unmarshal(data, &value); err != nil { - return err - } - *p = Presence(value) - p._rawJSON = json.RawMessage(data) - return nil -} - -func (p *Presence) String() string { - if len(p._rawJSON) > 0 { - if value, err := core.StringifyJSON(p._rawJSON); err == nil { - return value - } - } - if value, err := core.StringifyJSON(p); err == nil { - return value - } - return fmt.Sprintf("%#v", p) -} - -// The current status of an identity. This helps players understand if another player is currently playing or has their game in the background. -type Status string - -const ( - StatusOnline Status = "online" - StatusAway Status = "away" - StatusOffline Status = "offline" -) - -func NewStatusFromString(s string) (Status, error) { - switch s { - case "online": - return StatusOnline, nil - case "away": - return StatusAway, nil - case "offline": - return StatusOffline, nil - } - var t Status - return "", fmt.Errorf("%s is not a valid %T", s, t) -} - -func (s Status) Ptr() *Status { - return &s -} diff --git a/sdks/full/go/identity/types.go b/sdks/full/go/identity/types.go index 59334981ae..a67e722a6f 100644 --- a/sdks/full/go/identity/types.go +++ b/sdks/full/go/identity/types.go @@ -181,6 +181,42 @@ func (e *EmailLinkedAccount) String() string { return fmt.Sprintf("%#v", e) } +// The game an identity is currently participating in. +type GameActivity struct { + Game *game.Handle `json:"game,omitempty"` + // A short activity message about the current game activity. + Message string `json:"message"` + // JSON data seen by anyone. + PublicMetadata interface{} `json:"public_metadata,omitempty"` + // JSON data seen only by the given identity and their mutual followers. + MutualMetadata interface{} `json:"mutual_metadata,omitempty"` + + _rawJSON json.RawMessage +} + +func (g *GameActivity) UnmarshalJSON(data []byte) error { + type unmarshaler GameActivity + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *g = GameActivity(value) + g._rawJSON = json.RawMessage(data) + return nil +} + +func (g *GameActivity) String() string { + if len(g._rawJSON) > 0 { + if value, err := core.StringifyJSON(g._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(g); err == nil { + return value + } + return fmt.Sprintf("%#v", g) +} + type GameLinkStatus string const ( @@ -450,8 +486,7 @@ type Profile struct { DisplayName sdk.DisplayName `json:"display_name"` AccountNumber sdk.AccountNumber `json:"account_number"` // The URL of this identity's avatar image. - AvatarUrl string `json:"avatar_url"` - Presence *identity.Presence `json:"presence,omitempty"` + AvatarUrl string `json:"avatar_url"` // Whether or not this identity is registered with a linked account. IsRegistered bool `json:"is_registered"` External *identity.ExternalLinks `json:"external,omitempty"` @@ -503,14 +538,39 @@ func (p *Profile) String() string { return fmt.Sprintf("%#v", p) } +// The current status of an identity. This helps players understand if another player is currently playing or has their game in the background. +type Status string + +const ( + StatusOnline Status = "online" + StatusAway Status = "away" + StatusOffline Status = "offline" +) + +func NewStatusFromString(s string) (Status, error) { + switch s { + case "online": + return StatusOnline, nil + case "away": + return StatusAway, nil + case "offline": + return StatusOffline, nil + } + var t Status + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (s Status) Ptr() *Status { + return &s +} + // An identity summary. type Summary struct { IdentityId uuid.UUID `json:"identity_id"` DisplayName sdk.DisplayName `json:"display_name"` AccountNumber sdk.AccountNumber `json:"account_number"` // The URL of this identity's avatar image. - AvatarUrl string `json:"avatar_url"` - Presence *identity.Presence `json:"presence,omitempty"` + AvatarUrl string `json:"avatar_url"` // Whether or not this identity is registered with a linked account. IsRegistered bool `json:"is_registered"` External *identity.ExternalLinks `json:"external,omitempty"` @@ -648,7 +708,7 @@ type UpdateProfileRequest struct { } type UpdateStatusRequest struct { - Status identity.Status `json:"status,omitempty"` + Status Status `json:"status,omitempty"` } type ValidateProfileRequest struct { diff --git a/sdks/full/openapi/openapi.yml b/sdks/full/openapi/openapi.yml index fa9eab92f9..ebd299f2a3 100644 --- a/sdks/full/openapi/openapi.yml +++ b/sdks/full/openapi/openapi.yml @@ -13836,8 +13836,6 @@ components: avatar_url: type: string description: The URL of this identity's avatar image. - presence: - $ref: '#/components/schemas/IdentityPresence' is_registered: type: boolean description: Whether or not this identity is registered with a linked account. @@ -13864,8 +13862,6 @@ components: avatar_url: type: string description: The URL of this identity's avatar image. - presence: - $ref: '#/components/schemas/IdentityPresence' is_registered: type: boolean description: Whether or not this identity is registered with a linked account. @@ -13905,8 +13901,6 @@ components: avatar_url: type: string description: The URL of this identity's avatar image. - presence: - $ref: '#/components/schemas/IdentityPresence' is_registered: type: boolean description: Whether or not this identity is registered with a linked account. @@ -13992,19 +13986,6 @@ components: description: A link to the Rivet settings page. required: - profile - IdentityPresence: - type: object - description: Information about the identity's current status, party, and active game. - properties: - update_ts: - $ref: '#/components/schemas/Timestamp' - status: - $ref: '#/components/schemas/IdentityStatus' - game_activity: - $ref: '#/components/schemas/IdentityGameActivity' - required: - - update_ts - - status IdentityStatus: type: string enum: diff --git a/sdks/full/openapi_compat/openapi.yml b/sdks/full/openapi_compat/openapi.yml index 7a3a0fca99..e6e5c1b420 100644 --- a/sdks/full/openapi_compat/openapi.yml +++ b/sdks/full/openapi_compat/openapi.yml @@ -3619,8 +3619,6 @@ components: is_registered: description: Whether or not this identity is registered with a linked account. type: boolean - presence: - $ref: '#/components/schemas/IdentityPresence' required: - identity_id - display_name @@ -3757,20 +3755,6 @@ components: - identity_link_url - expire_ts type: object - IdentityPresence: - description: Information about the identity's current status, party, and active - game. - properties: - game_activity: - $ref: '#/components/schemas/IdentityGameActivity' - status: - $ref: '#/components/schemas/IdentityStatus' - update_ts: - $ref: '#/components/schemas/Timestamp' - required: - - update_ts - - status - type: object IdentityProfile: description: An identity profile. properties: @@ -3836,8 +3820,6 @@ components: items: $ref: '#/components/schemas/IdentityLinkedAccount' type: array - presence: - $ref: '#/components/schemas/IdentityPresence' required: - identity_id - display_name @@ -3942,8 +3924,6 @@ components: is_registered: description: Whether or not this identity is registered with a linked account. type: boolean - presence: - $ref: '#/components/schemas/IdentityPresence' required: - identity_id - display_name diff --git a/sdks/full/rust-cli/.openapi-generator/FILES b/sdks/full/rust-cli/.openapi-generator/FILES index 7d8cc9a763..52a2e03c4d 100644 --- a/sdks/full/rust-cli/.openapi-generator/FILES +++ b/sdks/full/rust-cli/.openapi-generator/FILES @@ -288,7 +288,6 @@ docs/IdentityListRecentFollowersResponse.md docs/IdentityPrepareAvatarUploadRequest.md docs/IdentityPrepareAvatarUploadResponse.md docs/IdentityPrepareGameLinkResponse.md -docs/IdentityPresence.md docs/IdentityProfile.md docs/IdentityReportRequest.md docs/IdentitySearchResponse.md @@ -684,7 +683,6 @@ src/models/identity_list_recent_followers_response.rs src/models/identity_prepare_avatar_upload_request.rs src/models/identity_prepare_avatar_upload_response.rs src/models/identity_prepare_game_link_response.rs -src/models/identity_presence.rs src/models/identity_profile.rs src/models/identity_report_request.rs src/models/identity_search_response.rs diff --git a/sdks/full/rust-cli/README.md b/sdks/full/rust-cli/README.md index b2c45ca2b4..a925667323 100644 --- a/sdks/full/rust-cli/README.md +++ b/sdks/full/rust-cli/README.md @@ -437,7 +437,6 @@ Class | Method | HTTP request | Description - [IdentityPrepareAvatarUploadRequest](docs/IdentityPrepareAvatarUploadRequest.md) - [IdentityPrepareAvatarUploadResponse](docs/IdentityPrepareAvatarUploadResponse.md) - [IdentityPrepareGameLinkResponse](docs/IdentityPrepareGameLinkResponse.md) - - [IdentityPresence](docs/IdentityPresence.md) - [IdentityProfile](docs/IdentityProfile.md) - [IdentityReportRequest](docs/IdentityReportRequest.md) - [IdentitySearchResponse](docs/IdentitySearchResponse.md) diff --git a/sdks/full/rust-cli/docs/IdentityHandle.md b/sdks/full/rust-cli/docs/IdentityHandle.md index 629764404f..dbddadf8b5 100644 --- a/sdks/full/rust-cli/docs/IdentityHandle.md +++ b/sdks/full/rust-cli/docs/IdentityHandle.md @@ -10,7 +10,6 @@ Name | Type | Description | Notes **external** | [**crate::models::IdentityExternalLinks**](IdentityExternalLinks.md) | | **identity_id** | [**uuid::Uuid**](uuid::Uuid.md) | | **is_registered** | **bool** | Whether or not this identity is registered with a linked account. | -**presence** | Option<[**crate::models::IdentityPresence**](IdentityPresence.md)> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/full/rust-cli/docs/IdentityPresence.md b/sdks/full/rust-cli/docs/IdentityPresence.md deleted file mode 100644 index 66a71fd89e..0000000000 --- a/sdks/full/rust-cli/docs/IdentityPresence.md +++ /dev/null @@ -1,13 +0,0 @@ -# IdentityPresence - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**game_activity** | Option<[**crate::models::IdentityGameActivity**](IdentityGameActivity.md)> | | [optional] -**status** | [**crate::models::IdentityStatus**](IdentityStatus.md) | | -**update_ts** | **String** | RFC3339 timestamp | - -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/sdks/full/rust-cli/docs/IdentityProfile.md b/sdks/full/rust-cli/docs/IdentityProfile.md index 9c79c1ee4d..615f085968 100644 --- a/sdks/full/rust-cli/docs/IdentityProfile.md +++ b/sdks/full/rust-cli/docs/IdentityProfile.md @@ -24,7 +24,6 @@ Name | Type | Description | Notes **is_registered** | **bool** | Whether or not this identity is registered with a linked account. | **join_ts** | **String** | RFC3339 timestamp | **linked_accounts** | [**Vec**](IdentityLinkedAccount.md) | | -**presence** | Option<[**crate::models::IdentityPresence**](IdentityPresence.md)> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/full/rust-cli/docs/IdentitySummary.md b/sdks/full/rust-cli/docs/IdentitySummary.md index 8b956b7a4e..2ccbb1ff8e 100644 --- a/sdks/full/rust-cli/docs/IdentitySummary.md +++ b/sdks/full/rust-cli/docs/IdentitySummary.md @@ -13,7 +13,6 @@ Name | Type | Description | Notes **is_following_me** | **bool** | Whether or not this identity is both following and is followed by the requestee's identity. | **is_mutual_following** | **bool** | | **is_registered** | **bool** | Whether or not this identity is registered with a linked account. | -**presence** | Option<[**crate::models::IdentityPresence**](IdentityPresence.md)> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/full/rust-cli/src/models/identity_handle.rs b/sdks/full/rust-cli/src/models/identity_handle.rs index 3fa21c3a42..aa3767fe0e 100644 --- a/sdks/full/rust-cli/src/models/identity_handle.rs +++ b/sdks/full/rust-cli/src/models/identity_handle.rs @@ -29,8 +29,6 @@ pub struct IdentityHandle { /// Whether or not this identity is registered with a linked account. #[serde(rename = "is_registered")] pub is_registered: bool, - #[serde(rename = "presence", skip_serializing_if = "Option::is_none")] - pub presence: Option>, } impl IdentityHandle { @@ -43,7 +41,6 @@ impl IdentityHandle { external: Box::new(external), identity_id, is_registered, - presence: None, } } } diff --git a/sdks/full/rust-cli/src/models/identity_presence.rs b/sdks/full/rust-cli/src/models/identity_presence.rs deleted file mode 100644 index 2e4df976d6..0000000000 --- a/sdks/full/rust-cli/src/models/identity_presence.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Rivet API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: 0.0.1 - * - * Generated by: https://openapi-generator.tech - */ - -/// IdentityPresence : Information about the identity's current status, party, and active game. - - - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct IdentityPresence { - #[serde(rename = "game_activity", skip_serializing_if = "Option::is_none")] - pub game_activity: Option>, - #[serde(rename = "status")] - pub status: crate::models::IdentityStatus, - /// RFC3339 timestamp - #[serde(rename = "update_ts")] - pub update_ts: String, -} - -impl IdentityPresence { - /// Information about the identity's current status, party, and active game. - pub fn new(status: crate::models::IdentityStatus, update_ts: String) -> IdentityPresence { - IdentityPresence { - game_activity: None, - status, - update_ts, - } - } -} - - diff --git a/sdks/full/rust-cli/src/models/identity_profile.rs b/sdks/full/rust-cli/src/models/identity_profile.rs index 920c1b42ac..ef5de34586 100644 --- a/sdks/full/rust-cli/src/models/identity_profile.rs +++ b/sdks/full/rust-cli/src/models/identity_profile.rs @@ -64,8 +64,6 @@ pub struct IdentityProfile { pub join_ts: String, #[serde(rename = "linked_accounts")] pub linked_accounts: Vec, - #[serde(rename = "presence", skip_serializing_if = "Option::is_none")] - pub presence: Option>, } impl IdentityProfile { @@ -92,7 +90,6 @@ impl IdentityProfile { is_registered, join_ts, linked_accounts, - presence: None, } } } diff --git a/sdks/full/rust-cli/src/models/identity_summary.rs b/sdks/full/rust-cli/src/models/identity_summary.rs index 585b399d60..d1d1fd63ec 100644 --- a/sdks/full/rust-cli/src/models/identity_summary.rs +++ b/sdks/full/rust-cli/src/models/identity_summary.rs @@ -37,8 +37,6 @@ pub struct IdentitySummary { /// Whether or not this identity is registered with a linked account. #[serde(rename = "is_registered")] pub is_registered: bool, - #[serde(rename = "presence", skip_serializing_if = "Option::is_none")] - pub presence: Option>, } impl IdentitySummary { @@ -54,7 +52,6 @@ impl IdentitySummary { is_following_me, is_mutual_following, is_registered, - presence: None, } } } diff --git a/sdks/full/rust-cli/src/models/mod.rs b/sdks/full/rust-cli/src/models/mod.rs index dfb93cb2a3..2bc9c3e35d 100644 --- a/sdks/full/rust-cli/src/models/mod.rs +++ b/sdks/full/rust-cli/src/models/mod.rs @@ -504,8 +504,6 @@ pub mod identity_prepare_avatar_upload_response; pub use self::identity_prepare_avatar_upload_response::IdentityPrepareAvatarUploadResponse; pub mod identity_prepare_game_link_response; pub use self::identity_prepare_game_link_response::IdentityPrepareGameLinkResponse; -pub mod identity_presence; -pub use self::identity_presence::IdentityPresence; pub mod identity_profile; pub use self::identity_profile::IdentityProfile; pub mod identity_report_request; diff --git a/sdks/full/rust/.openapi-generator/FILES b/sdks/full/rust/.openapi-generator/FILES index 7d8cc9a763..52a2e03c4d 100644 --- a/sdks/full/rust/.openapi-generator/FILES +++ b/sdks/full/rust/.openapi-generator/FILES @@ -288,7 +288,6 @@ docs/IdentityListRecentFollowersResponse.md docs/IdentityPrepareAvatarUploadRequest.md docs/IdentityPrepareAvatarUploadResponse.md docs/IdentityPrepareGameLinkResponse.md -docs/IdentityPresence.md docs/IdentityProfile.md docs/IdentityReportRequest.md docs/IdentitySearchResponse.md @@ -684,7 +683,6 @@ src/models/identity_list_recent_followers_response.rs src/models/identity_prepare_avatar_upload_request.rs src/models/identity_prepare_avatar_upload_response.rs src/models/identity_prepare_game_link_response.rs -src/models/identity_presence.rs src/models/identity_profile.rs src/models/identity_report_request.rs src/models/identity_search_response.rs diff --git a/sdks/full/rust/README.md b/sdks/full/rust/README.md index b2c45ca2b4..a925667323 100644 --- a/sdks/full/rust/README.md +++ b/sdks/full/rust/README.md @@ -437,7 +437,6 @@ Class | Method | HTTP request | Description - [IdentityPrepareAvatarUploadRequest](docs/IdentityPrepareAvatarUploadRequest.md) - [IdentityPrepareAvatarUploadResponse](docs/IdentityPrepareAvatarUploadResponse.md) - [IdentityPrepareGameLinkResponse](docs/IdentityPrepareGameLinkResponse.md) - - [IdentityPresence](docs/IdentityPresence.md) - [IdentityProfile](docs/IdentityProfile.md) - [IdentityReportRequest](docs/IdentityReportRequest.md) - [IdentitySearchResponse](docs/IdentitySearchResponse.md) diff --git a/sdks/full/rust/docs/IdentityHandle.md b/sdks/full/rust/docs/IdentityHandle.md index 629764404f..dbddadf8b5 100644 --- a/sdks/full/rust/docs/IdentityHandle.md +++ b/sdks/full/rust/docs/IdentityHandle.md @@ -10,7 +10,6 @@ Name | Type | Description | Notes **external** | [**crate::models::IdentityExternalLinks**](IdentityExternalLinks.md) | | **identity_id** | [**uuid::Uuid**](uuid::Uuid.md) | | **is_registered** | **bool** | Whether or not this identity is registered with a linked account. | -**presence** | Option<[**crate::models::IdentityPresence**](IdentityPresence.md)> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/full/rust/docs/IdentityPresence.md b/sdks/full/rust/docs/IdentityPresence.md deleted file mode 100644 index 66a71fd89e..0000000000 --- a/sdks/full/rust/docs/IdentityPresence.md +++ /dev/null @@ -1,13 +0,0 @@ -# IdentityPresence - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**game_activity** | Option<[**crate::models::IdentityGameActivity**](IdentityGameActivity.md)> | | [optional] -**status** | [**crate::models::IdentityStatus**](IdentityStatus.md) | | -**update_ts** | **String** | RFC3339 timestamp | - -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/sdks/full/rust/docs/IdentityProfile.md b/sdks/full/rust/docs/IdentityProfile.md index 9c79c1ee4d..615f085968 100644 --- a/sdks/full/rust/docs/IdentityProfile.md +++ b/sdks/full/rust/docs/IdentityProfile.md @@ -24,7 +24,6 @@ Name | Type | Description | Notes **is_registered** | **bool** | Whether or not this identity is registered with a linked account. | **join_ts** | **String** | RFC3339 timestamp | **linked_accounts** | [**Vec**](IdentityLinkedAccount.md) | | -**presence** | Option<[**crate::models::IdentityPresence**](IdentityPresence.md)> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/full/rust/docs/IdentitySummary.md b/sdks/full/rust/docs/IdentitySummary.md index 8b956b7a4e..2ccbb1ff8e 100644 --- a/sdks/full/rust/docs/IdentitySummary.md +++ b/sdks/full/rust/docs/IdentitySummary.md @@ -13,7 +13,6 @@ Name | Type | Description | Notes **is_following_me** | **bool** | Whether or not this identity is both following and is followed by the requestee's identity. | **is_mutual_following** | **bool** | | **is_registered** | **bool** | Whether or not this identity is registered with a linked account. | -**presence** | Option<[**crate::models::IdentityPresence**](IdentityPresence.md)> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/sdks/full/rust/src/models/identity_handle.rs b/sdks/full/rust/src/models/identity_handle.rs index 3fa21c3a42..aa3767fe0e 100644 --- a/sdks/full/rust/src/models/identity_handle.rs +++ b/sdks/full/rust/src/models/identity_handle.rs @@ -29,8 +29,6 @@ pub struct IdentityHandle { /// Whether or not this identity is registered with a linked account. #[serde(rename = "is_registered")] pub is_registered: bool, - #[serde(rename = "presence", skip_serializing_if = "Option::is_none")] - pub presence: Option>, } impl IdentityHandle { @@ -43,7 +41,6 @@ impl IdentityHandle { external: Box::new(external), identity_id, is_registered, - presence: None, } } } diff --git a/sdks/full/rust/src/models/identity_presence.rs b/sdks/full/rust/src/models/identity_presence.rs deleted file mode 100644 index 2e4df976d6..0000000000 --- a/sdks/full/rust/src/models/identity_presence.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Rivet API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: 0.0.1 - * - * Generated by: https://openapi-generator.tech - */ - -/// IdentityPresence : Information about the identity's current status, party, and active game. - - - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct IdentityPresence { - #[serde(rename = "game_activity", skip_serializing_if = "Option::is_none")] - pub game_activity: Option>, - #[serde(rename = "status")] - pub status: crate::models::IdentityStatus, - /// RFC3339 timestamp - #[serde(rename = "update_ts")] - pub update_ts: String, -} - -impl IdentityPresence { - /// Information about the identity's current status, party, and active game. - pub fn new(status: crate::models::IdentityStatus, update_ts: String) -> IdentityPresence { - IdentityPresence { - game_activity: None, - status, - update_ts, - } - } -} - - diff --git a/sdks/full/rust/src/models/identity_profile.rs b/sdks/full/rust/src/models/identity_profile.rs index 920c1b42ac..ef5de34586 100644 --- a/sdks/full/rust/src/models/identity_profile.rs +++ b/sdks/full/rust/src/models/identity_profile.rs @@ -64,8 +64,6 @@ pub struct IdentityProfile { pub join_ts: String, #[serde(rename = "linked_accounts")] pub linked_accounts: Vec, - #[serde(rename = "presence", skip_serializing_if = "Option::is_none")] - pub presence: Option>, } impl IdentityProfile { @@ -92,7 +90,6 @@ impl IdentityProfile { is_registered, join_ts, linked_accounts, - presence: None, } } } diff --git a/sdks/full/rust/src/models/identity_summary.rs b/sdks/full/rust/src/models/identity_summary.rs index 585b399d60..d1d1fd63ec 100644 --- a/sdks/full/rust/src/models/identity_summary.rs +++ b/sdks/full/rust/src/models/identity_summary.rs @@ -37,8 +37,6 @@ pub struct IdentitySummary { /// Whether or not this identity is registered with a linked account. #[serde(rename = "is_registered")] pub is_registered: bool, - #[serde(rename = "presence", skip_serializing_if = "Option::is_none")] - pub presence: Option>, } impl IdentitySummary { @@ -54,7 +52,6 @@ impl IdentitySummary { is_following_me, is_mutual_following, is_registered, - presence: None, } } } diff --git a/sdks/full/rust/src/models/mod.rs b/sdks/full/rust/src/models/mod.rs index dfb93cb2a3..2bc9c3e35d 100644 --- a/sdks/full/rust/src/models/mod.rs +++ b/sdks/full/rust/src/models/mod.rs @@ -504,8 +504,6 @@ pub mod identity_prepare_avatar_upload_response; pub use self::identity_prepare_avatar_upload_response::IdentityPrepareAvatarUploadResponse; pub mod identity_prepare_game_link_response; pub use self::identity_prepare_game_link_response::IdentityPrepareGameLinkResponse; -pub mod identity_presence; -pub use self::identity_presence::IdentityPresence; pub mod identity_profile; pub use self::identity_profile::IdentityProfile; pub mod identity_report_request; diff --git a/sdks/full/typescript/archive.tgz b/sdks/full/typescript/archive.tgz index 22e796eb74..119fb29093 100644 --- a/sdks/full/typescript/archive.tgz +++ b/sdks/full/typescript/archive.tgz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:958448a451bef33a624b50dcacc57d88eb5f766ae525a7353a0f7c4ced309e48 -size 543882 +oid sha256:ab7b3bd68085a1fadcaa66bdd2ad7f0d67f1be835ebec5de1eac3183666b5fa1 +size 550670 diff --git a/sdks/full/typescript/src/api/resources/identity/resources/common/types/Handle.ts b/sdks/full/typescript/src/api/resources/identity/resources/common/types/Handle.ts index 9204d80e3f..1c90232b0d 100644 --- a/sdks/full/typescript/src/api/resources/identity/resources/common/types/Handle.ts +++ b/sdks/full/typescript/src/api/resources/identity/resources/common/types/Handle.ts @@ -13,7 +13,6 @@ export interface Handle { accountNumber: Rivet.AccountNumber; /** The URL of this identity's avatar image. */ avatarUrl: string; - presence?: Rivet.identity.Presence; /** Whether or not this identity is registered with a linked account. */ isRegistered: boolean; external: Rivet.identity.ExternalLinks; diff --git a/sdks/full/typescript/src/api/resources/identity/resources/common/types/Presence.ts b/sdks/full/typescript/src/api/resources/identity/resources/common/types/Presence.ts deleted file mode 100644 index d8f235cfad..0000000000 --- a/sdks/full/typescript/src/api/resources/identity/resources/common/types/Presence.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * This file was auto-generated by Fern from our API Definition. - */ - -import * as Rivet from "../../../../../index"; - -/** - * Information about the identity's current status, party, and active game. - */ -export interface Presence { - updateTs: Rivet.Timestamp; - status: Rivet.identity.Status; - gameActivity?: Rivet.identity.GameActivity; -} diff --git a/sdks/full/typescript/src/api/resources/identity/resources/common/types/Profile.ts b/sdks/full/typescript/src/api/resources/identity/resources/common/types/Profile.ts index f2b7568675..2119ff50fa 100644 --- a/sdks/full/typescript/src/api/resources/identity/resources/common/types/Profile.ts +++ b/sdks/full/typescript/src/api/resources/identity/resources/common/types/Profile.ts @@ -13,7 +13,6 @@ export interface Profile { accountNumber: Rivet.AccountNumber; /** The URL of this identity's avatar image. */ avatarUrl: string; - presence?: Rivet.identity.Presence; /** Whether or not this identity is registered with a linked account. */ isRegistered: boolean; external: Rivet.identity.ExternalLinks; diff --git a/sdks/full/typescript/src/api/resources/identity/resources/common/types/Summary.ts b/sdks/full/typescript/src/api/resources/identity/resources/common/types/Summary.ts index a14af15d23..77c50ee443 100644 --- a/sdks/full/typescript/src/api/resources/identity/resources/common/types/Summary.ts +++ b/sdks/full/typescript/src/api/resources/identity/resources/common/types/Summary.ts @@ -13,7 +13,6 @@ export interface Summary { accountNumber: Rivet.AccountNumber; /** The URL of this identity's avatar image. */ avatarUrl: string; - presence?: Rivet.identity.Presence; /** Whether or not this identity is registered with a linked account. */ isRegistered: boolean; external: Rivet.identity.ExternalLinks; diff --git a/sdks/full/typescript/src/api/resources/identity/resources/common/types/index.ts b/sdks/full/typescript/src/api/resources/identity/resources/common/types/index.ts index 699a6353eb..02242e7a8f 100644 --- a/sdks/full/typescript/src/api/resources/identity/resources/common/types/index.ts +++ b/sdks/full/typescript/src/api/resources/identity/resources/common/types/index.ts @@ -8,7 +8,6 @@ export * from "./Handle"; export * from "./Summary"; export * from "./Profile"; export * from "./ExternalLinks"; -export * from "./Presence"; export * from "./Status"; export * from "./GameActivity"; export * from "./Group"; diff --git a/sdks/full/typescript/src/serialization/resources/identity/resources/common/types/Handle.ts b/sdks/full/typescript/src/serialization/resources/identity/resources/common/types/Handle.ts index bb5b69af4c..9f7b50d68c 100644 --- a/sdks/full/typescript/src/serialization/resources/identity/resources/common/types/Handle.ts +++ b/sdks/full/typescript/src/serialization/resources/identity/resources/common/types/Handle.ts @@ -7,7 +7,6 @@ import * as Rivet from "../../../../../../api/index"; import * as core from "../../../../../../core"; import { DisplayName as common$$displayName } from "../../../../common/types/DisplayName"; import { AccountNumber as common$$accountNumber } from "../../../../common/types/AccountNumber"; -import { Presence as identity_common$$presence } from "./Presence"; import { ExternalLinks as identity_common$$externalLinks } from "./ExternalLinks"; import { common, identity } from "../../../../index"; @@ -17,7 +16,6 @@ export const Handle: core.serialization.ObjectSchema = - core.serialization.object({ - updateTs: core.serialization.property("update_ts", common$$timestamp), - status: identity_common$$status, - gameActivity: core.serialization.property("game_activity", identity_common$$gameActivity.optional()), - }); - -export declare namespace Presence { - interface Raw { - update_ts: common.Timestamp.Raw; - status: identity.Status.Raw; - game_activity?: identity.GameActivity.Raw | null; - } -} diff --git a/sdks/full/typescript/src/serialization/resources/identity/resources/common/types/Profile.ts b/sdks/full/typescript/src/serialization/resources/identity/resources/common/types/Profile.ts index cae08c9f83..198131e263 100644 --- a/sdks/full/typescript/src/serialization/resources/identity/resources/common/types/Profile.ts +++ b/sdks/full/typescript/src/serialization/resources/identity/resources/common/types/Profile.ts @@ -7,7 +7,6 @@ import * as Rivet from "../../../../../../api/index"; import * as core from "../../../../../../core"; import { DisplayName as common$$displayName } from "../../../../common/types/DisplayName"; import { AccountNumber as common$$accountNumber } from "../../../../common/types/AccountNumber"; -import { Presence as identity_common$$presence } from "./Presence"; import { ExternalLinks as identity_common$$externalLinks } from "./ExternalLinks"; import { DevState as identity_common$$devState } from "./DevState"; import { Timestamp as common$$timestamp } from "../../../../common/types/Timestamp"; @@ -23,7 +22,6 @@ export const Profile: core.serialization.ObjectSchema GlobalResult<(HeaderName, He .map_err(Into::::into)?, )) } - -pub fn touch_user_presence(ctx: OperationContext<()>, user_id: Uuid) { - let spawn_res = tokio::task::Builder::new() - .name("api_auth::user_presence_touch") - .spawn(async move { - let res = op!([ctx] user_presence_touch { - user_id: Some(user_id.into()), - }) - .await; - match res { - Ok(_) => {} - Err(err) => tracing::error!(?err, "failed to touch user presence"), - } - }); - if let Err(err) = spawn_res { - tracing::error!(?err, "failed to spawn user_presence_touch task"); - } -} diff --git a/svc/api/group/Cargo.toml b/svc/api/group/Cargo.toml index a7b253c717..bbd67e7deb 100644 --- a/svc/api/group/Cargo.toml +++ b/svc/api/group/Cargo.toml @@ -55,7 +55,6 @@ upload-prepare = { path = "../../pkg/upload/ops/prepare" } user-follow-get = { path = "../../pkg/user-follow/ops/get" } user-get = { path = "../../pkg/user/ops/get" } user-identity-get = { path = "../../pkg/user-identity/ops/get" } -user-presence-get = { path = "../../pkg/user-presence/ops/get" } user-team-list = { path = "../../pkg/user/ops/team-list" } [dev-dependencies] diff --git a/svc/api/group/src/convert/identity.rs b/svc/api/group/src/convert/identity.rs index f5034cfc8f..e2df5a1b61 100644 --- a/svc/api/group/src/convert/identity.rs +++ b/svc/api/group/src/convert/identity.rs @@ -7,7 +7,6 @@ use crate::{convert, fetch}; pub fn handle( current_user_id: Uuid, user: &backend::user::User, - presences_ctx: &fetch::identity::PresencesCtx, is_mutual_following: bool, ) -> GlobalResult { let raw_user_id = unwrap!(user.user_id); @@ -15,24 +14,11 @@ pub fn handle( let is_self = user_id == current_user_id; - let user_presence = unwrap!(presences_ctx - .res - .users - .iter() - .find(|presence| presence.user_id == user.user_id)); - let user_presence = unwrap_ref!(user_presence.presence); - let _status = unwrap!(backend::user::Status::from_i32(user_presence.status)); - Ok(models::IdentityHandle { identity_id: user_id.to_string(), display_name: user.display_name.clone(), account_number: user.account_number as i32, avatar_url: util::route::user_avatar(user), - presence: Some(presence( - user_presence, - &presences_ctx.games, - is_self || is_mutual_following, - )?), is_registered: true, // TODO: external: models::IdentityExternalLinks { profile: util::route::user_profile(user_id), @@ -40,55 +26,6 @@ pub fn handle( chat: Default::default(), }, party: None, - }) -} - -pub fn presence( - presence: &backend::user::Presence, - games: &[backend::game::Game], - is_mutual_following: bool, -) -> GlobalResult { - let status = unwrap!(backend::user::Status::from_i32(presence.status)); - - let game_activity = if let Some(game_activity) = &presence.game_activity { - let game_id = unwrap_ref!(game_activity.game_id); - - let game = unwrap!(games - .iter() - .find(|game| game.game_id.as_ref() == Some(game_id))); - - Some(models::IdentityGameActivity { - game: convert::game_handle(game)?, - message: game_activity.message.to_owned(), - public_metadata: game_activity - .public_metadata - .as_ref() - .map(|metadata| serde_json::from_str::(metadata.as_str())) - .transpose()?, - mutual_metadata: if is_mutual_following { - game_activity - .friend_metadata - .as_ref() - .map(|metadata| serde_json::from_str::(metadata.as_str())) - .transpose()? - } else { - None - }, - }) - } else { - None - }; - - Ok(models::IdentityPresence { - update_ts: util::timestamp::to_chrono(presence.update_ts)?, - status: match status { - backend::user::Status::Offline => models::IdentityStatus::Offline, - backend::user::Status::Away => models::IdentityStatus::Away, - backend::user::Status::Online => models::IdentityStatus::Online, - }, - game_activity: match status { - backend::user::Status::Offline => None, - _ => game_activity, - }, + presence: None, }) } diff --git a/svc/api/group/src/fetch/identity.rs b/svc/api/group/src/fetch/identity.rs index 43311f67a2..444973f714 100644 --- a/svc/api/group/src/fetch/identity.rs +++ b/svc/api/group/src/fetch/identity.rs @@ -9,12 +9,6 @@ use rivet_operation::prelude::*; use crate::{auth::Auth, convert}; -pub struct PresencesCtx { - pub res: user_presence::get::Response, - pub games: Vec, - pub games_with_namespace_ids: Vec, -} - pub async fn users( ctx: &Ctx, user_ids: Vec, @@ -25,65 +19,6 @@ pub async fn users( .await } -pub async fn presence_data( - ctx: &Ctx, - _current_user_id: Uuid, - user_ids: Vec, - _summary_info: bool, -) -> GlobalResult { - let ((presences_res, game_ids),) = tokio::try_join!(presences_and_game_ids(ctx, user_ids),)?; - let (games, games_with_namespace_ids) = games( - ctx, - game_ids - .into_iter() - .map(Into::::into) - .collect::>(), - Vec::new(), - ) - .await?; - - Ok(PresencesCtx { - res: presences_res, - games, - games_with_namespace_ids, - }) -} - -async fn presences_and_game_ids( - ctx: &Ctx, - user_ids: Vec, -) -> GlobalResult<(user_presence::get::Response, Vec)> { - let user_presences_res = op!([ctx] user_presence_get { - user_ids: user_ids, - }) - .await?; - - // Fetch game ids from game activities - let game_ids = user_presences_res - .users - .iter() - .filter_map(|user_presence| { - if let Some(backend::user::Presence { - game_activity: - Some(backend::user::presence::GameActivity { - game_id: Some(game_id), - .. - }), - .. - }) = &user_presence.presence - { - Some(game_id.as_uuid()) - } else { - None - } - }) - .collect::>() - .into_iter() - .collect::>(); - - Ok((user_presences_res, game_ids)) -} - async fn games( ctx: &Ctx, game_ids: Vec, diff --git a/svc/api/group/src/route/groups.rs b/svc/api/group/src/route/groups.rs index 6cbe57ebd0..ec6973bf3a 100644 --- a/svc/api/group/src/route/groups.rs +++ b/svc/api/group/src/route/groups.rs @@ -238,12 +238,6 @@ pub async fn members( tail_anchor!([ctx, anchor] user::msg::update(user_id.as_uuid())).boxed() })); - // User presence subs - let user_presence_subs_select = - util::future::select_all_or_wait(user_ids.iter().cloned().map(|user_id| { - tail_anchor!([ctx, anchor] user_presence::msg::update(user_id.as_uuid())).boxed() - })); - // Listen for updates util::macros::select_with_timeout!({ event = team_member_create_sub => { @@ -263,9 +257,6 @@ pub async fn members( event = user_subs_select => { (None, event?.msg_ts()) } - event = user_presence_subs_select => { - (None, event?.msg_ts()) - } }) } else { Default::default() @@ -293,9 +284,8 @@ pub async fn members( // NOTE: We don't use fetch::identities::handles here because the end model is `GroupMember` not `IdentityHandle` // Fetch team member and join request data - let (users, presences_ctx, user_follows) = tokio::try_join!( + let (users, user_follows) = tokio::try_join!( fetch::identity::users(&ctx, user_ids.clone()), - fetch::identity::presence_data(&ctx, user_ent.user_id, user_ids.clone(), false), fetch::identity::follows( &ctx, user_ent.user_id, @@ -318,12 +308,7 @@ pub async fn members( }); Ok(models::GroupMember { - identity: convert::identity::handle( - user_ent.user_id, - user, - &presences_ctx, - is_mutual_following, - )?, + identity: convert::identity::handle(user_ent.user_id, user, is_mutual_following)?, }) }) .collect::>>()?; @@ -400,12 +385,6 @@ pub async fn join_requests( tail_anchor!([ctx, anchor] user::msg::update(user_id.as_uuid())).boxed() })); - // User presence subs - let user_presence_subs_select = - util::future::select_all_or_wait(user_ids.iter().cloned().map(|user_id| { - tail_anchor!([ctx, anchor] user_presence::msg::update(user_id.as_uuid())).boxed() - })); - // Listen for updates util::macros::select_with_timeout!({ event = team_join_request_create_sub => { @@ -425,9 +404,6 @@ pub async fn join_requests( event = user_subs_select => { (None, event?.msg_ts()) } - event = user_presence_subs_select => { - (None, event?.msg_ts()) - } }) } else { Default::default() @@ -461,9 +437,8 @@ pub async fn join_requests( // NOTE: We don't use fetch::identities::handles here because the end model is `GroupMember` not // `IdentityHandle` // Fetch team member and join request data - let (users, presences_ctx, user_follows) = tokio::try_join!( + let (users, user_follows) = tokio::try_join!( fetch::identity::users(&ctx, user_ids.clone()), - fetch::identity::presence_data(&ctx, user_ent.user_id, user_ids.clone(), false), fetch::identity::follows( &ctx, user_ent.user_id, @@ -492,12 +467,7 @@ pub async fn join_requests( }); Ok(models::GroupJoinRequest { - identity: convert::identity::handle( - user_ent.user_id, - user, - &presences_ctx, - is_mutual_following, - )?, + identity: convert::identity::handle(user_ent.user_id, user, is_mutual_following)?, ts: util::timestamp::to_chrono(join_request_ts)?, }) }) @@ -1309,12 +1279,6 @@ pub async fn bans( tail_anchor!([ctx, anchor] user::msg::update(user_id.as_uuid())).boxed() })); - // User presence subs - let user_presence_subs_select = - util::future::select_all_or_wait(user_ids.iter().cloned().map(|user_id| { - tail_anchor!([ctx, anchor] user_presence::msg::update(user_id.as_uuid())).boxed() - })); - // Listen for updates util::macros::select_with_timeout!({ event = team_ban_sub => { @@ -1334,9 +1298,6 @@ pub async fn bans( event = user_subs_select => { (None, event?.msg_ts()) } - event = user_presence_subs_select => { - (None, event?.msg_ts()) - } }) } else { Default::default() @@ -1370,9 +1331,8 @@ pub async fn bans( // NOTE: We don't use fetch::identities::handles here because the end model is `BannedIdentity` not // `IdentityHandle` // Fetch team member and ban data - let (users, presences_ctx, user_follows) = tokio::try_join!( + let (users, user_follows) = tokio::try_join!( fetch::identity::users(&ctx, user_ids.clone()), - fetch::identity::presence_data(&ctx, user_ent.user_id, user_ids.clone(), false), fetch::identity::follows( &ctx, user_ent.user_id, @@ -1406,12 +1366,7 @@ pub async fn bans( }); Ok(models::GroupBannedIdentity { - identity: convert::identity::handle( - user_ent.user_id, - user, - &presences_ctx, - is_mutual_following, - )?, + identity: convert::identity::handle(user_ent.user_id, user, is_mutual_following)?, ban_ts: util::timestamp::to_chrono(ban_ts)?, }) }) diff --git a/svc/api/identity/Cargo.toml b/svc/api/identity/Cargo.toml index 1a37daee94..3555a4bdea 100644 --- a/svc/api/identity/Cargo.toml +++ b/svc/api/identity/Cargo.toml @@ -67,7 +67,6 @@ user-get = { path = "../../pkg/user/ops/get" } user-identity-get = { path = "../../pkg/user-identity/ops/get" } user-mutual-friend-list = { path = "../../pkg/user/ops/mutual-friend-list" } user-pending-delete-toggle = { path = "../../pkg/user/ops/pending-delete-toggle" } -user-presence-touch = { path = "../../pkg/user-presence/ops/touch" } user-profile-validate = { path = "../../pkg/user/ops/profile-validate" } user-search = { path = "../../pkg/user/ops/search" } diff --git a/svc/api/identity/src/route/activities.rs b/svc/api/identity/src/route/activities.rs deleted file mode 100644 index 3e31e1b58d..0000000000 --- a/svc/api/identity/src/route/activities.rs +++ /dev/null @@ -1,327 +0,0 @@ -use std::collections::HashSet; - -use api_helper::{ - anchor::{WatchIndexQuery, WatchResponse}, - ctx::Ctx, -}; -use chirp_client::TailAnchorResponse; -use futures_util::FutureExt; -use proto::{ - backend::{self, pkg::*}, - common, -}; -use rivet_api::models; -use rivet_convert::{convert, fetch}; -use rivet_operation::prelude::*; - -use crate::auth::Auth; - -#[derive(Debug)] -struct FollowingEntry<'a> { - user: &'a backend::user::User, - presence: &'a backend::user::Presence, -} - -// MARK: GET /activities -#[derive(Debug)] -enum ConsumerUpdate { - Follow(common::Uuid), - Unfollow(common::Uuid), -} - -// TODO: Add message when a new game user session is created and don't refetch all recent games when receiving -// that message -pub async fn activities( - ctx: Ctx, - watch_index: WatchIndexQuery, -) -> GlobalResult { - let (current_user_id, game_user) = ctx.auth().dual_user(ctx.op_ctx()).await?; - - // Fetch users - let followers_res = op!([ctx] user_follow_list { - kind: user_follow::list::request::Kind::Mutual as i32, - user_ids: vec![current_user_id.into()], - limit: 32, - anchor: None, - }) - .await?; - let follows = unwrap!(followers_res.follows.first()).follows.clone(); - - // Fetch user presences - let mut user_ids = follows - .iter() - .filter_map(|f| f.user_id) - .map(|f| *f) - .collect::>(); - - // Wait for an update if needed - let (update, update_ts) = if let Some(anchor) = watch_index.to_consumer()? { - let follow_sub = - tail_anchor!([ctx, anchor] user::msg::mutual_follow_create(current_user_id)); - let unfollow_sub = - tail_anchor!([ctx, anchor] user::msg::mutual_follow_delete(current_user_id)); - - // User presence subs - let user_presence_subs_select = - util::future::select_all_or_wait(user_ids.iter().cloned().map(|user_id| { - tail_anchor!([ctx, anchor] user_presence::msg::update(user_id)).boxed() - })); - - util::macros::select_with_timeout!({ - event = follow_sub => { - if let TailAnchorResponse::Message(msg) = event? { - (msg.user_b_id.map(ConsumerUpdate::Follow), Some(msg.msg_ts())) - } else { - Default::default() - } - } - event = unfollow_sub => { - if let TailAnchorResponse::Message(msg) = event? { - (msg.user_b_id.map(ConsumerUpdate::Unfollow), Some(msg.msg_ts())) - } else { - Default::default() - } - } - event = user_presence_subs_select => { - if let TailAnchorResponse::Message(msg) = event? { - (None, Some(msg.msg_ts())) - } else { - Default::default() - } - } - }) - } else { - Default::default() - }; - let update_ts = update_ts.unwrap_or_else(util::timestamp::now); - - // Remove/add new user - match update { - Some(ConsumerUpdate::Follow(user_id)) => { - user_ids.insert(user_id.as_uuid()); - } - Some(ConsumerUpdate::Unfollow(user_id)) => { - user_ids.remove(&user_id.as_uuid()); - } - _ => {} - } - - // Fetch suggested players and add to user id list so we can fetch their presence data - let suggested_players = - fetch_suggested_players(ctx.op_ctx(), current_user_id, &game_user).await?; - user_ids.extend( - suggested_players - .iter() - .map(|game_user| Ok(**unwrap_ref!(game_user.user_id))) - .collect::>>()? - .into_iter(), - ); - - // Convert into Vec - let user_ids = user_ids.into_iter().map(Into::into).collect::>(); - - // Fetch user data and new follower data (if updated) - let (follows, users, presences_ctx, recent_games, suggested_groups) = tokio::try_join!( - // Fetch follow list updates - async { - match update { - // Refetch follow list if a new follow occurred - Some(ConsumerUpdate::Follow(_)) => { - let followers_res = op!([ctx] user_follow_list { - kind: user_follow::list::request::Kind::Mutual as i32, - user_ids: vec![current_user_id.into()], - limit: 32, - anchor: None, - }) - .await - .map_err(Into::::into)?; - - GlobalResult::Ok(unwrap!(followers_res.follows.first()).follows.clone()) - } - _ => Ok(follows), - } - }, - fetch::identity::users(ctx.op_ctx(), user_ids.clone()), - fetch::identity::presence_data(ctx.op_ctx(), user_ids, true), - fetch_recent_games(ctx.op_ctx(), current_user_id, &game_user), - fetch_suggested_groups(ctx.op_ctx(), current_user_id), - )?; - - // Build following state - let mut follows = follows - .iter() - .filter(|f| { - // Filter out whoever was unfollowed (since we don't re-fetch the follows list for unfollows) - if let Some(ConsumerUpdate::Unfollow(unfollow_id)) = update { - f.user_id != Some(unfollow_id) - } else { - true - } - }) - .map(|follow| { - let user = unwrap!(users.users.iter().find(|u| u.user_id == follow.user_id)); - let presence = unwrap!(presences_ctx - .res - .users - .iter() - .find(|u| u.user_id == follow.user_id) - .and_then(|p| p.presence.as_ref())); - - Ok(FollowingEntry { user, presence }) - }) - .collect::>>()? - .into_iter() - .filter(|f| f.presence.status != backend::user::Status::Offline as i32) - .collect::>(); - - // Sort follows - follows.sort_by_key(|f| f.presence.update_ts); - - let identities = follows - .into_iter() - .map(|follow| convert::identity::handle(current_user_id, follow.user, &presences_ctx, true)) - .collect::>>()?; - - let suggested_players = suggested_players - .into_iter() - .filter_map(|game_user| { - if let Some(user) = users.users.iter().find(|u| u.user_id == game_user.user_id) { - Some(convert::identity::handle( - current_user_id, - user, - &presences_ctx, - true, - )) - } else { - tracing::info!(?game_user, "game user's user does not exist"); - None - } - }) - .collect::>>()?; - - Ok(models::IdentityListActivitiesResponse { - identities, - games: recent_games, - suggested_groups, - suggested_players, - - watch: WatchResponse::new_as_model(update_ts), - }) -} - -async fn fetch_recent_games( - ctx: &OperationContext<()>, - current_user_id: Uuid, - game_user: &Option, -) -> GlobalResult> { - // Don't return recent games for game users - if game_user.is_some() { - return Ok(Vec::new()); - } - - let recent_session_res = op!([ctx] game_user_recent_session_list { - user_ids: vec![current_user_id.into()], - }) - .await?; - let user = unwrap!(recent_session_res.users.first()); - - // Fetch game IDs - let ns_ids = user - .sessions - .iter() - .filter_map(|x| x.namespace_id) - .collect::>(); - let games_res = op!([ctx] game_resolve_namespace_id { - namespace_ids: ns_ids, - }) - .await?; - - // Fetch games - let game_ids = games_res - .games - .iter() - .filter_map(|x| x.game_id) - .map(|x| x.as_uuid()) - .collect::>(); - let games = fetch::game::summaries(ctx, game_ids).await?; - - // Reorder the games by the recent session order - let games = user - .sessions - .iter() - // Session -> namespace - .filter_map(|session| session.namespace_id) - // Namespace -> game - .filter_map(|namespace_id| { - games_res - .games - .iter() - .find(|x| x.namespace_ids.contains(&namespace_id)) - .and_then(|x| x.game_id) - .map(|x| x.as_uuid()) - }) - // Game -> game summary - .filter_map(|game_id| games.iter().find(|x| x.game_id == game_id)) - .cloned() - .collect::>(); - - Ok(games) -} - -async fn fetch_suggested_players( - ctx: &OperationContext<()>, - current_user_id: Uuid, - game_user: &Option, -) -> GlobalResult> { - let recommended_game_user_res = op!([ctx] game_user_recommend { - count: 16, - }) - .await?; - - // Remove self from list if present (game user) - let game_user_ids = if let Some(game_user) = game_user { - let game_user_id = unwrap_ref!(game_user.game_user_id); - - recommended_game_user_res - .game_user_ids - .iter() - .filter(|gi| gi != &game_user_id) - .cloned() - .collect::>() - } else { - recommended_game_user_res.game_user_ids.clone() - }; - - let game_user_res = op!([ctx] game_user_get { - game_user_ids: game_user_ids, - }) - .await?; - - // Remove self from list if present (normal user) - Ok(game_user_res - .game_users - .into_iter() - .filter(|gu| gu.user_id.map(|id| *id) != Some(current_user_id)) - .collect::>()) -} - -async fn fetch_suggested_groups( - ctx: &OperationContext<()>, - current_user_id: Uuid, -) -> GlobalResult> { - let teams_res = op!([ctx] team_recommend { - count: 16, - }) - .await?; - - fetch::group::summaries( - ctx, - Some(current_user_id), - teams_res - .team_ids - .iter() - .map(|team_id| **team_id) - .collect::>(), - ) - .await -} diff --git a/svc/api/identity/src/route/events.rs b/svc/api/identity/src/route/events.rs index d57eb601d9..3c41497e28 100644 --- a/svc/api/identity/src/route/events.rs +++ b/svc/api/identity/src/route/events.rs @@ -27,8 +27,6 @@ pub async fn events( None }; - utils::touch_user_presence(ctx.op_ctx().base(), current_user_id, false); - // Wait for an update if needed let EventsWaitResponse { new_mm_lobby_joins, @@ -128,9 +126,6 @@ async fn events_wait( backend::user::event::event::Kind::UserUpdate(_) => { user_update_ts = Some(msg.msg_ts()); } - backend::user::event::event::Kind::PresenceUpdate(_) => { - user_update_ts = Some(msg.msg_ts()); - } backend::user::event::event::Kind::TeamMemberRemove(team) => { removed_team_ids.push((msg.msg_ts(), unwrap_ref!(team.team_id).as_uuid())); } diff --git a/svc/api/identity/src/route/identities.rs b/svc/api/identity/src/route/identities.rs index d49169c3be..c46d5e9e4d 100644 --- a/svc/api/identity/src/route/identities.rs +++ b/svc/api/identity/src/route/identities.rs @@ -58,8 +58,6 @@ pub async fn setup_identity( }) .await?; - utils::touch_user_presence(ctx.op_ctx().base(), user_id, true); - // Decode the tokens for the expiration ts let user_token_claims = rivet_claims::decode(&game_user_res.token)??; let game_user_id = *unwrap!(game_user_res.game_user_id); @@ -210,7 +208,6 @@ async fn attempt_setup_existing_identity_token( tracing::info!("game user not found"); return Ok(None); }; - utils::touch_user_presence(ctx.op_ctx().base(), user_id, false); let (identities, game_resolve_res) = tokio::try_join!( fetch::identity::profiles( @@ -479,7 +476,7 @@ pub async fn search( let user_handles = res .users .iter() - .map(|user| convert::identity::handle_without_presence(current_user_id, user)) + .map(|user| convert::identity::handle(current_user_id, user)) .collect::>>()?; Ok(models::IdentitySearchResponse { @@ -488,64 +485,6 @@ pub async fn search( }) } -// MARK: POST /identities/self/activity/ -pub async fn set_game_activity( - ctx: Ctx, - body: models::IdentitySetGameActivityRequest, -) -> GlobalResult { - let game_user = ctx.auth().fetch_game_user(ctx.op_ctx()).await?; - - msg!([ctx] user_presence::msg::game_activity_set(game_user.user_id) { - user_id: Some(game_user.user_id.into()), - game_activity: Some(backend::user::presence::GameActivity { - game_id: Some(game_user.game_id.into()), - message: body.game_activity.message.unwrap_or_default(), - public_metadata: body.game_activity - .public_metadata - .map(|public_metadata| serde_json::to_string(&public_metadata)) - .transpose()?, - friend_metadata: body.game_activity - .mutual_metadata - .map(|mutual_metadata| serde_json::to_string(&mutual_metadata)) - .transpose()?, - }), - }) - .await?; - - Ok(serde_json::json!({})) -} - -// MARK: DELETE /identities/self/activity/ -pub async fn remove_game_activity(ctx: Ctx) -> GlobalResult { - let game_user = ctx.auth().fetch_game_user(ctx.op_ctx()).await?; - - msg!([ctx] user_presence::msg::game_activity_set(game_user.user_id) { - user_id: Some(game_user.user_id.into()), - game_activity: None, - }) - .await?; - - Ok(serde_json::json!({})) -} - -// MARK: POST /identities/self/status -pub async fn update_status( - ctx: Ctx, - body: models::IdentityUpdateStatusRequest, -) -> GlobalResult { - let (current_user_id, _) = ctx.auth().dual_user(ctx.op_ctx()).await?; - - msg!([ctx] user_presence::msg::status_set(current_user_id) { - user_id: Some(current_user_id.into()), - status: ApiInto::::api_into(body.status) as i32, - user_set_status: true, - silent: false, - }) - .await?; - - Ok(serde_json::json!({})) -} - // MARK: POST /identities/{}/follow pub async fn follow_identity( ctx: Ctx, @@ -755,12 +694,6 @@ pub async fn followers( let follow_sub = tail_anchor!([ctx, anchor] user_follow::msg::create("*", identity_id)); let unfollow_sub = tail_anchor!([ctx, anchor] user_follow::msg::delete("*", identity_id)); - // User presence subs - let user_presence_subs_select = - util::future::select_all_or_wait(user_ids.iter().cloned().map(|user_id| { - tail_anchor!([ctx, anchor] user_presence::msg::update(user_id)).boxed() - })); - util::macros::select_with_timeout!({ event = follow_sub => { if let TailAnchorResponse::Message(msg) = event? { @@ -776,13 +709,6 @@ pub async fn followers( Default::default() } } - event = user_presence_subs_select => { - if let TailAnchorResponse::Message(msg) = event? { - (None, Some(msg.msg_ts())) - } else { - Default::default() - } - } }) } else { Default::default() @@ -848,12 +774,6 @@ pub async fn following( let follow_sub = tail_anchor!([ctx, anchor] user_follow::msg::create(identity_id, "*")); let unfollow_sub = tail_anchor!([ctx, anchor] user_follow::msg::delete(identity_id, "*")); - // User presence subs - let user_presence_subs_select = - util::future::select_all_or_wait(user_ids.iter().cloned().map(|user_id| { - tail_anchor!([ctx, anchor] user_presence::msg::update(user_id)).boxed() - })); - util::macros::select_with_timeout!({ event = follow_sub => { if let TailAnchorResponse::Message(msg) = event? { @@ -869,13 +789,6 @@ pub async fn following( Default::default() } } - event = user_presence_subs_select => { - if let TailAnchorResponse::Message(msg) = event? { - (None, Some(msg.msg_ts())) - } else { - Default::default() - } - } }) } else { Default::default() @@ -942,12 +855,6 @@ pub async fn friends( let unfollow_sub = tail_anchor!([ctx, anchor] user::msg::mutual_follow_delete(current_user_id)); - // User presence subs - let user_presence_subs_select = - util::future::select_all_or_wait(user_ids.iter().cloned().map(|user_id| { - tail_anchor!([ctx, anchor] user_presence::msg::update(user_id)).boxed() - })); - util::macros::select_with_timeout!({ event = follow_sub => { if let TailAnchorResponse::Message(msg) = event? { @@ -963,13 +870,6 @@ pub async fn friends( Default::default() } } - event = user_presence_subs_select => { - if let TailAnchorResponse::Message(msg) = event? { - (None, Some(msg.msg_ts())) - } else { - Default::default() - } - } }) } else { Default::default() @@ -1075,12 +975,6 @@ pub async fn recent_followers( let mutual_sub = tail_anchor!([ctx, anchor] user::msg::mutual_follow_create(current_user_id)); - // User presence subs - let user_presence_subs_select = - util::future::select_all_or_wait(user_ids.iter().cloned().map(|user_id| { - tail_anchor!([ctx, anchor] user_presence::msg::update(user_id)).boxed() - })); - util::macros::select_with_timeout!({ event = follow_sub => { if let TailAnchorResponse::Message(msg) = event? { @@ -1116,11 +1010,6 @@ pub async fn recent_followers( Default::default() } } - event = user_presence_subs_select => { - let event = event?; - - (None, event.msg_ts()) - } }) } else { Default::default() diff --git a/svc/api/identity/src/route/links.rs b/svc/api/identity/src/route/links.rs index 13c717dab2..62c1142110 100644 --- a/svc/api/identity/src/route/links.rs +++ b/svc/api/identity/src/route/links.rs @@ -45,10 +45,6 @@ pub async fn get_game_link( watch_index: WatchIndexQuery, query: GameLinkQuery, ) -> GlobalResult { - if let Ok((current_user_id, _)) = ctx.auth().dual_user(ctx.op_ctx()).await { - utils::touch_user_presence(ctx.op_ctx().base(), current_user_id, false); - } - let (game_user_link_ent, _) = ctx .auth() .game_user_link_ent(query.identity_link_token.to_owned())?; @@ -165,8 +161,6 @@ pub async fn complete_game_link( ) -> GlobalResult { let user_ent = ctx.auth().user(ctx.op_ctx()).await?; - utils::touch_user_presence(ctx.op_ctx().base(), user_ent.user_id, false); - let (game_user_link_ent, token_jti) = ctx .auth() .game_user_link_ent(body.identity_link_token.to_owned())?; @@ -201,8 +195,6 @@ pub async fn cancel_game_link( ) -> GlobalResult { let user_ent = ctx.auth().user(ctx.op_ctx()).await?; - utils::touch_user_presence(ctx.op_ctx().base(), user_ent.user_id, false); - let (game_user_link_ent, token_jti) = ctx .auth() .game_user_link_ent(body.identity_link_token.to_owned())?; diff --git a/svc/api/identity/src/route/mod.rs b/svc/api/identity/src/route/mod.rs index 6edc927c9c..34fad35913 100644 --- a/svc/api/identity/src/route/mod.rs +++ b/svc/api/identity/src/route/mod.rs @@ -3,7 +3,6 @@ use hyper::{Body, Request, Response}; use rivet_api::models; use uuid::Uuid; -mod activities; mod events; mod identities; mod links; @@ -96,35 +95,6 @@ define_router! { "identities" / "self" / "beta-signup": { POST: identities::beta_signup(body: models::IdentitySignupForBetaRequest), }, - "identities" / "self" / "activity": { - POST: identities::set_game_activity( - body: models::IdentitySetGameActivityRequest, - rate_limit: { - key: "identity-activity-set", - buckets: [ - { count: 8 }, - ], - }, - ), - DELETE: identities::remove_game_activity( - rate_limit: { - key: "identity-activity-set", - buckets: [ - { count: 8 }, - ], - }, - ), - }, - "identities" / "self" / "status": { - POST: identities::update_status( - body: models::IdentityUpdateStatusRequest, - rate_limit: { - buckets: [ - { count: 8 }, - ], - }, - ), - }, "identities" / Uuid / "follow": { POST: identities::follow_identity( body: serde_json::Value, @@ -182,11 +152,6 @@ define_router! { GET: events::events(), }, - // Activities - "activities": { - GET: activities::activities(), - }, - // Links "game-links": { POST: links::prepare_game_link( diff --git a/svc/api/identity/src/utils.rs b/svc/api/identity/src/utils.rs index a9071be946..0652eac807 100644 --- a/svc/api/identity/src/utils.rs +++ b/svc/api/identity/src/utils.rs @@ -49,25 +49,6 @@ pub async fn resolve_user_with_game_user_id( Ok(Some(unwrap_ref!(game_user.user_id).as_uuid())) } -pub fn touch_user_presence(ctx: OperationContext<()>, user_id: Uuid, silent: bool) { - let spawn_res = tokio::task::Builder::new() - .name("api_identity::user_presence_touch") - .spawn(async move { - let res = op!([ctx] user_presence_touch { - user_id: Some(user_id.into()), - silent: silent, - }) - .await; - match res { - Ok(_) => {} - Err(err) => tracing::error!(?err, "failed to touch user presence"), - } - }); - if let Err(err) = spawn_res { - tracing::error!(?err, "failed to spawn user_presence_touch task"); - } -} - pub async fn validate_config( ctx: &OperationContext<()>, namespace_id: common::Uuid, diff --git a/svc/pkg/game-node/src/types.rs b/svc/pkg/game-node/src/types.rs index 5e04c26c29..966d6e1bc4 100644 --- a/svc/pkg/game-node/src/types.rs +++ b/svc/pkg/game-node/src/types.rs @@ -1,4 +1,6 @@ -use crate::{CPU_PER_CORE, DISK_PER_CORE, NOMAD_RESERVE_MEMORY, PEGBOARD_RESERVE_MEMORY, RESERVE_LB_MEMORY}; +use crate::{ + CPU_PER_CORE, DISK_PER_CORE, NOMAD_RESERVE_MEMORY, PEGBOARD_RESERVE_MEMORY, RESERVE_LB_MEMORY, +}; /// Provider agnostic hardware specs. #[derive(Debug)] diff --git a/svc/pkg/mm-config/ops/version-prepare/src/lib.rs b/svc/pkg/mm-config/ops/version-prepare/src/lib.rs index 7102a69c97..15c2270ace 100644 --- a/svc/pkg/mm-config/ops/version-prepare/src/lib.rs +++ b/svc/pkg/mm-config/ops/version-prepare/src/lib.rs @@ -1,6 +1,4 @@ -use std::{ - collections::{HashMap, HashSet}, -}; +use std::collections::{HashMap, HashSet}; use proto::backend::{self, pkg::*}; use rivet_operation::prelude::*; diff --git a/svc/pkg/monolith/standalone/worker/Cargo.toml b/svc/pkg/monolith/standalone/worker/Cargo.toml index 6f94cf5570..2a11d267da 100644 --- a/svc/pkg/monolith/standalone/worker/Cargo.toml +++ b/svc/pkg/monolith/standalone/worker/Cargo.toml @@ -35,6 +35,5 @@ team-worker = { path = "../../../team/worker" } upload-worker = { path = "../../../upload/worker" } user-dev-worker = { path = "../../../user-dev/worker" } user-follow-worker = { path = "../../../user-follow/worker" } -user-presence-worker = { path = "../../../user-presence/worker" } user-report-worker = { path = "../../../user-report/worker" } user-worker = { path = "../../../user/worker" } diff --git a/svc/pkg/monolith/standalone/worker/src/lib.rs b/svc/pkg/monolith/standalone/worker/src/lib.rs index 43faafb1ad..4053985c1a 100644 --- a/svc/pkg/monolith/standalone/worker/src/lib.rs +++ b/svc/pkg/monolith/standalone/worker/src/lib.rs @@ -37,7 +37,6 @@ pub async fn run_from_env(pools: rivet_pools::Pools) -> GlobalResult<()> { upload_worker, user_dev_worker, user_follow_worker, - user_presence_worker, user_report_worker, user_worker, ]; diff --git a/svc/pkg/user-presence/db/redis-user-presence/Service.toml b/svc/pkg/user-presence/db/redis-user-presence/Service.toml deleted file mode 100644 index a137e9645a..0000000000 --- a/svc/pkg/user-presence/db/redis-user-presence/Service.toml +++ /dev/null @@ -1,9 +0,0 @@ -[service] -name = "redis-user-presence" - -[runtime] -kind = "redis" -persistent = false - -[cache] - diff --git a/svc/pkg/user-presence/db/user-presence/Service.toml b/svc/pkg/user-presence/db/user-presence/Service.toml deleted file mode 100644 index ff78da7d85..0000000000 --- a/svc/pkg/user-presence/db/user-presence/Service.toml +++ /dev/null @@ -1,7 +0,0 @@ -[service] -name = "db-user-presence" - -[runtime] -kind = "crdb" - -[database] diff --git a/svc/pkg/user-presence/db/user-presence/migrations/20200101000000_init.down.sql b/svc/pkg/user-presence/db/user-presence/migrations/20200101000000_init.down.sql deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/svc/pkg/user-presence/db/user-presence/migrations/20200101000000_init.up.sql b/svc/pkg/user-presence/db/user-presence/migrations/20200101000000_init.up.sql deleted file mode 100644 index 6204ac2f14..0000000000 --- a/svc/pkg/user-presence/db/user-presence/migrations/20200101000000_init.up.sql +++ /dev/null @@ -1,5 +0,0 @@ -CREATE TABLE user_presences ( - user_id UUID PRIMARY KEY, - user_set_status INT NOT NULL -); - diff --git a/svc/pkg/user-presence/ops/get/Cargo.toml b/svc/pkg/user-presence/ops/get/Cargo.toml deleted file mode 100644 index c57c586980..0000000000 --- a/svc/pkg/user-presence/ops/get/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "user-presence-get" -version = "0.0.1" -edition = "2021" -authors = ["Rivet Gaming, LLC "] -license = "Apache-2.0" - -[dependencies] -rivet-operation = { path = "../../../../../lib/operation/core" } -chirp-client = { path = "../../../../../lib/chirp/client" } -chrono = "0.4" -prost = "0.10" -util-user-presence = { package = "rivet-util-user-presence", path = "../../util" } - -[dev-dependencies] -chirp-worker = { path = "../../../../../lib/chirp/worker" } diff --git a/svc/pkg/user-presence/ops/get/Service.toml b/svc/pkg/user-presence/ops/get/Service.toml deleted file mode 100644 index 90c81dbbfa..0000000000 --- a/svc/pkg/user-presence/ops/get/Service.toml +++ /dev/null @@ -1,10 +0,0 @@ -[service] -name = "user-presence-get" - -[runtime] -kind = "rust" - -[operation] - -[databases] -redis-user-presence = {} diff --git a/svc/pkg/user-presence/ops/get/src/lib.rs b/svc/pkg/user-presence/ops/get/src/lib.rs deleted file mode 100644 index e8ddd6bbe2..0000000000 --- a/svc/pkg/user-presence/ops/get/src/lib.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::collections::HashMap; - -use proto::backend::{self, pkg::*}; -use rivet_operation::prelude::*; - -const DEFAULT_STATUS: i32 = backend::user::Status::Offline as i32; - -#[operation(name = "user-presence-get")] -async fn handle( - ctx: OperationContext, -) -> GlobalResult { - let mut redis = ctx.redis_user_presence().await?; - - let user_ids = ctx - .user_ids - .iter() - .map(common::Uuid::as_uuid) - .collect::>(); - - // TODO: Merge Redis calls in to single pipe - - // Fetch game activities - let mut game_activities = { - use util_user_presence::key; - - let mut pipe = redis::pipe(); - - for user_id in &user_ids { - pipe.hget( - key::game_activity(*user_id), - &[ - key::game_activity::USER_ID, - key::game_activity::GAME_ID, - key::game_activity::MESSAGE, - key::game_activity::PUBLIC_METADATA_JSON, - key::game_activity::FRIEND_METADATA_JSON, - ], - ); - } - - pipe.query_async::<_, Vec< - Vec<( - Option, - Option, - Option, - Option, - Option, - )>, - >>(&mut redis) - .await? - .into_iter() - .flatten() - .map( - |(user_id, game_id, message, public_metadata, friend_metadata)| { - if user_id.is_none() { - return GlobalResult::Ok(None); - } - - let user_id = util::uuid::parse(unwrap_ref!(user_id))?; - let game_id = util::uuid::parse(unwrap_ref!(game_id))?; - GlobalResult::Ok(Some(( - user_id, - backend::user::presence::GameActivity { - game_id: Some(game_id.into()), - message: unwrap!(message), - public_metadata, - friend_metadata, - }, - ))) - }, - ) - .filter_map(|x| x.transpose()) - .collect::>>()? - }; - - // Fetch presences - let mut user_presences = { - use util_user_presence::key; - - let mut pipe = redis::pipe(); - - for user_id in &user_ids { - pipe.hget( - key::user_presence(*user_id), - &[ - key::user_presence::USER_ID, - key::user_presence::UPDATE_TS, - key::user_presence::STATUS, - ], - ); - } - - pipe.query_async::<_, Vec, Option, Option)>>>(&mut redis) - .await? - .into_iter() - .flatten() - .map(|(user_id, update_ts, status)| { - if user_id.is_none() { - return GlobalResult::Ok(None); - } - - let user_id = util::uuid::parse(unwrap_ref!(user_id))?; - GlobalResult::Ok(Some(( - user_id, - backend::user::Presence { - update_ts: unwrap!(update_ts), - status: unwrap!(status) as i32, - game_activity: game_activities.remove(&user_id), - }, - ))) - }) - .filter_map(|x| x.transpose()) - .collect::>>()? - }; - - let users = user_ids - .into_iter() - .map(|user_id| { - let presence = user_presences - .remove(&user_id) - .unwrap_or(backend::user::Presence { - update_ts: 0, - status: DEFAULT_STATUS, - game_activity: None, - }); - - Ok(user_presence::get::UserPresenceEntry { - user_id: Some(user_id.into()), - presence: Some(presence), - }) - }) - .collect::>>()?; - - Ok(user_presence::get::Response { users }) -} diff --git a/svc/pkg/user-presence/ops/get/tests/integration.rs b/svc/pkg/user-presence/ops/get/tests/integration.rs deleted file mode 100644 index d7a3aa3bed..0000000000 --- a/svc/pkg/user-presence/ops/get/tests/integration.rs +++ /dev/null @@ -1,56 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; - -#[worker_test] -async fn empty(ctx: TestCtx) { - let user_a_id = Uuid::new_v4(); - let user_nonexistent_id = Uuid::new_v4(); - - let user_a_status = backend::user::Status::Away; - let user_a_game_id = Uuid::new_v4(); - - msg!([ctx] user_presence::msg::status_set(user_a_id) -> user_presence::msg::update { - user_id: Some(user_a_id.into()), - status: user_a_status as i32, - user_set_status: false, - silent: false, - }) - .await - .unwrap(); - - msg!([ctx] user_presence::msg::game_activity_set(user_a_id) -> user_presence::msg::update { - user_id: Some(user_a_id.into()), - game_activity: Some(backend::user::presence::GameActivity { - game_id: Some(user_a_game_id.into()), - message: "".to_owned(), - public_metadata: None, - friend_metadata: None - }) - }) - .await - .unwrap(); - - let res = op!([ctx] user_presence_get { - user_ids: vec![user_a_id.into(), user_nonexistent_id.into()], - }) - .await - .unwrap(); - assert_eq!(2, res.users.len()); - - for user in &res.users { - let user_id: Uuid = **user.user_id.as_ref().unwrap(); - let user_presence = user.presence.as_ref().unwrap(); - - if user_id == user_a_id { - let game_activity = user_presence.game_activity.as_ref().unwrap(); - - assert_eq!(user_a_status as i32, user_presence.status); - assert_eq!(user_a_game_id, **game_activity.game_id.as_ref().unwrap()); - } else if user_id == user_nonexistent_id { - assert_eq!(backend::user::Status::Offline as i32, user_presence.status); - assert!(user_presence.game_activity.is_none()); - } else { - panic!("unknown user"); - } - } -} diff --git a/svc/pkg/user-presence/ops/touch/Cargo.toml b/svc/pkg/user-presence/ops/touch/Cargo.toml deleted file mode 100644 index 696b821f04..0000000000 --- a/svc/pkg/user-presence/ops/touch/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "user-presence-touch" -version = "0.0.1" -edition = "2021" -authors = ["Rivet Gaming, LLC "] -license = "Apache-2.0" - -[dependencies] -rivet-operation = { path = "../../../../../lib/operation/core" } -chirp-client = { path = "../../../../../lib/chirp/client" } -prost = "0.10" -util-user-presence = { package = "rivet-util-user-presence", path = "../../util" } - -[dev-dependencies] -chirp-worker = { path = "../../../../../lib/chirp/worker" } - -faker-user = { path = "../../../faker/ops/user" } diff --git a/svc/pkg/user-presence/ops/touch/README.md b/svc/pkg/user-presence/ops/touch/README.md deleted file mode 100644 index 9f22f32554..0000000000 --- a/svc/pkg/user-presence/ops/touch/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# user-presence-touch - -Called any time the user makes a presence-related API call. - -This will update the last known timestamp of when the user was seen. We use this to set the user as invisible -if they don't make contact for a while. diff --git a/svc/pkg/user-presence/ops/touch/Service.toml b/svc/pkg/user-presence/ops/touch/Service.toml deleted file mode 100644 index 9a86576f6b..0000000000 --- a/svc/pkg/user-presence/ops/touch/Service.toml +++ /dev/null @@ -1,10 +0,0 @@ -[service] -name = "user-presence-touch" - -[runtime] -kind = "rust" - -[operation] - -[databases] -redis-user-presence = {} diff --git a/svc/pkg/user-presence/ops/touch/src/lib.rs b/svc/pkg/user-presence/ops/touch/src/lib.rs deleted file mode 100644 index 07db23eeeb..0000000000 --- a/svc/pkg/user-presence/ops/touch/src/lib.rs +++ /dev/null @@ -1,32 +0,0 @@ -use proto::backend::pkg::*; -use redis::AsyncCommands; -use rivet_operation::prelude::*; - -#[operation(name = "user-presence-touch")] -async fn handle( - ctx: OperationContext, -) -> GlobalResult { - let mut redis = ctx.redis_user_presence().await?; - - let user_id = unwrap_ref!(ctx.user_id).as_uuid(); - - let elements_added: i64 = redis - .zadd( - util_user_presence::key::user_presence_touch(), - user_id.to_string(), - ctx.ts(), - ) - .await?; - tracing::info!(?elements_added, ?user_id, "updated presence"); - - if elements_added > 0 { - tracing::info!("publishing arrive"); - msg!([ctx] user_presence::msg::arrive(user_id) { - user_id: Some(user_id.into()), - silent: ctx.silent, - }) - .await?; - } - - Ok(user_presence::touch::Response {}) -} diff --git a/svc/pkg/user-presence/ops/touch/tests/integration.rs b/svc/pkg/user-presence/ops/touch/tests/integration.rs deleted file mode 100644 index e05fb80e61..0000000000 --- a/svc/pkg/user-presence/ops/touch/tests/integration.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::time::Duration; - -use chirp_worker::prelude::*; -use proto::backend::pkg::*; -use redis::AsyncCommands; - -#[worker_test] -async fn basic(ctx: TestCtx) { - let mut redis = ctx.redis_user_presence().await.unwrap(); - - let res = op!([ctx] faker_user { - }) - .await - .unwrap(); - let user_id = *res.user_id.unwrap(); - - { - // Test arrive - let mut arrive_sub = subscribe!([ctx] user_presence::msg::arrive(user_id)) - .await - .unwrap(); - op!([ctx] user_presence_touch { - user_id: res.user_id, - }) - .await - .unwrap(); - arrive_sub.next().await.unwrap(); - - // Test it doesn't send arrive message again - op!([ctx] user_presence_touch { - user_id: res.user_id, - }) - .await - .unwrap(); - tokio::time::timeout(Duration::from_secs(1), arrive_sub.next()) - .await - .expect_err("should not have received second arrive message"); - } - - // Force user to leave - msg!([ctx] user_presence::msg::leave(user_id) -> user_presence::msg::status_set { - user_id: res.user_id, - }) - .await - .unwrap(); - - let score: Option = redis - .zscore( - util_user_presence::key::user_presence_touch(), - user_id.to_string(), - ) - .await - .unwrap(); - assert!(score.is_none(), "user presence not removed"); - - // Make sure user status updates when arrive again - // - // We have to make another `arrive_sub` since we test the `next` with a - // timeout before. - { - let mut arrive_sub = subscribe!([ctx] user_presence::msg::arrive(user_id)) - .await - .unwrap(); - op!([ctx] user_presence_touch { - user_id: res.user_id, - }) - .await - .unwrap(); - arrive_sub.next().await.unwrap(); - } -} diff --git a/svc/pkg/user-presence/proto/get.proto b/svc/pkg/user-presence/proto/get.proto deleted file mode 100644 index 9da21e52c6..0000000000 --- a/svc/pkg/user-presence/proto/get.proto +++ /dev/null @@ -1,19 +0,0 @@ -syntax = "proto3"; - -package rivet.backend.pkg.user_presence.get; - -import "proto/common.proto"; -import "proto/backend/user.proto"; - -message Request { - repeated rivet.common.Uuid user_ids = 1; -} - -message Response { - repeated UserPresenceEntry users = 1; -} - -message UserPresenceEntry { - rivet.common.Uuid user_id = 1; - rivet.backend.user.Presence presence = 2; -} diff --git a/svc/pkg/user-presence/proto/leave.proto b/svc/pkg/user-presence/proto/leave.proto deleted file mode 100644 index 67102bd1bf..0000000000 --- a/svc/pkg/user-presence/proto/leave.proto +++ /dev/null @@ -1,13 +0,0 @@ -syntax = "proto3"; - -package rivet.backend.pkg.user_presence.leave; - -import "proto/common.proto"; - -message Request { - rivet.common.Uuid user_id = 1; -} - -message Response { - -} diff --git a/svc/pkg/user-presence/proto/msg/arrive.proto b/svc/pkg/user-presence/proto/msg/arrive.proto deleted file mode 100644 index a91b0a84cc..0000000000 --- a/svc/pkg/user-presence/proto/msg/arrive.proto +++ /dev/null @@ -1,14 +0,0 @@ -syntax = "proto3"; - -package rivet.backend.pkg.user_presence.msg.arrive; - -import "proto/common.proto"; - -/// name = "msg-user-presence-arrive" -/// parameters = [ -/// { name = "user_id" }, -/// ] -message Message { - rivet.common.Uuid user_id = 1; - bool silent = 2; -} diff --git a/svc/pkg/user-presence/proto/msg/game-activity-set.proto b/svc/pkg/user-presence/proto/msg/game-activity-set.proto deleted file mode 100644 index 337b291483..0000000000 --- a/svc/pkg/user-presence/proto/msg/game-activity-set.proto +++ /dev/null @@ -1,15 +0,0 @@ -syntax = "proto3"; - -package rivet.backend.pkg.user_presence.msg.game_activity_set; - -import "proto/common.proto"; -import "proto/backend/user.proto"; - -/// name = "msg-user-game-activity-set" -/// parameters = [ -/// { name = "user_id" }, -/// ] -message Message { - rivet.common.Uuid user_id = 1; - optional rivet.backend.user.Presence.GameActivity game_activity = 2; -} diff --git a/svc/pkg/user-presence/proto/msg/leave.proto b/svc/pkg/user-presence/proto/msg/leave.proto deleted file mode 100644 index c2e8128006..0000000000 --- a/svc/pkg/user-presence/proto/msg/leave.proto +++ /dev/null @@ -1,13 +0,0 @@ -syntax = "proto3"; - -package rivet.backend.pkg.user_presence.msg.leave; - -import "proto/common.proto"; - -/// name = "msg-user-presence-leave" -/// parameters = [ -/// { name = "user_id" }, -/// ] -message Message { - rivet.common.Uuid user_id = 1; -} diff --git a/svc/pkg/user-presence/proto/msg/status-set.proto b/svc/pkg/user-presence/proto/msg/status-set.proto deleted file mode 100644 index 9f9e917c32..0000000000 --- a/svc/pkg/user-presence/proto/msg/status-set.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; - -package rivet.backend.pkg.user_presence.msg.status_set; - -import "proto/common.proto"; -import "proto/backend/user.proto"; - -/// name = "msg-user-status-set" -/// parameters = [ -/// { name = "user_id" }, -/// ] -message Message { - rivet.common.Uuid user_id = 1; - rivet.backend.user.Status status = 2; - // Denotes that the given status is what the user wants it to be - bool user_set_status = 3; - bool silent = 4; -} diff --git a/svc/pkg/user-presence/proto/msg/update.proto b/svc/pkg/user-presence/proto/msg/update.proto deleted file mode 100644 index a8882a3518..0000000000 --- a/svc/pkg/user-presence/proto/msg/update.proto +++ /dev/null @@ -1,23 +0,0 @@ -syntax = "proto3"; - -package rivet.backend.pkg.user_presence.msg.update; - -import "proto/common.proto"; -import "proto/backend/user.proto"; - -/// name = "msg-user-presence-update" -/// tail-ttl = 300 -/// parameters = [ -/// { name = "user_id" }, -/// ] -message Message { - reserved 2; - rivet.common.Uuid user_id = 1; - int64 update_ts = 3; - - // NOTE: Will be unset when clearing game activity - oneof kind { - backend.user.Status status = 4; - backend.user.Presence.GameActivity game_activity = 5; - } -} diff --git a/svc/pkg/user-presence/proto/touch.proto b/svc/pkg/user-presence/proto/touch.proto deleted file mode 100644 index 690b8c1192..0000000000 --- a/svc/pkg/user-presence/proto/touch.proto +++ /dev/null @@ -1,14 +0,0 @@ -syntax = "proto3"; - -package rivet.backend.pkg.user_presence.touch; - -import "proto/common.proto"; - -message Request { - rivet.common.Uuid user_id = 1; - bool silent = 2; -} - -message Response { - -} diff --git a/svc/pkg/user-presence/standalone/gc/Cargo.toml b/svc/pkg/user-presence/standalone/gc/Cargo.toml deleted file mode 100644 index 31ddadb7fa..0000000000 --- a/svc/pkg/user-presence/standalone/gc/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "user-presence-gc" -version = "0.0.1" -edition = "2021" -authors = ["Rivet Gaming, LLC "] -license = "Apache-2.0" - -[dependencies] -chirp-client = { path = "../../../../../lib/chirp/client" } -futures-util = "0.3" -indoc = "1.0" -lazy_static = "1.4" -prost = "0.10" -rivet-connection = { path = "../../../../../lib/connection" } -rivet-health-checks = { path = "../../../../../lib/health-checks" } -rivet-metrics = { path = "../../../../../lib/metrics" } -rivet-operation = { path = "../../../../../lib/operation/core" } -rivet-pools = { path = "../../../../../lib/pools" } -rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.29", features = ["full"] } -tracing = "0.1" -tracing-subscriber = { version = "0.3", default-features = false, features = [ - "fmt", - "json", - "ansi", -] } -tracing-logfmt = "0.3" -util-user-presence = { package = "rivet-util-user-presence", path = "../../util" } - -[dev-dependencies] -chirp-worker = { path = "../../../../../lib/chirp/worker" } -chrono = "0.4" - -user-presence-touch = { path = "../../ops/touch" } diff --git a/svc/pkg/user-presence/standalone/gc/README.md b/svc/pkg/user-presence/standalone/gc/README.md deleted file mode 100644 index 20f8b1bba8..0000000000 --- a/svc/pkg/user-presence/standalone/gc/README.md +++ /dev/null @@ -1 +0,0 @@ -# user-presence-gc diff --git a/svc/pkg/user-presence/standalone/gc/Service.toml b/svc/pkg/user-presence/standalone/gc/Service.toml deleted file mode 100644 index bcc847f155..0000000000 --- a/svc/pkg/user-presence/standalone/gc/Service.toml +++ /dev/null @@ -1,20 +0,0 @@ -[service] -name = "user-presence-gc" - -[runtime] -kind = "rust" - -[headless] -singleton = true - -[databases] -redis-user-presence = {} - -[resources.single-node] -cpu = 50 -memory = 64 - -[resources.distributed] -cpu = 100 -memory = 128 - diff --git a/svc/pkg/user-presence/standalone/gc/src/lib.rs b/svc/pkg/user-presence/standalone/gc/src/lib.rs deleted file mode 100644 index db59ab3825..0000000000 --- a/svc/pkg/user-presence/standalone/gc/src/lib.rs +++ /dev/null @@ -1,43 +0,0 @@ -use futures_util::{StreamExt, TryStreamExt}; -use proto::backend::pkg::*; -use rivet_operation::prelude::*; - -#[tracing::instrument(skip_all)] -pub async fn run_from_env(ts: i64, pools: rivet_pools::Pools) -> GlobalResult<()> { - let client = chirp_client::SharedClient::from_env(pools.clone())?.wrap_new("user-presence-gc"); - let mut redis = pools.redis("ephemeral")?; - - let expire_ts = ts - util_user_presence::USER_PRESENCE_TTL; - let (user_ids,) = redis::pipe() - .zrangebyscore( - util_user_presence::key::user_presence_touch(), - 0, - expire_ts as isize, - ) - .zrembyscore( - util_user_presence::key::user_presence_touch(), - 0, - expire_ts as isize, - ) - .ignore() - .query_async::<_, (Vec,)>(&mut redis) - .await?; - - let user_ids = user_ids - .into_iter() - .filter_map(|x| util::uuid::parse(&x).ok()) - .collect::>(); - tracing::info!(count = user_ids.len(), "removing user presences"); - - futures_util::stream::iter(user_ids.into_iter()) - .map(|user_id| { - msg!([client] @wait user_presence::msg::leave(user_id) { - user_id: Some(user_id.into()), - }) - }) - .buffer_unordered(32) - .try_collect::>() - .await?; - - Ok(()) -} diff --git a/svc/pkg/user-presence/standalone/gc/src/main.rs b/svc/pkg/user-presence/standalone/gc/src/main.rs deleted file mode 100644 index 7574b52c4a..0000000000 --- a/svc/pkg/user-presence/standalone/gc/src/main.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::time::Duration; - -use rivet_operation::prelude::*; - -fn main() -> GlobalResult<()> { - rivet_runtime::run(start()).unwrap() -} - -async fn start() -> GlobalResult<()> { - // TODO: Handle ctrl-c - - let pools = rivet_pools::from_env("user-presence-gc").await?; - - tokio::task::Builder::new() - .name("user_presence_gc::health_checks") - .spawn(rivet_health_checks::run_standalone( - rivet_health_checks::Config { - pools: Some(pools.clone()), - }, - ))?; - - tokio::task::Builder::new() - .name("user_presence_gc::metrics") - .spawn(rivet_metrics::run_standalone())?; - - let mut interval = tokio::time::interval(Duration::from_secs(15)); - loop { - interval.tick().await; - - user_presence_gc::run_from_env(util::timestamp::now(), pools.clone()).await?; - } -} diff --git a/svc/pkg/user-presence/standalone/gc/tests/integration.rs b/svc/pkg/user-presence/standalone/gc/tests/integration.rs deleted file mode 100644 index 38418dce5e..0000000000 --- a/svc/pkg/user-presence/standalone/gc/tests/integration.rs +++ /dev/null @@ -1,63 +0,0 @@ -use ::user_presence_gc::run_from_env; -use chirp_worker::prelude::*; -use redis::AsyncCommands; -use tracing_subscriber::prelude::*; - -#[tokio::test(flavor = "multi_thread")] -async fn basic() { - tracing_subscriber::registry() - .with( - tracing_logfmt::builder() - .layer() - .with_filter(tracing_subscriber::filter::LevelFilter::INFO), - ) - .init(); - - let pools = rivet_pools::from_env("user-presence-gc-test") - .await - .unwrap(); - let ctx = TestCtx::from_env("basic").await.unwrap(); - let mut redis = ctx.redis_user_presence().await.unwrap(); - - let user_id = Uuid::new_v4(); - op!([ctx] user_presence_touch { - user_id: Some(user_id.into()), - }) - .await - .unwrap(); - - // Check the user isn't removed immediately - { - run_from_env(util::timestamp::now(), pools.clone()) - .await - .unwrap(); - - let expire_ts = redis - .zscore::<_, _, Option>( - util_user_presence::key::user_presence_touch(), - user_id.to_string(), - ) - .await - .unwrap(); - assert!(expire_ts.is_some(), "user already removed"); - } - - // Make the GC remove the player - { - run_from_env( - util::timestamp::now() + util_user_presence::USER_PRESENCE_TTL, - pools.clone(), - ) - .await - .unwrap(); - - let expire_ts = redis - .zscore::<_, _, Option>( - util_user_presence::key::user_presence_touch(), - user_id.to_string(), - ) - .await - .unwrap(); - assert!(expire_ts.is_none(), "user not removed"); - } -} diff --git a/svc/pkg/user-presence/util/Cargo.toml b/svc/pkg/user-presence/util/Cargo.toml deleted file mode 100644 index 0d33b3dfa2..0000000000 --- a/svc/pkg/user-presence/util/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "rivet-util-user-presence" -version = "0.1.0" -edition = "2021" -authors = ["Rivet Gaming, LLC "] -license = "Apache-2.0" - -[dependencies] -rivet-util = { path = "../../../../lib/util/core" } -serde = { version = "1.0", features = ["derive"] } -uuid = { version = "1", features = ["v4", "serde"] } diff --git a/svc/pkg/user-presence/util/src/key.rs b/svc/pkg/user-presence/util/src/key.rs deleted file mode 100644 index e513914a30..0000000000 --- a/svc/pkg/user-presence/util/src/key.rs +++ /dev/null @@ -1,63 +0,0 @@ -use uuid::Uuid; - -/// HASH -pub fn user_presence(user_id: Uuid) -> String { - format!("{{global}}:user_presence:user:{user_id}") -} - -pub mod user_presence { - use serde::{Deserialize, Serialize}; - use uuid::Uuid; - - #[derive(Debug, Serialize, Deserialize)] - pub struct State { - #[serde(rename = "u")] - pub user_id: Uuid, - #[serde(rename = "ut")] - pub update_ts: i64, - #[serde(rename = "s")] - pub status: i64, - } - - pub const USER_ID: &str = "u"; - pub const UPDATE_TS: &str = "ut"; - pub const STATUS: &str = "s"; -} - -/// HASH -pub fn game_activity(user_id: Uuid) -> String { - format!("{{global}}:user_presence:game_activity:{user_id}") -} - -pub mod game_activity { - use serde::{Deserialize, Serialize}; - use uuid::Uuid; - - #[derive(Debug, Serialize, Deserialize)] - pub struct State { - #[serde(rename = "u")] - pub user_id: Uuid, - #[serde(rename = "g")] - pub game_id: Uuid, - #[serde(rename = "ut")] - pub update_ts: i64, - #[serde(rename = "m")] - pub message: String, - #[serde(rename = "pm")] - pub public_metadata_json: Option, - #[serde(rename = "fm")] - pub friend_metadata_json: Option, - } - - pub const USER_ID: &str = "u"; - pub const GAME_ID: &str = "g"; - pub const UPDATE_TS: &str = "ut"; - pub const MESSAGE: &str = "m"; - pub const PUBLIC_METADATA_JSON: &str = "pm"; - pub const FRIEND_METADATA_JSON: &str = "gm"; -} - -/// ZSET -pub fn user_presence_touch() -> String { - "{global}:user_presence:user:touch".to_string() -} diff --git a/svc/pkg/user-presence/util/src/lib.rs b/svc/pkg/user-presence/util/src/lib.rs deleted file mode 100644 index 74a49b0ba7..0000000000 --- a/svc/pkg/user-presence/util/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -use rivet_util as util; - -pub mod key; - -pub const USER_PRESENCE_TTL: i64 = util::duration::seconds(90); diff --git a/svc/pkg/user-presence/worker/Cargo.toml b/svc/pkg/user-presence/worker/Cargo.toml deleted file mode 100644 index 1779188fd4..0000000000 --- a/svc/pkg/user-presence/worker/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "user-presence-worker" -version = "0.0.1" -edition = "2021" -authors = ["Rivet Gaming, LLC "] -license = "Apache-2.0" - -[dependencies] -chirp-client = { path = "../../../../lib/chirp/client" } -chirp-worker = { path = "../../../../lib/chirp/worker" } -rivet-health-checks = { path = "../../../../lib/health-checks" } -rivet-metrics = { path = "../../../../lib/metrics" } -rivet-runtime = { path = "../../../../lib/runtime" } -util-user-presence = { package = "rivet-util-user-presence", path = "../util" } - -[dependencies.sqlx] -git = "https://github.com/rivet-gg/sqlx" -rev = "08d6e61aa0572e7ec557abbedb72cebb96e1ac5b" -default-features = false - -[dev-dependencies] -chirp-worker = { path = "../../../../lib/chirp/worker" } - -faker-user = { path = "../../faker/ops/user" } diff --git a/svc/pkg/user-presence/worker/Service.toml b/svc/pkg/user-presence/worker/Service.toml deleted file mode 100644 index 99820feecd..0000000000 --- a/svc/pkg/user-presence/worker/Service.toml +++ /dev/null @@ -1,11 +0,0 @@ -[service] -name = "user-presence-worker" - -[runtime] -kind = "rust" - -[consumer] - -[databases] -db-user-presence = {} -redis-user-presence = {} diff --git a/svc/pkg/user-presence/worker/src/lib.rs b/svc/pkg/user-presence/worker/src/lib.rs deleted file mode 100644 index 3719b10aa8..0000000000 --- a/svc/pkg/user-presence/worker/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod workers; diff --git a/svc/pkg/user-presence/worker/src/workers/arrive.rs b/svc/pkg/user-presence/worker/src/workers/arrive.rs deleted file mode 100644 index 8df9e3f0ba..0000000000 --- a/svc/pkg/user-presence/worker/src/workers/arrive.rs +++ /dev/null @@ -1,35 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; - -const DEFAULT_USER_SET_STATUS: i32 = backend::user::Status::Online as i32; - -#[worker(name = "user-presence-arrive")] -async fn worker(ctx: &OperationContext) -> GlobalResult<()> { - let user_id = unwrap_ref!(ctx.user_id).as_uuid(); - - let user_set_status = sql_fetch_optional!( - [ctx, (Option,)] - "SELECT user_set_status FROM db_user_presence.user_presences WHERE user_id = $1", - user_id, - ) - .await? - .and_then(|x| x.0) - .map(|x| x as i32) - .unwrap_or(DEFAULT_USER_SET_STATUS); - - // No changes need to be made if user set themselves as invisible. Otherwise set to user selected status. - if !matches!( - unwrap_ref!(backend::user::Status::from_i32(user_set_status)), - backend::user::Status::Offline - ) { - msg!([ctx] user_presence::msg::status_set(user_id) { - user_id: ctx.user_id, - status: user_set_status, - user_set_status: false, - silent: ctx.silent, - }) - .await?; - } - - Ok(()) -} diff --git a/svc/pkg/user-presence/worker/src/workers/game_activity_set.rs b/svc/pkg/user-presence/worker/src/workers/game_activity_set.rs deleted file mode 100644 index d4335f0dd8..0000000000 --- a/svc/pkg/user-presence/worker/src/workers/game_activity_set.rs +++ /dev/null @@ -1,52 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::pkg::*; -use redis::AsyncCommands; - -#[worker(name = "user-presence-game-activity-set")] -async fn worker( - ctx: &OperationContext, -) -> GlobalResult<()> { - let mut redis = ctx.redis_user_presence().await?; - - let user_id = unwrap_ref!(ctx.user_id).as_uuid(); - - if let Some(game_activity) = &ctx.game_activity { - use util_user_presence::key; - - let game_id = unwrap_ref!(game_activity.game_id).as_uuid(); - - // TODO: Validate user is online atomically - redis::cmd("HSET") - .arg(key::game_activity(user_id)) - .arg(key::game_activity::USER_ID) - .arg(user_id.to_string()) - .arg(key::game_activity::GAME_ID) - .arg(game_id.to_string()) - .arg(key::game_activity::UPDATE_TS) - .arg(ctx.ts()) - .arg(key::game_activity::MESSAGE) - .arg(&game_activity.message) - .arg(key::game_activity::PUBLIC_METADATA_JSON) - .arg(&game_activity.public_metadata) - .arg(key::game_activity::FRIEND_METADATA_JSON) - .arg(&game_activity.friend_metadata) - .query_async::<_, ()>(&mut redis) - .await?; - } else { - redis - .unlink(util_user_presence::key::game_activity(user_id)) - .await?; - } - - // TODO: Don't publish if user status is set to offline - msg!([ctx] user_presence::msg::update(user_id) { - user_id: Some(user_id.into()), - update_ts: ctx.ts(), - kind: ctx.game_activity - .clone() - .map(user_presence::msg::update::message::Kind::GameActivity), - }) - .await?; - - Ok(()) -} diff --git a/svc/pkg/user-presence/worker/src/workers/leave.rs b/svc/pkg/user-presence/worker/src/workers/leave.rs deleted file mode 100644 index 07941f13f9..0000000000 --- a/svc/pkg/user-presence/worker/src/workers/leave.rs +++ /dev/null @@ -1,61 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; - -const DEFAULT_USER_SET_STATUS: i32 = backend::user::Status::Online as i32; - -#[worker(name = "user-presence-leave")] -async fn worker(ctx: &OperationContext) -> GlobalResult<()> { - let mut redis = ctx.redis_user_presence().await?; - - let user_id = unwrap_ref!(ctx.user_id).as_uuid(); - - let user_set_status = sql_fetch_optional!( - [ctx, (Option,)] - "SELECT user_set_status FROM db_user_presence.user_presences WHERE user_id = $1", - user_id, - ) - .await? - .and_then(|x| x.0) - .map(|x| x as i32) - .unwrap_or(DEFAULT_USER_SET_STATUS); - - // Remove the user from Redis. - // - // Remove the user presence from the register. User may have already been - // removed by user-presence-gc. - let _pipe = redis::pipe() - .atomic() - .unlink(util_user_presence::key::user_presence(user_id)) - .unlink(util_user_presence::key::game_activity(user_id)) - .zrem( - util_user_presence::key::user_presence_touch(), - user_id.to_string(), - ) - .query_async(&mut redis) - .await?; - - // Clear game activity - msg!([ctx] user_presence::msg::game_activity_set(user_id) { - user_id: ctx.user_id, - game_activity: None, - }) - .await?; - - // No changes need to be made if user previously set themselves as invisible. Although we delete the user - // presence data from redis prior to this point (effectively making the user appear offline), this - // block of code sends out a status set event which other subscribers can pick up on for event-based code. - if !matches!( - unwrap_ref!(backend::user::Status::from_i32(user_set_status)), - backend::user::Status::Offline - ) { - msg!([ctx] user_presence::msg::status_set(user_id) { - user_id: ctx.user_id, - status: backend::user::Status::Offline as i32, - user_set_status: false, - silent: false, - }) - .await?; - } - - Ok(()) -} diff --git a/svc/pkg/user-presence/worker/src/workers/mod.rs b/svc/pkg/user-presence/worker/src/workers/mod.rs deleted file mode 100644 index 61fda4f736..0000000000 --- a/svc/pkg/user-presence/worker/src/workers/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod arrive; -mod game_activity_set; -mod leave; -mod status_set; - -chirp_worker::workers![arrive, game_activity_set, leave, status_set,]; diff --git a/svc/pkg/user-presence/worker/src/workers/status_set.rs b/svc/pkg/user-presence/worker/src/workers/status_set.rs deleted file mode 100644 index ed54b54ff4..0000000000 --- a/svc/pkg/user-presence/worker/src/workers/status_set.rs +++ /dev/null @@ -1,56 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; - -#[derive(thiserror::Error, Debug)] -enum Error { - #[error("invalid status")] - InvalidStatus, -} - -#[worker(name = "user-presence-status-set")] -async fn worker( - ctx: &OperationContext, -) -> GlobalResult<()> { - let user_id = unwrap_ref!(ctx.user_id).as_uuid(); - - if backend::user::Status::from_i32(ctx.status).is_none() { - return Err(Error::InvalidStatus.into()); - } - - // Set user status - redis::cmd("HSET") - .arg(util_user_presence::key::user_presence(user_id)) - .arg(util_user_presence::key::user_presence::USER_ID) - .arg(user_id.to_string()) - .arg(util_user_presence::key::user_presence::UPDATE_TS) - .arg(ctx.ts()) - .arg(util_user_presence::key::user_presence::STATUS) - .arg(ctx.status) - .query_async::<_, ()>(&mut ctx.redis_user_presence().await?) - .await?; - - // Update the default status - if ctx.user_set_status { - sql_execute!( - [ctx] - " - UPSERT INTO db_user_presence.user_presences (user_id, user_set_status) - VALUES ($1, $2) - ", - user_id, - ctx.user_set_status, - ) - .await?; - } - - if !ctx.silent { - msg!([ctx] user_presence::msg::update(user_id) { - user_id: Some(user_id.into()), - update_ts: ctx.ts(), - kind: Some(user_presence::msg::update::message::Kind::Status(ctx.status)), - }) - .await?; - } - - Ok(()) -} diff --git a/svc/pkg/user-presence/worker/tests/arrive.rs b/svc/pkg/user-presence/worker/tests/arrive.rs deleted file mode 100644 index 1c0623fe31..0000000000 --- a/svc/pkg/user-presence/worker/tests/arrive.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::time::Duration; - -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; -use redis::AsyncCommands; - -#[worker_test] -async fn basic(ctx: TestCtx) { - let res = op!([ctx] faker_user {}).await.unwrap(); - let user_id = res.user_id.unwrap().as_uuid(); - - msg!([ctx] user_presence::msg::status_set(user_id) { - user_id: res.user_id, - status: backend::user::Status::Away as i32, - user_set_status: false, - silent: false, - }) - .await - .unwrap(); - - msg!([ctx] user_presence::msg::arrive(user_id) { - user_id: res.user_id, - silent: false, - }) - .await - .unwrap(); - - tokio::time::sleep(Duration::from_secs(1)).await; - - let mut redis = ctx.redis_user_presence().await.unwrap(); - let redis_status: i32 = redis - .hget( - util_user_presence::key::user_presence(user_id), - util_user_presence::key::user_presence::STATUS, - ) - .await - .unwrap(); - assert_eq!( - backend::user::Status::Online as i32, - redis_status, - "status did not reset to online" - ); -} diff --git a/svc/pkg/user-presence/worker/tests/game_activity_set.rs b/svc/pkg/user-presence/worker/tests/game_activity_set.rs deleted file mode 100644 index 3a4ba96a41..0000000000 --- a/svc/pkg/user-presence/worker/tests/game_activity_set.rs +++ /dev/null @@ -1,37 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; -use redis::AsyncCommands; - -#[worker_test] -async fn empty(ctx: TestCtx) { - let user_id = Uuid::new_v4(); - let game_id = Uuid::new_v4(); - - let mut user_presence_sub = subscribe!([ctx] user_presence::msg::update(user_id)) - .await - .unwrap(); - msg!([ctx] user_presence::msg::game_activity_set(user_id) { - user_id: Some(user_id.into()), - game_activity: Some(backend::user::presence::GameActivity { - game_id: Some(game_id.into()), - message: "".to_owned(), - public_metadata: None, - friend_metadata: None - }) - }) - .await - .unwrap(); - user_presence_sub.next().await.unwrap(); - - let mut redis = ctx.redis_user_presence().await.unwrap(); - let redis_game_id: Option = redis - .hget::<_, _, Option>( - util_user_presence::key::game_activity(user_id), - util_user_presence::key::game_activity::GAME_ID, - ) - .await - .unwrap() - .map(|x| util::uuid::parse(&x).unwrap()); - - assert_eq!(Some(game_id), redis_game_id); -} diff --git a/svc/pkg/user-presence/worker/tests/leave.rs b/svc/pkg/user-presence/worker/tests/leave.rs deleted file mode 100644 index e6c7deeca2..0000000000 --- a/svc/pkg/user-presence/worker/tests/leave.rs +++ /dev/null @@ -1,40 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; -use redis::AsyncCommands; - -#[worker_test] -async fn leave(ctx: TestCtx) { - let res = op!([ctx] faker_user {}).await.unwrap(); - let user_id = res.user_id.unwrap().as_uuid(); - - msg!([ctx] user_presence::msg::status_set(user_id) { - user_id: res.user_id, - status: backend::user::Status::Online as i32, - user_set_status: false, - silent: false, - }) - .await - .unwrap(); - - msg!([ctx] user_presence::msg::leave(user_id) -> user_presence::msg::update { - user_id: res.user_id, - }) - .await - .unwrap(); - - tokio::time::sleep(std::time::Duration::from_secs(3)).await; - - let mut redis = ctx.redis_user_presence().await.unwrap(); - let redis_status: i32 = redis - .hget( - util_user_presence::key::user_presence(user_id), - util_user_presence::key::user_presence::STATUS, - ) - .await - .unwrap(); - assert_eq!( - backend::user::Status::Offline as i32, - redis_status, - "status did not set to offline" - ); -} diff --git a/svc/pkg/user-presence/worker/tests/status_set.rs b/svc/pkg/user-presence/worker/tests/status_set.rs deleted file mode 100644 index 2a2c9fde17..0000000000 --- a/svc/pkg/user-presence/worker/tests/status_set.rs +++ /dev/null @@ -1,32 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; -use redis::AsyncCommands; - -#[worker_test] -async fn empty(ctx: TestCtx) { - let user_id = Uuid::new_v4(); - let status = backend::user::Status::Away; - - let mut user_presence_sub = subscribe!([ctx] user_presence::msg::update(user_id)) - .await - .unwrap(); - msg!([ctx] user_presence::msg::status_set(user_id) { - user_id: Some(user_id.into()), - status: status.into(), - user_set_status: false, - silent: false, - }) - .await - .unwrap(); - user_presence_sub.next().await.unwrap(); - - let mut redis = ctx.redis_user_presence().await.unwrap(); - let redis_status: i32 = redis - .hget( - util_user_presence::key::user_presence(user_id), - util_user_presence::key::user_presence::STATUS, - ) - .await - .unwrap(); - assert_eq!(status as i32, redis_status); -} diff --git a/svc/pkg/user/worker/src/workers/event_user_presence_update.rs b/svc/pkg/user/worker/src/workers/event_user_presence_update.rs deleted file mode 100644 index 53a98dff94..0000000000 --- a/svc/pkg/user/worker/src/workers/event_user_presence_update.rs +++ /dev/null @@ -1,20 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; -use rivet_convert::ApiInto; - -#[worker(name = "user-event-user-presence-update")] -async fn worker(ctx: &OperationContext) -> GlobalResult<()> { - let user_id = unwrap_ref!(ctx.user_id); - - msg!([ctx] user::msg::event(user_id) { - user_id: ctx.user_id, - event: Some(backend::user::event::Event { - kind: Some(backend::user::event::event::Kind::PresenceUpdate(backend::user::event::PresenceUpdate { - kind: ctx.kind.clone().map(ApiInto::api_into), - })), - }), - }) - .await?; - - Ok(()) -} diff --git a/svc/pkg/user/worker/src/workers/mod.rs b/svc/pkg/user/worker/src/workers/mod.rs index 4ad692dd35..b37bf405a6 100644 --- a/svc/pkg/user/worker/src/workers/mod.rs +++ b/svc/pkg/user/worker/src/workers/mod.rs @@ -3,7 +3,6 @@ mod create; mod delete; mod event_team_member_remove; mod event_user_mm_lobby_join; -mod event_user_presence_update; mod event_user_update; mod profile_set; mod search_update; @@ -11,7 +10,6 @@ mod search_update_user_follow_create; mod search_update_user_update; mod updated_user_follow_create; mod updated_user_follow_delete; -mod updated_user_presence_update; mod updated_user_update; chirp_worker::workers![ @@ -20,7 +18,6 @@ chirp_worker::workers![ delete, event_team_member_remove, event_user_mm_lobby_join, - event_user_presence_update, event_user_update, profile_set, search_update, @@ -28,6 +25,5 @@ chirp_worker::workers![ search_update_user_update, updated_user_follow_create, updated_user_follow_delete, - updated_user_presence_update, updated_user_update, ]; diff --git a/svc/pkg/user/worker/src/workers/updated_user_presence_update.rs b/svc/pkg/user/worker/src/workers/updated_user_presence_update.rs deleted file mode 100644 index 60624a54f7..0000000000 --- a/svc/pkg/user/worker/src/workers/updated_user_presence_update.rs +++ /dev/null @@ -1,20 +0,0 @@ -use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; -use rivet_convert::ApiInto; - -#[worker(name = "user-updated-user-presence-update")] -async fn worker(ctx: &OperationContext) -> GlobalResult<()> { - let user_id = unwrap_ref!(ctx.user_id); - - msg!([ctx] user::msg::updated(user_id) { - user_id: ctx.user_id, - update: Some(backend::user::update::Update { - kind: Some(backend::user::update::update::Kind::PresenceUpdate(backend::user::update::PresenceUpdate { - kind: ctx.kind.clone().map(ApiInto::api_into), - })), - }), - }) - .await?; - - Ok(()) -}