From 772a7d2ee0499e397e081e4a157751d1739bd11c Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 25 Mar 2026 00:45:03 +0100 Subject: [PATCH 1/5] Update steamworks-rs and add playtime tracking methods to client.d.ts --- Cargo.toml | 2 +- client.d.ts | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 396540a..dae62c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ napi = { version = "2.16.8", features = ["tokio_rt", "napi6", "serde-json"] } napi-derive = "2.16.9" lazy_static = "1" tokio = { version = "1", features = ["sync", "time"] } -steamworks = { git = "https://github.com/Noxime/steamworks-rs/", rev = "40a457a61f5ef714d93804e51e0c5e3d405145a3", features = ["serde"] } +steamworks = { git = "https://github.com/Noxime/steamworks-rs/", rev = "b1ec75c5156c905a00292aee0292e17ddb99ef7c", features = ["serde"] } serde = "1" serde_json = "1" diff --git a/client.d.ts b/client.d.ts index 2834978..9dbb2b4 100644 --- a/client.d.ts +++ b/client.d.ts @@ -600,4 +600,38 @@ export declare namespace workshop { export function getItems(items: Array, queryConfig?: WorkshopItemQueryConfig | undefined | null): Promise export function getAllItems(page: number, queryType: UGCQueryType, itemType: UGCType, creatorAppId: number, consumerAppId: number, queryConfig?: WorkshopItemQueryConfig | undefined | null): Promise export function getUserItems(page: number, accountId: number, listType: UserListType, itemType: UGCType, sortOrder: UserListOrder, appIds: AppIDs, queryConfig?: WorkshopItemQueryConfig | undefined | null): Promise + /** + * Start tracking playtime on a set of workshop items. + * + * When your app shuts down, playtime tracking will automatically stop. + * + * @param itemIds - The array of workshop items you want to start tracking. (Maximum of 100 items.) + * @returns Promise that resolves when the operation completes + * + * {@link https://partner.steamgames.com/doc/api/ISteamUGC#StartPlaytimeTracking} + */ + export function startPlaytimeTracking(itemIds: Array): Promise + /** + * Stop tracking playtime on a set of workshop items. + * + * This will increment the number of "playtime" sessions for those items by one. + * When your app shuts down, playtime tracking will automatically stop. + * + * @param itemIds - The array of workshop items you want to stop tracking. (Maximum of 100 items.) + * @returns Promise that resolves when the operation completes + * + * {@link https://partner.steamgames.com/doc/api/ISteamUGC#StopPlaytimeTracking} + */ + export function stopPlaytimeTracking(itemIds: Array): Promise + /** + * Stop tracking playtime of all workshop items. + * + * When your app shuts down, playtime tracking will automatically stop. + * This will increment the number of "playtime" sessions for all items that were being tracked by one. + * + * @returns Promise that resolves when the operation completes + * + * {@link https://partner.steamgames.com/doc/api/ISteamUGC#StopPlaytimeTrackingForAllItems} + */ + export function stopPlaytimeTrackingForAllItems(): Promise } From ac4ae3d97d58d8ed2b8419f5a79d88c90a472ccf Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 25 Mar 2026 00:45:23 +0100 Subject: [PATCH 2/5] chore: update steamworks and steamworks-sys to version 0.12.2 --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f562254..4276b99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -338,8 +338,8 @@ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "steamworks" -version = "0.12.1" -source = "git+https://github.com/Noxime/steamworks-rs/?rev=40a457a61f5ef714d93804e51e0c5e3d405145a3#40a457a61f5ef714d93804e51e0c5e3d405145a3" +version = "0.12.2" +source = "git+https://github.com/Noxime/steamworks-rs/?rev=b1ec75c5156c905a00292aee0292e17ddb99ef7c#b1ec75c5156c905a00292aee0292e17ddb99ef7c" dependencies = [ "bitflags", "paste", @@ -351,7 +351,7 @@ dependencies = [ [[package]] name = "steamworks-sys" version = "0.12.0" -source = "git+https://github.com/Noxime/steamworks-rs/?rev=40a457a61f5ef714d93804e51e0c5e3d405145a3#40a457a61f5ef714d93804e51e0c5e3d405145a3" +source = "git+https://github.com/Noxime/steamworks-rs/?rev=b1ec75c5156c905a00292aee0292e17ddb99ef7c#b1ec75c5156c905a00292aee0292e17ddb99ef7c" [[package]] name = "steamworksjs" diff --git a/Cargo.toml b/Cargo.toml index dae62c6..396540a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ napi = { version = "2.16.8", features = ["tokio_rt", "napi6", "serde-json"] } napi-derive = "2.16.9" lazy_static = "1" tokio = { version = "1", features = ["sync", "time"] } -steamworks = { git = "https://github.com/Noxime/steamworks-rs/", rev = "b1ec75c5156c905a00292aee0292e17ddb99ef7c", features = ["serde"] } +steamworks = { git = "https://github.com/Noxime/steamworks-rs/", rev = "40a457a61f5ef714d93804e51e0c5e3d405145a3", features = ["serde"] } serde = "1" serde_json = "1" From dc2fb6ec89d591b23bf5813112d1d3a19c233140 Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 25 Mar 2026 00:53:59 +0100 Subject: [PATCH 3/5] chore: downgrade steamworks to version 0.12.1 and update source reference --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4276b99..f562254 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -338,8 +338,8 @@ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "steamworks" -version = "0.12.2" -source = "git+https://github.com/Noxime/steamworks-rs/?rev=b1ec75c5156c905a00292aee0292e17ddb99ef7c#b1ec75c5156c905a00292aee0292e17ddb99ef7c" +version = "0.12.1" +source = "git+https://github.com/Noxime/steamworks-rs/?rev=40a457a61f5ef714d93804e51e0c5e3d405145a3#40a457a61f5ef714d93804e51e0c5e3d405145a3" dependencies = [ "bitflags", "paste", @@ -351,7 +351,7 @@ dependencies = [ [[package]] name = "steamworks-sys" version = "0.12.0" -source = "git+https://github.com/Noxime/steamworks-rs/?rev=b1ec75c5156c905a00292aee0292e17ddb99ef7c#b1ec75c5156c905a00292aee0292e17ddb99ef7c" +source = "git+https://github.com/Noxime/steamworks-rs/?rev=40a457a61f5ef714d93804e51e0c5e3d405145a3#40a457a61f5ef714d93804e51e0c5e3d405145a3" [[package]] name = "steamworksjs" From adfcb4cef2b0d986935ef155100784f7f6a675f7 Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 25 Mar 2026 01:25:12 +0100 Subject: [PATCH 4/5] feat(api): update steamworks version to 0.12.2 and add playtime tracking methods Fixed a few issues, WIP testing with a fork of steamworks-rs --- Cargo.lock | 4 +- Cargo.toml | 2 +- src/api/friends.rs | 1 + src/api/workshop.rs | 229 ++++++++++++++++++++++---------------------- 4 files changed, 115 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f562254..a107b04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -338,8 +338,7 @@ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "steamworks" -version = "0.12.1" -source = "git+https://github.com/Noxime/steamworks-rs/?rev=40a457a61f5ef714d93804e51e0c5e3d405145a3#40a457a61f5ef714d93804e51e0c5e3d405145a3" +version = "0.12.2" dependencies = [ "bitflags", "paste", @@ -351,7 +350,6 @@ dependencies = [ [[package]] name = "steamworks-sys" version = "0.12.0" -source = "git+https://github.com/Noxime/steamworks-rs/?rev=40a457a61f5ef714d93804e51e0c5e3d405145a3#40a457a61f5ef714d93804e51e0c5e3d405145a3" [[package]] name = "steamworksjs" diff --git a/Cargo.toml b/Cargo.toml index 396540a..ae50358 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ napi = { version = "2.16.8", features = ["tokio_rt", "napi6", "serde-json"] } napi-derive = "2.16.9" lazy_static = "1" tokio = { version = "1", features = ["sync", "time"] } -steamworks = { git = "https://github.com/Noxime/steamworks-rs/", rev = "40a457a61f5ef714d93804e51e0c5e3d405145a3", features = ["serde"] } +steamworks = { path = "../steamworks-rs", features = ["serde"] } serde = "1" serde_json = "1" diff --git a/src/api/friends.rs b/src/api/friends.rs index 6927430..38acbac 100644 --- a/src/api/friends.rs +++ b/src/api/friends.rs @@ -78,6 +78,7 @@ pub mod friends { steamworks::FriendState::Snooze => PersonaState::Snooze, steamworks::FriendState::LookingToTrade => PersonaState::LookingToTrade, steamworks::FriendState::LookingToPlay => PersonaState::LookingToPlay, + steamworks::FriendState::Invisible => PersonaState::Invisible, }, game_played: f.game_played().map(|g| FriendGameInfo { game_id: BigInt::from(g.game.raw()), diff --git a/src/api/workshop.rs b/src/api/workshop.rs index b7e9108..245525a 100644 --- a/src/api/workshop.rs +++ b/src/api/workshop.rs @@ -424,121 +424,116 @@ pub mod workshop { } } - // TODO: Uncomment these methods once the steamworks-rs PR is merged - // PR: https://github.com/Noxime/steamworks-rs/pull/297 - // These methods require start_playtime_tracking, stop_playtime_tracking, and - // stop_playtime_tracking_for_all_items to be added to the steamworks-rs UGC API - - // /// Start tracking playtime on a set of workshop items. - // /// - // /// When your app shuts down, playtime tracking will automatically stop. - // /// - // /// @param itemIds - The array of workshop items you want to start tracking. (Maximum of 100 items.) - // /// @returns Promise that resolves when the operation completes - // /// - // /// {@link https://partner.steamgames.com/doc/api/ISteamUGC#StartPlaytimeTracking} - // #[napi] - // pub async fn start_playtime_tracking(item_ids: Vec) -> Result<(), Error> { - // if item_ids.is_empty() { - // return Err(Error::from_reason( - // "item_ids must contain at least 1 item".to_string(), - // )); - // } - // - // if item_ids.len() > 100 { - // return Err(Error::from_reason( - // "item_ids must not contain more than 100 items".to_string(), - // )); - // } - // - // let client = crate::client::get_client(); - // let (tx, rx) = oneshot::channel(); - // - // let published_file_ids: Vec = item_ids - // .iter() - // .map(|id| PublishedFileId(id.get_u64().1)) - // .collect(); - // - // client - // .ugc() - // .start_playtime_tracking(&published_file_ids, |result| { - // tx.send(result).unwrap(); - // }); - // - // let result = rx.await.unwrap(); - // match result { - // Ok(()) => Ok(()), - // Err(e) => Err(Error::from_reason(e.to_string())), - // } - // } - - // /// Stop tracking playtime on a set of workshop items. - // /// - // /// This will increment the number of "playtime" sessions for those items by one. - // /// When your app shuts down, playtime tracking will automatically stop. - // /// - // /// @param itemIds - The array of workshop items you want to stop tracking. (Maximum of 100 items.) - // /// @returns Promise that resolves when the operation completes - // /// - // /// {@link https://partner.steamgames.com/doc/api/ISteamUGC#StopPlaytimeTracking} - // #[napi] - // pub async fn stop_playtime_tracking(item_ids: Vec) -> Result<(), Error> { - // if item_ids.is_empty() { - // return Err(Error::from_reason( - // "item_ids must contain at least 1 item".to_string(), - // )); - // } - // - // if item_ids.len() > 100 { - // return Err(Error::from_reason( - // "item_ids must not contain more than 100 items".to_string(), - // )); - // } - // - // let client = crate::client::get_client(); - // let (tx, rx) = oneshot::channel(); - // - // let published_file_ids: Vec = item_ids - // .iter() - // .map(|id| PublishedFileId(id.get_u64().1)) - // .collect(); - // - // client - // .ugc() - // .stop_playtime_tracking(&published_file_ids, |result| { - // tx.send(result).unwrap(); - // }); - // - // let result = rx.await.unwrap(); - // match result { - // Ok(()) => Ok(()), - // Err(e) => Err(Error::from_reason(e.to_string())), - // } - // } - - // /// Stop tracking playtime of all workshop items. - // /// - // /// When your app shuts down, playtime tracking will automatically stop. - // /// This will increment the number of "playtime" sessions for all items that were being tracked by one. - // /// - // /// @returns Promise that resolves when the operation completes - // /// - // /// {@link https://partner.steamgames.com/doc/api/ISteamUGC#StopPlaytimeTrackingForAllItems} - // #[napi] - // pub async fn stop_playtime_tracking_for_all_items() -> Result<(), Error> { - // let client = crate::client::get_client(); - // let (tx, rx) = oneshot::channel(); - // - // client - // .ugc() - // .stop_playtime_tracking_for_all_items(|result| { - // tx.send(result).unwrap(); - // }); - // - // let result = rx.await.unwrap(); - // match result { - // Ok(()) => Ok(()), - // Err(e) => Err(Error::from_reason(e.to_string())), - // } - // } + /// Start tracking playtime on a set of workshop items. + /// + /// When your app shuts down, playtime tracking will automatically stop. + /// + /// @param itemIds - The array of workshop items you want to start tracking. (Maximum of 100 items.) + /// @returns Promise that resolves when the operation completes + /// + /// {@link https://partner.steamgames.com/doc/api/ISteamUGC#StartPlaytimeTracking} + #[napi] + pub async fn start_playtime_tracking(item_ids: Vec) -> Result<(), Error> { + if item_ids.is_empty() { + return Err(Error::from_reason( + "item_ids must contain at least 1 item".to_string(), + )); + } + + if item_ids.len() > 100 { + return Err(Error::from_reason( + "item_ids must not contain more than 100 items".to_string(), + )); + } + + let client = crate::client::get_client(); + let (tx, rx) = oneshot::channel(); + + let published_file_ids: Vec = item_ids + .iter() + .map(|id| PublishedFileId(id.get_u64().1)) + .collect(); + + client + .ugc() + .start_playtime_tracking(&published_file_ids, |result| { + tx.send(result).unwrap(); + }); + + let result = rx.await.unwrap(); + match result { + Ok(()) => Ok(()), + Err(e) => Err(Error::from_reason(e.to_string())), + } + } + + /// Stop tracking playtime on a set of workshop items. + /// + /// This will increment the number of "playtime" sessions for those items by one. + /// When your app shuts down, playtime tracking will automatically stop. + /// + /// @param itemIds - The array of workshop items you want to stop tracking. (Maximum of 100 items.) + /// @returns Promise that resolves when the operation completes + /// + /// {@link https://partner.steamgames.com/doc/api/ISteamUGC#StopPlaytimeTracking} + #[napi] + pub async fn stop_playtime_tracking(item_ids: Vec) -> Result<(), Error> { + if item_ids.is_empty() { + return Err(Error::from_reason( + "item_ids must contain at least 1 item".to_string(), + )); + } + + if item_ids.len() > 100 { + return Err(Error::from_reason( + "item_ids must not contain more than 100 items".to_string(), + )); + } + + let client = crate::client::get_client(); + let (tx, rx) = oneshot::channel(); + + let published_file_ids: Vec = item_ids + .iter() + .map(|id| PublishedFileId(id.get_u64().1)) + .collect(); + + client + .ugc() + .stop_playtime_tracking(&published_file_ids, |result| { + tx.send(result).unwrap(); + }); + + let result = rx.await.unwrap(); + match result { + Ok(()) => Ok(()), + Err(e) => Err(Error::from_reason(e.to_string())), + } + } + + /// Stop tracking playtime of all workshop items. + /// + /// When your app shuts down, playtime tracking will automatically stop. + /// This will increment the number of "playtime" sessions for all items that were being tracked by one. + /// + /// @returns Promise that resolves when the operation completes + /// + /// {@link https://partner.steamgames.com/doc/api/ISteamUGC#StopPlaytimeTrackingForAllItems} + #[napi] + pub async fn stop_playtime_tracking_for_all_items() -> Result<(), Error> { + let client = crate::client::get_client(); + let (tx, rx) = oneshot::channel(); + + client + .ugc() + .stop_playtime_tracking_for_all_items(|result| { + tx.send(result).unwrap(); + }); + + let result = rx.await.unwrap(); + match result { + Ok(()) => Ok(()), + Err(e) => Err(Error::from_reason(e.to_string())), + } + } } From 99c440dff6d8eacb4f8a2651f3346f8718614584 Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 25 Mar 2026 01:25:20 +0100 Subject: [PATCH 5/5] formatting --- src/api/workshop.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/api/workshop.rs b/src/api/workshop.rs index 245525a..71228ab 100644 --- a/src/api/workshop.rs +++ b/src/api/workshop.rs @@ -524,11 +524,9 @@ pub mod workshop { let client = crate::client::get_client(); let (tx, rx) = oneshot::channel(); - client - .ugc() - .stop_playtime_tracking_for_all_items(|result| { - tx.send(result).unwrap(); - }); + client.ugc().stop_playtime_tracking_for_all_items(|result| { + tx.send(result).unwrap(); + }); let result = rx.await.unwrap(); match result {