Squashed commit of the following:

commit 7501fd264b7248633c6853a6f232dfbf894b944a
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Mon Oct 21 12:18:54 2024 +0200

    Remove CI artifact

commit d6ad6e78e386d08b2b7aeb53992b4b987b08d729
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Mon Oct 21 10:23:04 2024 +0200

    Bump experiments

commit d5553a52f3bc656c5dd1c280b9189bc48e4d417e
Merge: 6e34cdc2 4b3224a7
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Mon Oct 21 10:19:16 2024 +0200

    Merge branch 'main' into unified-experiments

commit 6e34cdc26c0804852c2b0cbadedcafbe45afb787
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Thu Oct 17 17:28:08 2024 +0200

    Update experiments

commit 70b1c6e367c697ee669b16bf4d18b17aef4c2bb0
Merge: c22eb587 def6b675
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Thu Oct 17 17:18:34 2024 +0200

    Merge branch 'main' into unified-experiments

commit c22eb5872ebcd1a284e354b645d4dc634412513b
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Mon Oct 14 20:07:23 2024 +0200

    Make it work

commit 9907d375040ca5a0750b70df541597be29abc21f
Merge: de4b33c2 d166e198
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Mon Oct 14 19:31:06 2024 +0200

    Merge branch 'main' into unified-experiments

commit de4b33c2c458d516b1945dd7ea24db321f15f7f9
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Sun Oct 13 20:22:32 2024 +0200

    Fix docker build again

commit 60f3be0bd89375d19333f017389c0ba223ea721a
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Sun Oct 13 20:18:27 2024 +0200

    Fix docker build

commit 07502180c4eb32549533917efca661e13ccf1a2f
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Sun Oct 13 20:15:18 2024 +0200

    Commit missing part

commit 75fd1b867511419fa11d224042f5bc761571ac8d
Author: Łukasz Domeradzki <JustArchi@JustArchi.net>
Date:   Sun Oct 13 20:12:12 2024 +0200

    Craft some experiments
This commit is contained in:
Łukasz Domeradzki
2024-10-21 12:19:23 +02:00
parent 4b3224a748
commit 6bc29e8c3f
5 changed files with 153 additions and 229 deletions

View File

@@ -32,14 +32,14 @@ namespace ArchiSteamFarm.OfficialPlugins.MobileAuthenticator;
internal sealed class MobileAuthenticatorHandler : ClientMsgHandler {
private readonly ArchiLogger ArchiLogger;
private readonly SteamUnifiedMessages.UnifiedService<ITwoFactor> UnifiedTwoFactorService;
private readonly TwoFactor UnifiedTwoFactorService;
internal MobileAuthenticatorHandler(ArchiLogger archiLogger, SteamUnifiedMessages steamUnifiedMessages) {
ArgumentNullException.ThrowIfNull(archiLogger);
ArgumentNullException.ThrowIfNull(steamUnifiedMessages);
ArchiLogger = archiLogger;
UnifiedTwoFactorService = steamUnifiedMessages.CreateService<ITwoFactor>();
UnifiedTwoFactorService = steamUnifiedMessages.CreateService<TwoFactor>();
}
public override void HandleMsg(IPacketMsg packetMsg) => ArgumentNullException.ThrowIfNull(packetMsg);
@@ -66,23 +66,17 @@ internal sealed class MobileAuthenticatorHandler : ClientMsgHandler {
steamid = steamID
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CTwoFactor_AddAuthenticator_Response> response;
try {
response = await UnifiedTwoFactorService.SendMessage(x => x.AddAuthenticator(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedTwoFactorService.AddAuthenticator(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CTwoFactor_AddAuthenticator_Response body = response.GetDeserializedResponse<CTwoFactor_AddAuthenticator_Response>();
return body;
return response.Result == EResult.OK ? response.Body : null;
}
internal async Task<CTwoFactor_FinalizeAddAuthenticator_Response?> FinalizeAuthenticator(ulong steamID, string activationCode, string authenticatorCode, ulong authenticatorTime) {
@@ -109,22 +103,16 @@ internal sealed class MobileAuthenticatorHandler : ClientMsgHandler {
steamid = steamID
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CTwoFactor_FinalizeAddAuthenticator_Response> response;
try {
response = await UnifiedTwoFactorService.SendMessage(x => x.FinalizeAddAuthenticator(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedTwoFactorService.FinalizeAddAuthenticator(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CTwoFactor_FinalizeAddAuthenticator_Response body = response.GetDeserializedResponse<CTwoFactor_FinalizeAddAuthenticator_Response>();
return body;
return response.Result == EResult.OK ? response.Body : null;
}
}

View File

@@ -383,8 +383,6 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
CallbackManager.Subscribe<SteamFriends.FriendsListCallback>(OnFriendsList);
CallbackManager.Subscribe<SteamFriends.PersonaStateCallback>(OnPersonaState);
CallbackManager.Subscribe<SteamUnifiedMessages.ServiceMethodNotification>(OnServiceMethod);
SteamUser = SteamClient.GetHandler<SteamUser>() ?? throw new InvalidOperationException(nameof(SteamUser));
CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
@@ -395,6 +393,9 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
CallbackManager.Subscribe<SharedLibraryLockStatusCallback>(OnSharedLibraryLockStatus);
CallbackManager.Subscribe<UserNotificationsCallback>(OnUserNotifications);
CallbackManager.SubscribeServiceNotification<ChatRoomClient, CChatRoom_IncomingChatMessage_Notification>(OnIncomingChatMessage);
CallbackManager.SubscribeServiceNotification<FriendMessagesClient, CFriendMessages_IncomingMessage_Notification>(OnIncomingMessage);
Actions = new Actions(this);
CardsFarmer = new CardsFarmer(this);
Commands = new Commands(this);
@@ -3041,100 +3042,100 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
await Actions.AcceptGuestPasses(guestPassIDs).ConfigureAwait(false);
}
private async Task OnIncomingChatMessage(CChatRoom_IncomingChatMessage_Notification notification) {
private async void OnIncomingChatMessage(SteamUnifiedMessages.ServiceMethodNotification<CChatRoom_IncomingChatMessage_Notification> notification) {
ArgumentNullException.ThrowIfNull(notification);
if (notification.chat_group_id == 0) {
ArchiLogger.LogNullError(notification.chat_group_id);
if (notification.Body.chat_group_id == 0) {
ArchiLogger.LogNullError(notification.Body.chat_group_id);
return;
}
if (notification.chat_id == 0) {
ArchiLogger.LogNullError(notification.chat_id);
if (notification.Body.chat_id == 0) {
ArchiLogger.LogNullError(notification.Body.chat_id);
return;
}
if (notification.steamid_sender == 0) {
ArchiLogger.LogNullError(notification.steamid_sender);
if (notification.Body.steamid_sender == 0) {
ArchiLogger.LogNullError(notification.Body.steamid_sender);
return;
}
// Under normal circumstances, timestamp must always be greater than 0, but Steam already proved that it's capable of going against the logic
if ((notification.steamid_sender != SteamID) && (notification.timestamp > 0)) {
if (ShouldAckChatMessage(notification.steamid_sender)) {
Utilities.InBackground(() => ArchiHandler.AckChatMessage(notification.chat_group_id, notification.chat_id, notification.timestamp));
if ((notification.Body.steamid_sender != SteamID) && (notification.Body.timestamp > 0)) {
if (ShouldAckChatMessage(notification.Body.steamid_sender)) {
Utilities.InBackground(() => ArchiHandler.AckChatMessage(notification.Body.chat_group_id, notification.Body.chat_id, notification.Body.timestamp));
}
}
string message;
// Prefer to use message without bbcode, but only if it's available
if (!string.IsNullOrEmpty(notification.message_no_bbcode)) {
message = notification.message_no_bbcode;
} else if (!string.IsNullOrEmpty(notification.message)) {
message = SteamChatMessage.Unescape(notification.message);
if (!string.IsNullOrEmpty(notification.Body.message_no_bbcode)) {
message = notification.Body.message_no_bbcode;
} else if (!string.IsNullOrEmpty(notification.Body.message)) {
message = SteamChatMessage.Unescape(notification.Body.message);
} else {
return;
}
ArchiLogger.LogChatMessage(false, message, notification.chat_group_id, notification.chat_id, notification.steamid_sender);
ArchiLogger.LogChatMessage(false, message, notification.Body.chat_group_id, notification.Body.chat_id, notification.Body.steamid_sender);
// Steam network broadcasts chat events also when we don't explicitly sign into Steam community
// We'll explicitly ignore those messages when using offline mode, as it was done in the first version of Steam chat when no messages were broadcasted at all before signing in
// Handling messages will still work correctly in invisible mode, which is how it should work in the first place
// This goes in addition to usual logic that ignores irrelevant messages from being parsed further
if ((notification.chat_group_id != MasterChatGroupID) || (BotConfig.OnlineStatus == EPersonaState.Offline)) {
if ((notification.Body.chat_group_id != MasterChatGroupID) || (BotConfig.OnlineStatus == EPersonaState.Offline)) {
return;
}
await Commands.HandleMessage(notification.chat_group_id, notification.chat_id, notification.steamid_sender, message).ConfigureAwait(false);
await Commands.HandleMessage(notification.Body.chat_group_id, notification.Body.chat_id, notification.Body.steamid_sender, message).ConfigureAwait(false);
}
private async Task OnIncomingMessage(CFriendMessages_IncomingMessage_Notification notification) {
private async void OnIncomingMessage(SteamUnifiedMessages.ServiceMethodNotification<CFriendMessages_IncomingMessage_Notification> notification) {
ArgumentNullException.ThrowIfNull(notification);
if (notification.steamid_friend == 0) {
ArchiLogger.LogNullError(notification.steamid_friend);
if (notification.Body.steamid_friend == 0) {
ArchiLogger.LogNullError(notification.Body.steamid_friend);
return;
}
if ((EChatEntryType) notification.chat_entry_type != EChatEntryType.ChatMsg) {
if ((EChatEntryType) notification.Body.chat_entry_type != EChatEntryType.ChatMsg) {
return;
}
// Under normal circumstances, timestamp must always be greater than 0, but Steam already proved that it's capable of going against the logic
if (notification is { local_echo: false, rtime32_server_timestamp: > 0 }) {
if (ShouldAckChatMessage(notification.steamid_friend)) {
Utilities.InBackground(() => ArchiHandler.AckMessage(notification.steamid_friend, notification.rtime32_server_timestamp));
if (notification.Body is { local_echo: false, rtime32_server_timestamp: > 0 }) {
if (ShouldAckChatMessage(notification.Body.steamid_friend)) {
Utilities.InBackground(() => ArchiHandler.AckMessage(notification.Body.steamid_friend, notification.Body.rtime32_server_timestamp));
}
}
string message;
// Prefer to use message without bbcode, but only if it's available
if (!string.IsNullOrEmpty(notification.message_no_bbcode)) {
message = notification.message_no_bbcode;
} else if (!string.IsNullOrEmpty(notification.message)) {
message = SteamChatMessage.Unescape(notification.message);
if (!string.IsNullOrEmpty(notification.Body.message_no_bbcode)) {
message = notification.Body.message_no_bbcode;
} else if (!string.IsNullOrEmpty(notification.Body.message)) {
message = SteamChatMessage.Unescape(notification.Body.message);
} else {
return;
}
ArchiLogger.LogChatMessage(notification.local_echo, message, steamID: notification.steamid_friend);
ArchiLogger.LogChatMessage(notification.Body.local_echo, message, steamID: notification.Body.steamid_friend);
// Steam network broadcasts chat events also when we don't explicitly sign into Steam community
// We'll explicitly ignore those messages when using offline mode, as it was done in the first version of Steam chat when no messages were broadcasted at all before signing in
// Handling messages will still work correctly in invisible mode, which is how it should work in the first place
// This goes in addition to usual logic that ignores irrelevant messages from being parsed further
if (notification.local_echo || (BotConfig.OnlineStatus == EPersonaState.Offline)) {
if (notification.Body.local_echo || (BotConfig.OnlineStatus == EPersonaState.Offline)) {
return;
}
await Commands.HandleMessage(notification.steamid_friend, message).ConfigureAwait(false);
await Commands.HandleMessage(notification.Body.steamid_friend, message).ConfigureAwait(false);
}
private void OnInventoryChanged() {
@@ -3466,21 +3467,6 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
private async void OnSendItemsTimer(object? state = null) => await Actions.SendInventory(filterFunction: item => BotConfig.LootableTypes.Contains(item.Type)).ConfigureAwait(false);
private async void OnServiceMethod(SteamUnifiedMessages.ServiceMethodNotification notification) {
ArgumentNullException.ThrowIfNull(notification);
switch (notification.MethodName) {
case "ChatRoomClient.NotifyIncomingChatMessage#1":
await OnIncomingChatMessage((CChatRoom_IncomingChatMessage_Notification) notification.Body).ConfigureAwait(false);
break;
case "FriendMessagesClient.IncomingMessage#1":
await OnIncomingMessage((CFriendMessages_IncomingMessage_Notification) notification.Body).ConfigureAwait(false);
break;
}
}
private async void OnSharedLibraryLockStatus(SharedLibraryLockStatusCallback callback) {
ArgumentNullException.ThrowIfNull(callback);

View File

@@ -54,17 +54,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
private readonly ArchiLogger ArchiLogger;
private readonly SteamUnifiedMessages.UnifiedService<IAccountPrivateApps> UnifiedAccountPrivateApps;
private readonly SteamUnifiedMessages.UnifiedService<IChatRoom> UnifiedChatRoomService;
private readonly SteamUnifiedMessages.UnifiedService<IClanChatRooms> UnifiedClanChatRoomsService;
private readonly SteamUnifiedMessages.UnifiedService<ICredentials> UnifiedCredentialsService;
private readonly SteamUnifiedMessages.UnifiedService<IEcon> UnifiedEconService;
private readonly SteamUnifiedMessages.UnifiedService<IFamilyGroups> UnifiedFamilyGroups;
private readonly SteamUnifiedMessages.UnifiedService<IFriendMessages> UnifiedFriendMessagesService;
private readonly SteamUnifiedMessages.UnifiedService<ILoyaltyRewards> UnifiedLoyaltyRewards;
private readonly SteamUnifiedMessages.UnifiedService<IPlayer> UnifiedPlayerService;
private readonly SteamUnifiedMessages.UnifiedService<IStore> UnifiedStoreService;
private readonly SteamUnifiedMessages.UnifiedService<ITwoFactor> UnifiedTwoFactorService;
private readonly AccountPrivateApps UnifiedAccountPrivateApps;
private readonly ChatRoom UnifiedChatRoomService;
private readonly ClanChatRooms UnifiedClanChatRoomsService;
private readonly Credentials UnifiedCredentialsService;
private readonly Econ UnifiedEconService;
private readonly FamilyGroups UnifiedFamilyGroups;
private readonly FriendMessages UnifiedFriendMessagesService;
private readonly LoyaltyRewards UnifiedLoyaltyRewards;
private readonly Player UnifiedPlayerService;
private readonly Store UnifiedStoreService;
private readonly TwoFactor UnifiedTwoFactorService;
internal DateTime LastPacketReceived { get; private set; }
@@ -74,17 +74,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
ArchiLogger = archiLogger;
UnifiedAccountPrivateApps = steamUnifiedMessages.CreateService<IAccountPrivateApps>();
UnifiedChatRoomService = steamUnifiedMessages.CreateService<IChatRoom>();
UnifiedClanChatRoomsService = steamUnifiedMessages.CreateService<IClanChatRooms>();
UnifiedCredentialsService = steamUnifiedMessages.CreateService<ICredentials>();
UnifiedEconService = steamUnifiedMessages.CreateService<IEcon>();
UnifiedFamilyGroups = steamUnifiedMessages.CreateService<IFamilyGroups>();
UnifiedFriendMessagesService = steamUnifiedMessages.CreateService<IFriendMessages>();
UnifiedLoyaltyRewards = steamUnifiedMessages.CreateService<ILoyaltyRewards>();
UnifiedPlayerService = steamUnifiedMessages.CreateService<IPlayer>();
UnifiedStoreService = steamUnifiedMessages.CreateService<IStore>();
UnifiedTwoFactorService = steamUnifiedMessages.CreateService<ITwoFactor>();
UnifiedAccountPrivateApps = steamUnifiedMessages.CreateService<AccountPrivateApps>();
UnifiedChatRoomService = steamUnifiedMessages.CreateService<ChatRoom>();
UnifiedClanChatRoomsService = steamUnifiedMessages.CreateService<ClanChatRooms>();
UnifiedCredentialsService = steamUnifiedMessages.CreateService<Credentials>();
UnifiedEconService = steamUnifiedMessages.CreateService<Econ>();
UnifiedFamilyGroups = steamUnifiedMessages.CreateService<FamilyGroups>();
UnifiedFriendMessagesService = steamUnifiedMessages.CreateService<FriendMessages>();
UnifiedLoyaltyRewards = steamUnifiedMessages.CreateService<LoyaltyRewards>();
UnifiedPlayerService = steamUnifiedMessages.CreateService<Player>();
UnifiedStoreService = steamUnifiedMessages.CreateService<Store>();
UnifiedTwoFactorService = steamUnifiedMessages.CreateService<TwoFactor>();
}
[PublicAPI]
@@ -103,10 +103,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
CPlayer_AddFriend_Request request = new() { steamid = steamID };
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CPlayer_AddFriend_Response> response;
try {
response = await UnifiedPlayerService.SendMessage(x => x.AddFriend(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedPlayerService.AddFriend(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -135,17 +135,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
steamid = steamID
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CClanChatRooms_GetClanChatRoomInfo_Response> response;
try {
response = await UnifiedClanChatRoomsService.SendMessage(x => x.GetClanChatRoomInfo(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedClanChatRoomsService.GetClanChatRoomInfo(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
return response.Result == EResult.OK ? response.GetDeserializedResponse<CClanChatRooms_GetClanChatRoomInfo_Response>() : null;
return response.Result == EResult.OK ? response.Body : null;
}
[PublicAPI]
@@ -160,17 +160,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
CCredentials_LastCredentialChangeTime_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CCredentials_LastCredentialChangeTime_Response> response;
try {
response = await UnifiedCredentialsService.SendMessage(x => x.GetCredentialChangeTimeDetails(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedCredentialsService.GetCredentialChangeTimeDetails(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
return response.Result == EResult.OK ? response.GetDeserializedResponse<CCredentials_LastCredentialChangeTime_Response>() : null;
return response.Result == EResult.OK ? response.Body : null;
}
[PublicAPI]
@@ -209,16 +209,16 @@ public sealed class ArchiHandler : ClientMsgHandler {
Dictionary<(ulong ClassID, ulong InstanceID), InventoryDescription>? descriptions = null;
while (true) {
SteamUnifiedMessages.ServiceMethodResponse? serviceMethodResponse = null;
SteamUnifiedMessages.ServiceMethodResponse<CEcon_GetInventoryItemsWithDescriptions_Response>? response = null;
for (byte i = 0; (i < WebBrowser.MaxTries) && (serviceMethodResponse?.Result != EResult.OK) && Client.IsConnected && (Client.SteamID != null); i++) {
for (byte i = 0; (i < WebBrowser.MaxTries) && (response?.Result != EResult.OK) && Client.IsConnected && (Client.SteamID != null); i++) {
if (i > 0) {
// It seems 2 seconds is enough to win over DuplicateRequest, so we'll use that for this and also other network-related failures
await Task.Delay(2000).ConfigureAwait(false);
}
try {
serviceMethodResponse = await UnifiedEconService.SendMessage(x => x.GetInventoryItemsWithDescriptions(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedEconService.GetInventoryItemsWithDescriptions(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -226,7 +226,7 @@ public sealed class ArchiHandler : ClientMsgHandler {
}
// Interpret the result and see what we should do about it
switch (serviceMethodResponse.Result) {
switch (response.Result) {
case EResult.OK:
// Success, we can continue
break;
@@ -240,39 +240,37 @@ public sealed class ArchiHandler : ClientMsgHandler {
continue;
case EResult.NoMatch:
// Expected failures that we're not going to retry
throw new TimeoutException(Strings.FormatWarningFailedWithError(serviceMethodResponse.Result));
throw new TimeoutException(Strings.FormatWarningFailedWithError(response.Result));
default:
// Unknown failures, report them and do not retry since we're unsure if we should
ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(serviceMethodResponse.Result), serviceMethodResponse.Result));
ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(response.Result), response.Result));
throw new TimeoutException(Strings.FormatWarningFailedWithError(serviceMethodResponse.Result));
throw new TimeoutException(Strings.FormatWarningFailedWithError(response.Result));
}
}
if (serviceMethodResponse == null) {
throw new TimeoutException(Strings.FormatErrorObjectIsNull(nameof(serviceMethodResponse)));
if (response == null) {
throw new TimeoutException(Strings.FormatErrorObjectIsNull(nameof(response)));
}
if (serviceMethodResponse.Result != EResult.OK) {
throw new TimeoutException(Strings.FormatWarningFailedWithError(serviceMethodResponse.Result));
if (response.Result != EResult.OK) {
throw new TimeoutException(Strings.FormatWarningFailedWithError(response.Result));
}
CEcon_GetInventoryItemsWithDescriptions_Response response = serviceMethodResponse.GetDeserializedResponse<CEcon_GetInventoryItemsWithDescriptions_Response>();
if ((response.total_inventory_count == 0) || (response.assets.Count == 0)) {
if ((response.Body.total_inventory_count == 0) || (response.Body.assets.Count == 0)) {
// Empty inventory
yield break;
}
if (response.descriptions.Count == 0) {
throw new InvalidOperationException(nameof(response.descriptions));
if (response.Body.descriptions.Count == 0) {
throw new InvalidOperationException(nameof(response.Body.descriptions));
}
if (response.total_inventory_count > Array.MaxLength) {
throw new InvalidOperationException(nameof(response.total_inventory_count));
if (response.Body.total_inventory_count > Array.MaxLength) {
throw new InvalidOperationException(nameof(response.Body.total_inventory_count));
}
assetIDs ??= new HashSet<ulong>((int) response.total_inventory_count);
assetIDs ??= new HashSet<ulong>((int) response.Body.total_inventory_count);
if (descriptions == null) {
descriptions = new Dictionary<(ulong ClassID, ulong InstanceID), InventoryDescription>();
@@ -281,7 +279,7 @@ public sealed class ArchiHandler : ClientMsgHandler {
descriptions.Clear();
}
foreach (CEconItem_Description? description in response.descriptions) {
foreach (CEconItem_Description? description in response.Body.descriptions) {
if (description.classid == 0) {
throw new NotSupportedException(Strings.FormatErrorObjectIsNull(nameof(description.classid)));
}
@@ -295,7 +293,7 @@ public sealed class ArchiHandler : ClientMsgHandler {
descriptions.Add(key, new InventoryDescription(description));
}
foreach (CEcon_Asset? asset in response.assets.Where(asset => assetIDs.Add(asset.assetid))) {
foreach (CEcon_Asset? asset in response.Body.assets.Where(asset => assetIDs.Add(asset.assetid))) {
InventoryDescription? description = descriptions.GetValueOrDefault((asset.classid, asset.instanceid));
// Extra bulletproofing against Steam showing us middle finger
@@ -306,15 +304,15 @@ public sealed class ArchiHandler : ClientMsgHandler {
yield return new Asset(asset, description);
}
if (!response.more_items) {
if (!response.Body.more_items) {
yield break;
}
if (response.last_assetid == 0) {
throw new NotSupportedException(Strings.FormatErrorObjectIsNull(nameof(response.last_assetid)));
if (response.Body.last_assetid == 0) {
throw new NotSupportedException(Strings.FormatErrorObjectIsNull(nameof(response.Body.last_assetid)));
}
request.start_assetid = response.last_assetid;
request.start_assetid = response.Body.last_assetid;
}
}
@@ -340,23 +338,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
skip_unvetted_apps = false
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CPlayer_GetOwnedGames_Response> response;
try {
response = await UnifiedPlayerService.SendMessage(x => x.GetOwnedGames(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedPlayerService.GetOwnedGames(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CPlayer_GetOwnedGames_Response body = response.GetDeserializedResponse<CPlayer_GetOwnedGames_Response>();
return body.games.ToDictionary(static game => (uint) game.appid, static game => game.name);
return response.Result == EResult.OK ? response.Body.games.ToDictionary(static game => (uint) game.appid, static game => game.name) : null;
}
[PublicAPI]
@@ -381,23 +373,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
CLoyaltyRewards_GetSummary_Request request = new() { steamid = steamID };
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CLoyaltyRewards_GetSummary_Response> response;
try {
response = await UnifiedLoyaltyRewards.SendMessage(x => x.GetSummary(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedLoyaltyRewards.GetSummary(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CLoyaltyRewards_GetSummary_Response body = response.GetDeserializedResponse<CLoyaltyRewards_GetSummary_Response>();
return body.summary?.points;
return response.Result == EResult.OK ? response.Body.summary?.points : null;
}
[PublicAPI]
@@ -412,17 +398,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
CCredentials_GetSteamGuardDetails_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CCredentials_GetSteamGuardDetails_Response> response;
try {
response = await UnifiedCredentialsService.SendMessage(x => x.GetSteamGuardDetails(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedCredentialsService.GetSteamGuardDetails(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
return response.Result == EResult.OK ? response.GetDeserializedResponse<CCredentials_GetSteamGuardDetails_Response>() : null;
return response.Result == EResult.OK ? response.Body : null;
}
[PublicAPI]
@@ -437,23 +423,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
CEcon_GetTradeOfferAccessToken_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CEcon_GetTradeOfferAccessToken_Response> response;
try {
response = await UnifiedEconService.SendMessage(x => x.GetTradeOfferAccessToken(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedEconService.GetTradeOfferAccessToken(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CEcon_GetTradeOfferAccessToken_Response body = response.GetDeserializedResponse<CEcon_GetTradeOfferAccessToken_Response>();
return body.trade_offer_access_token;
return response.Result == EResult.OK ? response.Body.trade_offer_access_token : null;
}
public override void HandleMsg(IPacketMsg packetMsg) {
@@ -503,10 +483,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
CChatRoom_JoinChatRoomGroup_Request request = new() { chat_group_id = chatGroupID };
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CChatRoom_JoinChatRoomGroup_Response> response;
try {
response = await UnifiedChatRoomService.SendMessage(x => x.JoinChatRoomGroup(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedChatRoomService.JoinChatRoomGroup(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -530,10 +510,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
CChatRoom_LeaveChatRoomGroup_Request request = new() { chat_group_id = chatGroupID };
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CChatRoom_LeaveChatRoomGroup_Response> response;
try {
response = await UnifiedChatRoomService.SendMessage(x => x.LeaveChatRoomGroup(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedChatRoomService.LeaveChatRoomGroup(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -559,10 +539,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
defid = definitionID
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CLoyaltyRewards_RedeemPoints_Response> response;
try {
response = await UnifiedLoyaltyRewards.SendMessage(x => x.RedeemPoints(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedLoyaltyRewards.RedeemPoints(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -588,10 +568,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
CPlayer_RemoveFriend_Request request = new() { steamid = steamID };
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CPlayer_RemoveFriend_Response> response;
try {
response = await UnifiedPlayerService.SendMessage(x => x.RemoveFriend(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedPlayerService.RemoveFriend(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -620,7 +600,7 @@ public sealed class ArchiHandler : ClientMsgHandler {
timestamp = timestamp
};
UnifiedChatRoomService.SendNotification(x => x.AckChatMessage(request));
UnifiedChatRoomService.AckChatMessage(request);
}
internal void AckMessage(ulong steamID, uint timestamp) {
@@ -643,7 +623,7 @@ public sealed class ArchiHandler : ClientMsgHandler {
timestamp = timestamp
};
UnifiedFriendMessagesService.SendNotification(x => x.AckMessage(request));
UnifiedFriendMessagesService.AckMessage(request);
}
internal void AcknowledgeClanInvite(ulong steamID, bool acceptInvite) {
@@ -689,10 +669,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
steamid = steamID
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CFamilyGroups_GetFamilyGroupForUser_Response> response;
try {
response = await UnifiedFamilyGroups.SendMessage(x => x.GetFamilyGroupForUser(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedFamilyGroups.GetFamilyGroupForUser(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -703,9 +683,7 @@ public sealed class ArchiHandler : ClientMsgHandler {
return null;
}
CFamilyGroups_GetFamilyGroupForUser_Response body = response.GetDeserializedResponse<CFamilyGroups_GetFamilyGroupForUser_Response>();
return body.family_group?.members.Where(member => member.steamid != steamID).Select(static member => member.steamid).ToHashSet() ?? [];
return response.Body.family_group?.members.Where(member => member.steamid != steamID).Select(static member => member.steamid).ToHashSet() ?? [];
}
internal async Task<uint?> GetLevel() {
@@ -718,10 +696,11 @@ public sealed class ArchiHandler : ClientMsgHandler {
}
CPlayer_GetGameBadgeLevels_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CPlayer_GetGameBadgeLevels_Response> response;
try {
response = await UnifiedPlayerService.SendMessage(x => x.GetGameBadgeLevels(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedPlayerService.GetGameBadgeLevels(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -732,9 +711,7 @@ public sealed class ArchiHandler : ClientMsgHandler {
return null;
}
CPlayer_GetGameBadgeLevels_Response body = response.GetDeserializedResponse<CPlayer_GetGameBadgeLevels_Response>();
return body.player_level;
return response.Body.player_level;
}
internal async Task<HashSet<ulong>?> GetMyChatGroupIDs() {
@@ -748,23 +725,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
CChatRoom_GetMyChatRoomGroups_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CChatRoom_GetMyChatRoomGroups_Response> response;
try {
response = await UnifiedChatRoomService.SendMessage(x => x.GetMyChatRoomGroups(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedChatRoomService.GetMyChatRoomGroups(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CChatRoom_GetMyChatRoomGroups_Response body = response.GetDeserializedResponse<CChatRoom_GetMyChatRoomGroups_Response>();
return body.chat_room_groups.Select(static chatRoom => chatRoom.group_summary.chat_group_id).ToHashSet();
return response.Result == EResult.OK ? response.Body.chat_room_groups.Select(static chatRoom => chatRoom.group_summary.chat_group_id).ToHashSet() : null;
}
internal async Task<CPrivacySettings?> GetPrivacySettings() {
@@ -778,23 +749,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
CPlayer_GetPrivacySettings_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CPlayer_GetPrivacySettings_Response> response;
try {
response = await UnifiedPlayerService.SendMessage(x => x.GetPrivacySettings(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedPlayerService.GetPrivacySettings(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CPlayer_GetPrivacySettings_Response body = response.GetDeserializedResponse<CPlayer_GetPrivacySettings_Response>();
return body.privacy_settings;
return response.Result == EResult.OK ? response.Body.privacy_settings : null;
}
internal async Task<HashSet<uint>?> GetPrivateAppIDs() {
@@ -808,23 +773,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
CAccountPrivateApps_GetPrivateAppList_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CAccountPrivateApps_GetPrivateAppList_Response> response;
try {
response = await UnifiedAccountPrivateApps.SendMessage(x => x.GetPrivateAppList(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedAccountPrivateApps.GetPrivateAppList(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CAccountPrivateApps_GetPrivateAppList_Response body = response.GetDeserializedResponse<CAccountPrivateApps_GetPrivateAppList_Response>();
return body.private_apps.appids.Select(static appID => (uint) appID).ToHashSet();
return response.Result == EResult.OK ? response.Body.private_apps.appids.Select(static appID => (uint) appID).ToHashSet() : null;
}
internal async Task<ulong> GetServerTime() {
@@ -838,23 +797,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
CTwoFactor_Time_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CTwoFactor_Time_Response> response;
try {
response = await UnifiedTwoFactorService.SendMessage(x => x.QueryTime(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedTwoFactorService.QueryTime(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return 0;
}
if (response.Result != EResult.OK) {
return 0;
}
CTwoFactor_Time_Response body = response.GetDeserializedResponse<CTwoFactor_Time_Response>();
return body.server_time;
return response.Result == EResult.OK ? response.Body.server_time : 0;
}
internal async Task<string?> GetTwoFactorDeviceIdentifier(ulong steamID) {
@@ -874,23 +827,17 @@ public sealed class ArchiHandler : ClientMsgHandler {
steamid = steamID
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CTwoFactor_Status_Response> response;
try {
response = await UnifiedTwoFactorService.SendMessage(x => x.QueryStatus(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedTwoFactorService.QueryStatus(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CTwoFactor_Status_Response body = response.GetDeserializedResponse<CTwoFactor_Status_Response>();
return body.device_identifier;
return response.Result == EResult.OK ? response.Body.device_identifier : null;
}
internal async Task PlayGames(IReadOnlyCollection<uint> gameIDs, string? gameName = null) {
@@ -994,18 +941,18 @@ public sealed class ArchiHandler : ClientMsgHandler {
is_request_from_client = true
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CStore_RegisterCDKey_Response> response;
try {
response = await UnifiedStoreService.SendMessage(x => x.RegisterCDKey(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedStoreService.RegisterCDKey(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
// We want to deserialize the response even with failed EResult
return response.GetDeserializedResponse<CStore_RegisterCDKey_Response>();
// We want to return the response even with failed EResult
return response.Body;
}
internal void RequestItemAnnouncements() {
@@ -1043,10 +990,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
steamid = steamID
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CFriendMessages_SendMessage_Response> response;
try {
response = await UnifiedFriendMessagesService.SendMessage(x => x.SendMessage(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedFriendMessagesService.SendMessage(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -1075,10 +1022,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
message = message
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CChatRoom_SendChatMessage_Response> response;
try {
response = await UnifiedChatRoomService.SendMessage(x => x.SendChatMessage(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedChatRoomService.SendChatMessage(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
@@ -1106,10 +1053,10 @@ public sealed class ArchiHandler : ClientMsgHandler {
steamid = steamID
};
SteamUnifiedMessages.ServiceMethodResponse response;
SteamUnifiedMessages.ServiceMethodResponse<CFriendMessages_SendMessage_Response> response;
try {
response = await UnifiedFriendMessagesService.SendMessage(x => x.SendMessage(request)).ToLongRunningTask().ConfigureAwait(false);
response = await UnifiedFriendMessagesService.SendMessage(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);

View File

@@ -34,6 +34,9 @@ using SteamKit2.Discovery;
namespace ArchiSteamFarm.Steam.SteamKit2;
internal sealed class InMemoryServerListProvider : IServerListProvider {
// TODO
public DateTime LastServerListRefresh => DateTime.MinValue;
[JsonDisallowNull]
[JsonInclude]
private ConcurrentHashSet<ServerRecordEndPoint> ServerRecords { get; init; } = [];

View File

@@ -15,7 +15,7 @@
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.9.0" />
<PackageVersion Include="SteamKit2" Version="3.0.0-Beta.4" />
<PackageVersion Include="SteamKit2" Version="3.0.0-Beta.5" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.9.0" />
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="6.9.0" />
<PackageVersion Include="System.Composition" Version="8.0.0" />