diff --git a/build.gradle.kts b/build.gradle.kts index 74bba141..6729d2ed 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,7 +18,7 @@ plugins { allprojects { group = "in.dragonbra" - version = "1.6.0" + version = "1.6.1-SNAPSHOT" } repositories { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6310548f..442d8d67 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,30 +6,30 @@ [versions] # Java / Kotlin versions java = "11" -kotlin = "2.1.0" # https://kotlinlang.org/docs/releases.html#release-details +kotlin = "2.1.10" # https://kotlinlang.org/docs/releases.html#release-details dokka = "2.0.0" # https://mvnrepository.com/artifact/org.jetbrains.dokka/dokka-gradle-plugin kotlinter = "5.0.1" # https://plugins.gradle.org/plugin/org.jmailen.kotlinter # Standard Library versions -bouncyCastle = "1.79" # https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk18on +bouncyCastle = "1.80" # https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk18on commons-io = "2.18.0" # https://mvnrepository.com/artifact/commons-io/commons-io commons-lang3 = "3.17.0" # https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 commons-validator = "1.9.0" # https://mvnrepository.com/artifact/commons-validator/commons-validator -gson = "2.11.0" # https://mvnrepository.com/artifact/com.google.code.gson/gson +gson = "2.12.1" # https://mvnrepository.com/artifact/com.google.code.gson/gson jacoco = "0.8.12" # https://www.eclemma.org/jacoco kotlin-coroutines = "1.10.1" # https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core okHttp = "5.0.0-alpha.14" # https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -protobuf = "4.29.2" # https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java +protobuf = "4.29.3" # https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java protobuf-gradle = "0.9.4" # https://mvnrepository.com/artifact/com.google.protobuf/protobuf-gradle-plugin publishPlugin = "1.3.0" # https://mvnrepository.com/artifact/io.github.gradle-nexus/publish-plugin qrCode = "1.0.1" # https://mvnrepository.com/artifact/pro.leaco.qrcode/console-qrcode xz = "1.10" # https://mvnrepository.com/artifact/org.tukaani/xz # Testing Lib versions -commonsCodec = "1.17.1" # https://mvnrepository.com/artifact/commons-codec/commons-codec +commonsCodec = "1.18.0" # https://mvnrepository.com/artifact/commons-codec/commons-codec junit5 = "5.11.4" # https://mvnrepository.com/artifact/org.junit/junit-bom mockWebServer = "5.0.0-alpha.14" # https://mvnrepository.com/artifact/com.squareup.okhttp3/mockwebserver3-junit5 -mockitoVersion = "5.14.2" # https://mvnrepository.com/artifact/org.mockito/mockito-core +mockitoVersion = "5.15.2" # https://mvnrepository.com/artifact/org.mockito/mockito-core [libraries] bouncyCastle = { module = "org.bouncycastle:bcprov-jdk18on", version.ref = "bouncyCastle" } diff --git a/javasteam-samples/src/main/java/in/dragonbra/javasteamsamples/_020_friends/SampleFriends.java b/javasteam-samples/src/main/java/in/dragonbra/javasteamsamples/_020_friends/SampleFriends.java index 136e827f..985168c5 100644 --- a/javasteam-samples/src/main/java/in/dragonbra/javasteamsamples/_020_friends/SampleFriends.java +++ b/javasteam-samples/src/main/java/in/dragonbra/javasteamsamples/_020_friends/SampleFriends.java @@ -7,7 +7,7 @@ import in.dragonbra.javasteam.steam.handlers.steamfriends.SteamFriends; import in.dragonbra.javasteam.steam.handlers.steamfriends.callback.FriendAddedCallback; import in.dragonbra.javasteam.steam.handlers.steamfriends.callback.FriendsListCallback; -import in.dragonbra.javasteam.steam.handlers.steamfriends.callback.PersonaStatesCallback; +import in.dragonbra.javasteam.steam.handlers.steamfriends.callback.PersonaStateCallback; import in.dragonbra.javasteam.steam.handlers.steamuser.LogOnDetails; import in.dragonbra.javasteam.steam.handlers.steamuser.SteamUser; import in.dragonbra.javasteam.steam.handlers.steamuser.callback.AccountInfoCallback; @@ -88,7 +88,7 @@ public void run() { manager.subscribe(AccountInfoCallback.class, this::onAccountInfo); manager.subscribe(FriendsListCallback.class, this::onFriendList); - manager.subscribe(PersonaStatesCallback.class, this::onPersonaStates); + manager.subscribe(PersonaStateCallback.class, this::onPersonaState); manager.subscribe(FriendAddedCallback.class, this::onFriendAdded); isRunning = true; @@ -203,10 +203,10 @@ private void onFriendAdded(FriendAddedCallback callback) { System.out.println(callback.getPersonaName() + " is now a friend"); } - private void onPersonaStates(PersonaStatesCallback callback) { + private void onPersonaState(PersonaStateCallback callback) { // this callback is received when the persona state (friend information) of a friend changes // for this sample we'll simply display the names of the friends - System.out.println("State change: " + callback.getName() + " " + callback.getState()); + System.out.println("State change: " + callback.getName() + " | " + callback.getState() + " | " + callback.getStatusFlags()); } } diff --git a/src/main/java/in/dragonbra/javasteam/steam/authentication/AuthSessionDetails.kt b/src/main/java/in/dragonbra/javasteam/steam/authentication/AuthSessionDetails.kt index 8c27cac6..5688ebcf 100644 --- a/src/main/java/in/dragonbra/javasteam/steam/authentication/AuthSessionDetails.kt +++ b/src/main/java/in/dragonbra/javasteam/steam/authentication/AuthSessionDetails.kt @@ -2,6 +2,7 @@ package `in`.dragonbra.javasteam.steam.authentication import `in`.dragonbra.javasteam.enums.EOSType import `in`.dragonbra.javasteam.protobufs.steamclient.SteammessagesAuthSteamclient.EAuthTokenPlatformType +import `in`.dragonbra.javasteam.util.HardwareUtils import `in`.dragonbra.javasteam.util.Utils /** @@ -23,7 +24,8 @@ class AuthSessionDetails { /** * Gets or Sets the device name (or user agent). By default, "(JavaSteam)" will be used. */ - var deviceFriendlyName: String? + @JvmField + var deviceFriendlyName: String? = HardwareUtils.getMachineName(true) /** * Gets or sets the platform type that the login will be performed for. @@ -62,9 +64,4 @@ class AuthSessionDetails { */ @JvmField var authenticator: IAuthenticator? = null - - init { - val machineName = System.getenv("COMPUTERNAME") ?: System.getenv("HOSTNAME") - deviceFriendlyName = "$machineName (JavaSteam)" - } } diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriends.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriends.kt index 4c09b2a5..fe7c555b 100644 --- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriends.kt +++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriends.kt @@ -56,7 +56,7 @@ import `in`.dragonbra.javasteam.steam.handlers.steamfriends.callback.IgnoreFrien import `in`.dragonbra.javasteam.steam.handlers.steamfriends.callback.NicknameCallback import `in`.dragonbra.javasteam.steam.handlers.steamfriends.callback.NicknameListCallback import `in`.dragonbra.javasteam.steam.handlers.steamfriends.callback.PersonaChangeCallback -import `in`.dragonbra.javasteam.steam.handlers.steamfriends.callback.PersonaStatesCallback +import `in`.dragonbra.javasteam.steam.handlers.steamfriends.callback.PersonaStateCallback import `in`.dragonbra.javasteam.steam.handlers.steamfriends.callback.ProfileInfoCallback import `in`.dragonbra.javasteam.steam.handlers.steamuser.callback.AccountInfoCallback import `in`.dragonbra.javasteam.steam.steamclient.callbackmgr.CallbackMsg @@ -530,7 +530,7 @@ class SteamFriends : ClientMsgHandler() { /** * Requests persona state for a list of specified SteamID. - * Results are returned in [PersonaStatesCallback]. + * Results are returned in [PersonaStateCallback]. * * @param steamIdList A list of SteamIDs to request the info of. * @param requestedInfo The requested info flags. If none specified, this uses [SteamConfiguration.defaultPersonaStateFlags]. @@ -554,7 +554,7 @@ class SteamFriends : ClientMsgHandler() { /** * Requests persona state for a specified SteamID. - * Results are returned in [PersonaStatesCallback]. + * Results are returned in [PersonaStateCallback]. * * @param steamID A SteamID to request the info of. * @param requestedInfo The requested info flags. If none specified, this uses [SteamConfiguration.defaultPersonaStateFlags]. @@ -781,7 +781,7 @@ class SteamFriends : ClientMsgHandler() { } perState.body.friendsList.forEach { friend -> - PersonaStatesCallback(friend).also(client::postCallback) + PersonaStateCallback(friend, flags).also(client::postCallback) } } diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/callback/PersonaStatesCallback.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/callback/PersonaStateCallback.kt similarity index 90% rename from src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/callback/PersonaStatesCallback.kt rename to src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/callback/PersonaStateCallback.kt index 1c057c07..9f863c26 100644 --- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/callback/PersonaStatesCallback.kt +++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamfriends/callback/PersonaStateCallback.kt @@ -14,13 +14,16 @@ import java.util.* /** * This callback is fired in response to someone changing their friend details over the network. */ -@Suppress("unused") -class PersonaStatesCallback(friend: CMsgClientPersonaState.Friend) : CallbackMsg() { +@Suppress("unused", "CanBePrimaryConstructorProperty") +class PersonaStateCallback( + friend: CMsgClientPersonaState.Friend, + statusFlags: EnumSet, +) : CallbackMsg() { /** * Gets the status flags. This shows what has changed. */ - val statusFlags: EnumSet = EClientPersonaStateFlag.from(friend.personaStateFlags) + val statusFlags: EnumSet = statusFlags /** * Gets the friend's [SteamID] diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/LogOnDetails.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/LogOnDetails.kt index 9888e4bf..a45387ee 100644 --- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/LogOnDetails.kt +++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/LogOnDetails.kt @@ -5,6 +5,7 @@ import `in`.dragonbra.javasteam.enums.EUIMode import `in`.dragonbra.javasteam.steam.authentication.AuthSessionDetails import `in`.dragonbra.javasteam.steam.authentication.SteamAuthentication import `in`.dragonbra.javasteam.types.SteamID +import `in`.dragonbra.javasteam.util.HardwareUtils import `in`.dragonbra.javasteam.util.Utils /** @@ -48,16 +49,8 @@ data class LogOnDetails( var requestSteam2Ticket: Boolean = false, var clientOSType: EOSType = Utils.getOSType(), var clientLanguage: String = "english", - var machineName: String = "", + var machineName: String = HardwareUtils.getMachineName(true), var chatMode: ChatMode = ChatMode.DEFAULT, var uiMode: EUIMode = EUIMode.Unknown, var isSteamDeck: Boolean = false, -) { - init { - var envName = System.getenv("COMPUTERNAME") - if (envName == null) { - envName = System.getenv("HOSTNAME") - } - machineName = "$envName (JavaSteam)" - } -} +) diff --git a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/callback/LoggedOnCallback.kt b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/callback/LoggedOnCallback.kt index a2c40331..dc719d8a 100644 --- a/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/callback/LoggedOnCallback.kt +++ b/src/main/java/in/dragonbra/javasteam/steam/handlers/steamuser/callback/LoggedOnCallback.kt @@ -130,6 +130,12 @@ class LoggedOnCallback : CallbackMsg { */ var parentalSettings: ParentalSettings? = null + /** + * Gets the id of the family group a user is joined in. + */ + var familyGroupId: Long = 0L + private set + constructor(packetMsg: IPacketMsg) { if (!packetMsg.isProto) { handleNonProtoLogon(packetMsg) @@ -177,6 +183,8 @@ class LoggedOnCallback : CallbackMsg { logger.error("Failed to parse parental settings", e) } } + + familyGroupId = resp.familyGroupId } constructor(result: EResult) { diff --git a/src/main/java/in/dragonbra/javasteam/types/AsyncJobMultiple.kt b/src/main/java/in/dragonbra/javasteam/types/AsyncJobMultiple.kt index fc4292fe..36fb7d95 100644 --- a/src/main/java/in/dragonbra/javasteam/types/AsyncJobMultiple.kt +++ b/src/main/java/in/dragonbra/javasteam/types/AsyncJobMultiple.kt @@ -18,13 +18,13 @@ class AsyncJobMultiple( private val finishCondition: (T) -> Boolean?, ) : AsyncJob(client, jobId) { - class ResultSet( + class ResultSet( var complete: Boolean = false, var failed: Boolean = false, - var results: List = listOf(), + var results: List = listOf(), ) - private val future = CompletableFuture() + private val future = CompletableFuture>() private val results = mutableListOf() @@ -33,15 +33,15 @@ class AsyncJobMultiple( } @Deprecated("Use toFuture() instead", ReplaceWith("toFuture()")) - fun toDeferred(): CompletableFuture = toFuture() + fun toDeferred(): CompletableFuture> = toFuture() - fun toFuture(): CompletableFuture = future + fun toFuture(): CompletableFuture> = future - suspend fun await(): ResultSet = future.await() + suspend fun await(): ResultSet = future.await() @Suppress("unused") @Throws(CancellationException::class) - fun runBlock(): ResultSet = toFuture().get() + fun runBlock(): ResultSet = toFuture().get() override fun addResult(callback: CallbackMsg): Boolean { @Suppress("UNCHECKED_CAST") diff --git a/src/main/java/in/dragonbra/javasteam/util/HardwareUtils.java b/src/main/java/in/dragonbra/javasteam/util/HardwareUtils.java index fa1e766f..0c71d162 100644 --- a/src/main/java/in/dragonbra/javasteam/util/HardwareUtils.java +++ b/src/main/java/in/dragonbra/javasteam/util/HardwareUtils.java @@ -1,9 +1,12 @@ package in.dragonbra.javasteam.util; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import java.io.*; import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Scanner; /** @@ -191,34 +194,44 @@ private static String readLshal() { } public static String getMachineName() { + return getMachineName(false); + } + + public static String getMachineName(boolean addTag) { if (MACHINE_NAME != null) { return MACHINE_NAME; } + if (SystemUtils.IS_OS_ANDROID) { MACHINE_NAME = getAndroidDeviceName(); } else { MACHINE_NAME = getDeviceName(); } - if (MACHINE_NAME == null || MACHINE_NAME.isEmpty()) { + if (StringUtils.isBlank(MACHINE_NAME)) { MACHINE_NAME = "Unknown"; } - return MACHINE_NAME; + if (addTag || MACHINE_NAME.contains("Unknown")) { + return MACHINE_NAME + " (JavaSteam)"; + } else { + return MACHINE_NAME; + } } private static String getDeviceName() { - try { - Process process = Runtime.getRuntime().exec("hostname"); - - try (var inputStreamReader = new InputStreamReader(process.getInputStream()); - var reader = new BufferedReader(inputStreamReader)) { - return reader.readLine().trim(); + var hostname = SystemUtils.getHostName(); + if (StringUtils.isBlank(hostname)) { + try { + // Last fallback. + hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + hostname = null; } - } catch (IOException e) { - return null; } + + return hostname; } private static String getAndroidDeviceName() { diff --git a/src/main/java/in/dragonbra/javasteam/util/Utils.java b/src/main/java/in/dragonbra/javasteam/util/Utils.java index 6e90385b..8c9a1406 100644 --- a/src/main/java/in/dragonbra/javasteam/util/Utils.java +++ b/src/main/java/in/dragonbra/javasteam/util/Utils.java @@ -210,11 +210,12 @@ public static int adlerHash(byte[] input) { /** * Validate a file against Steam3 Chunk data - * @param fs FileInputStream to read from + * + * @param fs FileInputStream to read from * @param chunkData Array of ChunkData to validate against * @return List of ChunkData that are needed - * @throws IOException If there's an error reading the file - * @throws ClosedChannelException If this channel is closed + * @throws IOException If there's an error reading the file + * @throws ClosedChannelException If this channel is closed * @throws IllegalArgumentException If the new position is negative */ @SuppressWarnings("resource") diff --git a/src/main/proto/in/dragonbra/javasteam/protobufs/steamclient/steammessages_familygroups.steamclient.proto b/src/main/proto/in/dragonbra/javasteam/protobufs/steamclient/steammessages_familygroups.steamclient.proto new file mode 100644 index 00000000..6fa0c52d --- /dev/null +++ b/src/main/proto/in/dragonbra/javasteam/protobufs/steamclient/steammessages_familygroups.steamclient.proto @@ -0,0 +1,477 @@ +import "in/dragonbra/javasteam/protobufs/steamclient/steammessages_base.proto"; +import "in/dragonbra/javasteam/protobufs/steamclient/steammessages_unified_base.steamclient.proto"; +import "in/dragonbra/javasteam/protobufs/steamclient/enums.proto"; + +option java_package = "in.dragonbra.javasteam.protobufs.steamclient"; + +option optimize_for = SPEED; +option java_generic_services = false; + +enum EFamilyGroupRole { + k_EFamilyGroupRole_None = 0; + k_EFamilyGroupRole_Adult = 1; + k_EFamilyGroupRole_Child = 2; + k_EFamilyGroupRole_MAX = 3; +} + +enum EFamilyGroupsTwoFactorMethod { + k_EFamilyGroupsTwoFactorMethodNone = 0; + k_EFamilyGroupsTwoFactorMethodMobile = 1; + k_EFamilyGroupsTwoFactorMethodEmail = 2; +} + +enum EPurchaseRequestAction { + k_EPurchaseRequestAction_None = 0; + k_EPurchaseRequestAction_Decline = 1; + k_EPurchaseRequestAction_Purchased = 2; + k_EPurchaseRequestAction_Abandoned = 3; + k_EPurchaseRequestAction_Cancel = 4; + k_EPurchaseRequestAction_MAX = 5; +} + +enum EFamilyGroupChangeLogType { + k_InvalidChangeType = 0; + k_FamilyGroupCreated = 1; + k_FamilyGroupModified = 2; + k_FamilyGroupDeleted = 3; + k_AccountInvited = 4; + k_InviteDeniedByGroupSize = 5; + k_JoinedFamilyGroup = 6; + k_JoinDeniedByRegionMismatch = 7; + k_JoinDeniedByMissingIpAddress = 8; + k_JoinDeniedByFamilyCooldown = 9; + k_JoinDeniedByUserCooldown = 10; + k_JoinDeniedByOtherGroup = 11; + k_AccountRemoved = 12; + k_InviteCanceled = 13; + k_PurchaseRequested = 14; + k_ParentalSettingsEnabled = 15; + k_ParentalSettingsDisabled = 16; + k_ParentalSettingsChanged = 17; + k_FamilyCooldownOverridesChanged = 18; + k_PurchaseRequestCanceled = 19; + k_PurchaseRequestApproved = 20; + k_PurchaseRequestDeclined = 21; + k_CooldownSkipConsumed = 22; + k_FamilyGroupRestored = 23; + k_JoinDenied = 24; + k_SupportForceAcceptedInvite = 25; +} + +enum ESharedLibraryExcludeReason { + k_ESharedLibrary_Included = 0; + k_ESharedLibrary_AppExcluded_ByPartner = 1; + k_ESharedLibrary_LicenseExcluded = 2; + k_ESharedLibrary_FreeGame = 3; + k_ESharedLibrary_LicensePrivate = 4; + k_ESharedLibrary_AppExcluded_WrongAppType = 6; + k_ESharedLibrary_AppExcluded_NonrefundableDLC = 7; + k_ESharedLibrary_AppExcluded_UnreleasedApp = 8; + k_ESharedLibrary_AppExcluded_ParentAppExcluded = 9; + k_ESharedLibrary_PackageExcluded_ByPartner = 10; + k_ESharedLibrary_PackageExcluded_Special = 11; + k_ESharedLibrary_PackageExcluded_Dev = 12; + k_ESharedLibrary_PackageExcluded_FreeWeekend = 13; + k_ESharedLibrary_PackageExcluded_Invalid = 15; + k_ESharedLibrary_PackageExcluded_RecurringLicense = 16; + k_ESharedLibrary_PackageExcluded_WrongLicenseType = 17; + k_ESharedLibrary_PackageExcluded_MasterSub = 18; + k_ESharedLibrary_PackageExcluded_NoShareableApps = 19; + k_ESharedLibrary_LicenseExcluded_PaymentMasterSub = 20; + k_ESharedLibrary_LicenseExcluded_PaymentFamilyGroup = 21; + k_ESharedLibrary_LicenseExcluded_PaymentAuthorizedDevice = 22; + k_ESharedLibrary_LicenseExcluded_PaymentAutoGrant = 23; + k_ESharedLibrary_LicenseExcluded_FlagPending = 24; + k_ESharedLibrary_LicenseExcluded_FlagPendingRefund = 25; + k_ESharedLibrary_LicenseExcluded_FlagBorrowed = 26; + k_ESharedLibrary_LicenseExcluded_FlagAutoGrant = 27; + k_ESharedLibrary_LicenseExcluded_FlagTimedTrial = 28; + k_ESharedLibrary_LicenseExcluded_FreeSub = 29; + k_ESharedLibrary_LicenseExcluded_Inactive = 30; +} + +message CFamilyGroups_CreateFamilyGroup_Request { + optional string name = 1; + optional fixed64 steamid = 2; +} + +message CFamilyGroups_CreateFamilyGroup_Response { + optional uint64 family_groupid = 1; + optional bool cooldown_skip_granted = 2; +} + +message CFamilyGroups_GetFamilyGroup_Request { + optional uint64 family_groupid = 1; + optional bool send_running_apps = 2; +} + +message FamilyGroupMember { + optional fixed64 steamid = 1; + optional .EFamilyGroupRole role = 2 [default = k_EFamilyGroupRole_None]; + optional uint32 time_joined = 3; + optional uint32 cooldown_seconds_remaining = 4; +} + +message FamilyGroupPendingInvite { + optional fixed64 steamid = 1; + optional .EFamilyGroupRole role = 2 [default = k_EFamilyGroupRole_None]; +} + +message FamilyGroupFormerMember { + optional fixed64 steamid = 1; +} + +message CFamilyGroups_GetFamilyGroup_Response { + optional string name = 1; + repeated .FamilyGroupMember members = 2; + repeated .FamilyGroupPendingInvite pending_invites = 3; + optional uint32 free_spots = 4; + optional string country = 5; + optional uint32 slot_cooldown_remaining_seconds = 6; + repeated .FamilyGroupFormerMember former_members = 7; + optional uint32 slot_cooldown_overrides = 8; +} + +message CFamilyGroups_GetFamilyGroupForUser_Request { + optional uint64 steamid = 1; + optional bool include_family_group_response = 2; +} + +message FamilyGroupPendingInviteForUser { + optional uint64 family_groupid = 1; + optional .EFamilyGroupRole role = 2 [default = k_EFamilyGroupRole_None]; + optional fixed64 inviter_steamid = 3; + optional bool awaiting_2fa = 4; +} + +message CFamilyGroups_GetFamilyGroupForUser_Response { + optional uint64 family_groupid = 1; + optional bool is_not_member_of_any_group = 2; + optional uint32 latest_time_joined = 3; + optional uint64 latest_joined_family_groupid = 4; + repeated .FamilyGroupPendingInviteForUser pending_group_invites = 5; + optional uint32 role = 6; + optional uint32 cooldown_seconds_remaining = 7; + optional .CFamilyGroups_GetFamilyGroup_Response family_group = 8; + optional bool can_undelete_last_joined_family = 9; +} + +message CFamilyGroups_ModifyFamilyGroupDetails_Request { + optional uint64 family_groupid = 1; + optional string name = 2; +} + +message CFamilyGroups_ModifyFamilyGroupDetails_Response { +} + +message CFamilyGroups_InviteToFamilyGroup_Request { + optional uint64 family_groupid = 1; + optional fixed64 receiver_steamid = 2; + optional .EFamilyGroupRole receiver_role = 3 [default = k_EFamilyGroupRole_None]; +} + +message CFamilyGroups_InviteToFamilyGroup_Response { + optional uint64 invite_id = 1; + optional .EFamilyGroupsTwoFactorMethod two_factor_method = 2 [default = k_EFamilyGroupsTwoFactorMethodNone]; +} + +message CFamilyGroups_ConfirmInviteToFamilyGroup_Request { + optional uint64 family_groupid = 1; + optional uint64 invite_id = 2; + optional uint64 nonce = 3; +} + +message CFamilyGroups_ConfirmInviteToFamilyGroup_Response { +} + +message CFamilyGroups_ResendInvitationToFamilyGroup_Request { + optional uint64 family_groupid = 1; + optional uint64 steamid = 2; +} + +message CFamilyGroups_ResendInvitationToFamilyGroup_Response { +} + +message CFamilyGroups_JoinFamilyGroup_Request { + optional uint64 family_groupid = 1; + optional uint64 nonce = 2; +} + +message CFamilyGroups_JoinFamilyGroup_Response { + optional .EFamilyGroupsTwoFactorMethod two_factor_method = 2 [default = k_EFamilyGroupsTwoFactorMethodNone]; + optional bool cooldown_skip_granted = 3; + optional bool invite_already_accepted = 4; +} + +message CFamilyGroups_ConfirmJoinFamilyGroup_Request { + optional uint64 family_groupid = 1; + optional uint64 invite_id = 2; + optional uint64 nonce = 3; +} + +message CFamilyGroups_ConfirmJoinFamilyGroup_Response { +} + +message CFamilyGroups_RemoveFromFamilyGroup_Request { + optional uint64 family_groupid = 1; + optional fixed64 steamid_to_remove = 2; +} + +message CFamilyGroups_RemoveFromFamilyGroup_Response { +} + +message CFamilyGroups_CancelFamilyGroupInvite_Request { + optional uint64 family_groupid = 1; + optional fixed64 steamid_to_cancel = 2; +} + +message CFamilyGroups_CancelFamilyGroupInvite_Response { +} + +message CFamilyGroups_GetUsersSharingDevice_Request { + optional uint64 family_groupid = 1; + optional uint64 client_instance_id = 2; +} + +message CFamilyGroups_GetUsersSharingDevice_Response { + repeated fixed64 users = 1; +} + +message CFamilyGroups_DeleteFamilyGroup_Request { + optional uint64 family_groupid = 1; +} + +message CFamilyGroups_DeleteFamilyGroup_Response { +} + +message CFamilyGroups_UndeleteFamilyGroup_Request { + optional uint64 family_groupid = 1; +} + +message CFamilyGroups_UndeleteFamilyGroup_Response { +} + +message CFamilyGroups_GetPlaytimeSummary_Request { + optional fixed64 family_groupid = 1; +} + +message CFamilyGroups_PlaytimeEntry { + optional fixed64 steamid = 1; + optional uint32 appid = 2; + optional uint32 first_played = 3; + optional uint32 latest_played = 4; + optional uint32 seconds_played = 5; +} + +message CFamilyGroups_GetPlaytimeSummary_Response { + repeated .CFamilyGroups_PlaytimeEntry entries = 1; + repeated .CFamilyGroups_PlaytimeEntry entries_by_owner = 2; +} + +message CFamilyGroups_RequestPurchase_Request { + optional uint64 family_groupid = 1; + optional uint64 gidshoppingcart = 2; + optional string store_country_code = 3; + optional bool use_account_cart = 4; +} + +message CFamilyGroups_RequestPurchase_Response { + optional uint64 gidshoppingcart = 1; + optional uint64 request_id = 2; +} + +message CFamilyGroups_GetPurchaseRequests_Request { + optional uint64 family_groupid = 1; + repeated uint64 request_ids = 3; + optional uint32 rt_include_completed_since = 4; +} + +message PurchaseRequest { + optional fixed64 requester_steamid = 1; + optional uint64 gidshoppingcart = 2; + optional uint32 time_requested = 3; + optional uint32 time_responded = 4; + optional fixed64 responder_steamid = 5; + optional .EPurchaseRequestAction response_action = 6 [default = k_EPurchaseRequestAction_None]; + optional bool is_completed = 7; + optional uint64 request_id = 8; + repeated uint32 requested_packageids = 9; + repeated uint32 purchased_packageids = 10; + repeated uint32 requested_bundleids = 11; + repeated uint32 purchased_bundleids = 12; +} + +message CFamilyGroups_GetPurchaseRequests_Response { + repeated .PurchaseRequest requests = 1; +} + +message CFamilyGroups_RespondToRequestedPurchase_Request { + optional uint64 family_groupid = 1; + optional .EPurchaseRequestAction action = 3 [default = k_EPurchaseRequestAction_None]; + optional uint64 request_id = 4; +} + +message CFamilyGroups_RespondToRequestedPurchase_Response { +} + +message CFamilyGroups_GetChangeLog_Request { + optional uint64 family_groupid = 1; +} + +message CFamilyGroups_GetChangeLog_Response { + message Change { + optional fixed64 timestamp = 1; + optional fixed64 actor_steamid = 2; + optional .EFamilyGroupChangeLogType type = 3 [default = k_InvalidChangeType]; + optional string body = 4; + optional bool by_support = 5; + } + + repeated .CFamilyGroups_GetChangeLog_Response.Change changes = 1; +} + +message CFamilyGroups_SetFamilyCooldownOverrides_Request { + optional uint64 family_groupid = 1; + optional uint32 cooldown_count = 2; +} + +message CFamilyGroups_SetFamilyCooldownOverrides_Response { +} + +message CFamilyGroups_GetSharedLibraryApps_Request { + optional fixed64 family_groupid = 1; + optional bool include_own = 2; + optional bool include_excluded = 3; + optional string language = 5; + optional uint32 max_apps = 6; + optional bool include_non_games = 7; + optional fixed64 steamid = 8; +} + +message CFamilyGroups_GetSharedLibraryApps_Response { + message SharedApp { + optional uint32 appid = 1; + repeated fixed64 owner_steamids = 2; + optional string name = 6; + optional string sort_as = 7; + optional string capsule_filename = 8; + optional string img_icon_hash = 9; + optional .ESharedLibraryExcludeReason exclude_reason = 10 [default = k_ESharedLibrary_Included]; + optional uint32 rt_time_acquired = 11; + optional uint32 rt_last_played = 12; + optional uint32 rt_playtime = 13; + optional .EProtoAppType app_type = 14 [default = k_EAppTypeGame]; + repeated uint32 content_descriptors = 15; + } + + repeated .CFamilyGroups_GetSharedLibraryApps_Response.SharedApp apps = 1; + optional fixed64 owner_steamid = 2; +} + +message CFamilyGroups_SetPreferredLender_Request { + optional uint64 family_groupid = 1; + optional uint32 appid = 2; + optional fixed64 lender_steamid = 3; +} + +message CFamilyGroups_SetPreferredLender_Response { +} + +message CFamilyGroups_GetPreferredLenders_Request { + optional uint64 family_groupid = 1; +} + +message CFamilyGroups_GetPreferredLenders_Response { + message FamilyMember { + optional fixed64 steamid = 1; + repeated uint32 preferred_appids = 2; + } + + repeated .CFamilyGroups_GetPreferredLenders_Response.FamilyMember members = 1; +} + +message CFamilyGroups_ForceAcceptInvite_Request { + optional uint64 family_groupid = 1; + optional fixed64 steamid = 2; +} + +message CFamilyGroups_ForceAcceptInvite_Response { +} + +message CFamilyGroups_GetInviteCheckResults_Request { + optional uint64 family_groupid = 1; + optional fixed64 steamid = 2; +} + +message CFamilyGroups_GetInviteCheckResults_Response { + optional bool wallet_country_matches = 1; + optional bool ip_match = 2; + optional uint32 join_restriction = 3; +} + +message CFamilyGroups_ClearCooldownSkip_Request { + optional fixed64 steamid = 1; + optional uint64 invite_id = 2; +} + +message CFamilyGroups_ClearCooldownSkip_Response { +} + +message CFamilyGroupsClient_NotifyRunningApps_Notification { + message PlayingMember { + optional fixed64 member_steamid = 1; + optional fixed64 owner_steamid = 2; + } + + message RunningApp { + optional uint32 appid = 1; + repeated .CFamilyGroupsClient_NotifyRunningApps_Notification.PlayingMember playing_members = 3; + } + + optional uint64 family_groupid = 1; + repeated .CFamilyGroupsClient_NotifyRunningApps_Notification.RunningApp running_apps = 2; +} + +message CFamilyGroupsClient_InviteStatus_Notification { +} + +message CFamilyGroupsClient_GroupChanged_Notification { + optional uint64 family_groupid = 1; +} + +service FamilyGroups { + rpc CreateFamilyGroup (.CFamilyGroups_CreateFamilyGroup_Request) returns (.CFamilyGroups_CreateFamilyGroup_Response); + rpc GetFamilyGroup (.CFamilyGroups_GetFamilyGroup_Request) returns (.CFamilyGroups_GetFamilyGroup_Response); + rpc GetFamilyGroupForUser (.CFamilyGroups_GetFamilyGroupForUser_Request) returns (.CFamilyGroups_GetFamilyGroupForUser_Response); + rpc ModifyFamilyGroupDetails (.CFamilyGroups_ModifyFamilyGroupDetails_Request) returns (.CFamilyGroups_ModifyFamilyGroupDetails_Response); + rpc InviteToFamilyGroup (.CFamilyGroups_InviteToFamilyGroup_Request) returns (.CFamilyGroups_InviteToFamilyGroup_Response); + rpc ConfirmInviteToFamilyGroup (.CFamilyGroups_ConfirmInviteToFamilyGroup_Request) returns (.CFamilyGroups_ConfirmInviteToFamilyGroup_Response); + rpc ResendInvitationToFamilyGroup (.CFamilyGroups_ResendInvitationToFamilyGroup_Request) returns (.CFamilyGroups_ResendInvitationToFamilyGroup_Response); + rpc JoinFamilyGroup (.CFamilyGroups_JoinFamilyGroup_Request) returns (.CFamilyGroups_JoinFamilyGroup_Response); + rpc ConfirmJoinFamilyGroup (.CFamilyGroups_ConfirmJoinFamilyGroup_Request) returns (.CFamilyGroups_ConfirmJoinFamilyGroup_Response); + rpc RemoveFromFamilyGroup (.CFamilyGroups_RemoveFromFamilyGroup_Request) returns (.CFamilyGroups_RemoveFromFamilyGroup_Response); + rpc CancelFamilyGroupInvite (.CFamilyGroups_CancelFamilyGroupInvite_Request) returns (.CFamilyGroups_CancelFamilyGroupInvite_Response); + rpc GetUsersSharingDevice (.CFamilyGroups_GetUsersSharingDevice_Request) returns (.CFamilyGroups_GetUsersSharingDevice_Response); + rpc DeleteFamilyGroup (.CFamilyGroups_DeleteFamilyGroup_Request) returns (.CFamilyGroups_DeleteFamilyGroup_Response); + rpc UndeleteFamilyGroup (.CFamilyGroups_UndeleteFamilyGroup_Request) returns (.CFamilyGroups_UndeleteFamilyGroup_Response); + rpc GetPlaytimeSummary (.CFamilyGroups_GetPlaytimeSummary_Request) returns (.CFamilyGroups_GetPlaytimeSummary_Response); + rpc RequestPurchase (.CFamilyGroups_RequestPurchase_Request) returns (.CFamilyGroups_RequestPurchase_Response); + rpc GetPurchaseRequests (.CFamilyGroups_GetPurchaseRequests_Request) returns (.CFamilyGroups_GetPurchaseRequests_Response); + rpc RespondToRequestedPurchase (.CFamilyGroups_RespondToRequestedPurchase_Request) returns (.CFamilyGroups_RespondToRequestedPurchase_Response); + rpc GetChangeLog (.CFamilyGroups_GetChangeLog_Request) returns (.CFamilyGroups_GetChangeLog_Response); + rpc SetFamilyCooldownOverrides (.CFamilyGroups_SetFamilyCooldownOverrides_Request) returns (.CFamilyGroups_SetFamilyCooldownOverrides_Response); + rpc GetSharedLibraryApps (.CFamilyGroups_GetSharedLibraryApps_Request) returns (.CFamilyGroups_GetSharedLibraryApps_Response); + rpc SetPreferredLender (.CFamilyGroups_SetPreferredLender_Request) returns (.CFamilyGroups_SetPreferredLender_Response); + rpc GetPreferredLenders (.CFamilyGroups_GetPreferredLenders_Request) returns (.CFamilyGroups_GetPreferredLenders_Response); + rpc ForceAcceptInvite (.CFamilyGroups_ForceAcceptInvite_Request) returns (.CFamilyGroups_ForceAcceptInvite_Response); + rpc GetInviteCheckResults (.CFamilyGroups_GetInviteCheckResults_Request) returns (.CFamilyGroups_GetInviteCheckResults_Response); + rpc ClearCooldownSkip (.CFamilyGroups_ClearCooldownSkip_Request) returns (.CFamilyGroups_ClearCooldownSkip_Response); +} + +service FamilyGroupsClient { + option (service_execution_site) = k_EProtoExecutionSiteSteamClient; + + rpc NotifyRunningApps (.CFamilyGroupsClient_NotifyRunningApps_Notification) returns (.NoResponse); + rpc NotifyInviteStatus (.CFamilyGroupsClient_InviteStatus_Notification) returns (.NoResponse); + rpc NotifyGroupChanged (.CFamilyGroupsClient_GroupChanged_Notification) returns (.NoResponse); +} diff --git a/src/test/java/in/dragonbra/javasteam/rpc/UnifiedInterfaceTest.kt b/src/test/java/in/dragonbra/javasteam/rpc/UnifiedInterfaceTest.kt index 7693f899..5ddff513 100644 --- a/src/test/java/in/dragonbra/javasteam/rpc/UnifiedInterfaceTest.kt +++ b/src/test/java/in/dragonbra/javasteam/rpc/UnifiedInterfaceTest.kt @@ -62,6 +62,8 @@ class UnifiedInterfaceTest { "ContentServerDirectory.kt", "DepotContentDetection.kt", "EmbeddedClient.kt", + "FamilyGroups.kt", + "FamilyGroupsClient.kt", "FriendMessages.kt", "FriendMessagesClient.kt", "GameNotifications.kt", diff --git a/src/test/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriendsTest.java b/src/test/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriendsTest.java index 2f44510c..c5d4a61e 100644 --- a/src/test/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriendsTest.java +++ b/src/test/java/in/dragonbra/javasteam/steam/handlers/steamfriends/SteamFriendsTest.java @@ -327,7 +327,7 @@ public void handlePersonaState() { handler.handleMsg(msg); - PersonaStatesCallback callback = verifyCallback(); + PersonaStateCallback callback = verifyCallback(); //assertEquals(1, callback.getPersonaStates().size()); assertEquals(EPersonaState.Offline, callback.getState()); diff --git a/src/test/java/in/dragonbra/javasteam/types/AsyncJobTest.kt b/src/test/java/in/dragonbra/javasteam/types/AsyncJobTest.kt index 3027484d..b3ade8c1 100644 --- a/src/test/java/in/dragonbra/javasteam/types/AsyncJobTest.kt +++ b/src/test/java/in/dragonbra/javasteam/types/AsyncJobTest.kt @@ -394,7 +394,7 @@ class AsyncJobTest { "AsyncJobMultiple should not be canceled on partial (timed out) result set" ) - val result: AsyncJobMultiple.ResultSet = asyncTask.get() + val result = asyncTask.get() Assertions.assertFalse(result.complete, "ResultSet should be incomplete") Assertions.assertFalse(result.failed, "ResultSet should not be failed") @@ -432,7 +432,7 @@ class AsyncJobTest { "AsyncJobMultiple should not be canceled on partial (failed) result set" ) - val result: AsyncJobMultiple.ResultSet = asyncTask.get() + val result = asyncTask.get() Assertions.assertFalse(result.complete, "ResultSet should be incomplete") Assertions.assertTrue(result.failed, "ResultSet should be failed") diff --git a/src/test/java/in/dragonbra/javasteam/util/HardwareUtilsTest.java b/src/test/java/in/dragonbra/javasteam/util/HardwareUtilsTest.java new file mode 100644 index 00000000..299da293 --- /dev/null +++ b/src/test/java/in/dragonbra/javasteam/util/HardwareUtilsTest.java @@ -0,0 +1,32 @@ +package in.dragonbra.javasteam.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Field; + +public class HardwareUtilsTest { + + @BeforeEach + public void setUp() throws NoSuchFieldException, IllegalAccessException { + // Ehh.... This resets the 'MACHINE_NAME' field for every test. + Field field = HardwareUtils.class.getDeclaredField("MACHINE_NAME"); + field.setAccessible(true); + field.set(null, null); + } + + @Test + public void machineNameWithTag() { + var name = HardwareUtils.getMachineName(true); + System.out.println(name); + Assertions.assertTrue(name.contains(" (JavaSteam)")); + } + + @Test + public void machineNameWithNoTag() { + var name = HardwareUtils.getMachineName(); + System.out.println(name); + Assertions.assertFalse(name.contains(" (JavaSteam)")); + } +}