Compare commits

..

9 Commits

Author SHA1 Message Date
Łukasz Domeradzki
a313a19cec Add support for machine name 2025-09-08 22:50:23 +02:00
Łukasz Domeradzki
c5f7565ac0 Misc 2025-09-08 03:42:12 +02:00
Łukasz Domeradzki
f52486528b Cache generated swagger.json by default 2025-09-08 03:29:17 +02:00
Łukasz Domeradzki
d17399d98b Misc 2025-09-08 02:42:33 +02:00
Łukasz Domeradzki
1eadaad9bd Fix rp command not working with badge upgrades
Of course volvo had to use different endpoint for that, it'd be too easy otherwise
2025-09-08 02:41:31 +02:00
ArchiBot
22e424a78c Automatic translations update 2025-09-07 02:22:59 +00:00
renovate[bot]
712b57e46b chore(deps): update asf-ui digest to 96606b8 2025-09-06 08:37:05 +00:00
renovate[bot]
bc914f0a09 chore(deps): update asf-ui digest to 64ee49e 2025-09-05 21:29:58 +00:00
renovate[bot]
1da2ccbb1c chore(deps): update asf-ui digest to 4e72d57 2025-09-05 03:11:25 +00:00
8 changed files with 100 additions and 34 deletions

2
ASF-ui

Submodule ASF-ui updated: 62ed8b8146...96606b83ed

View File

@@ -248,6 +248,11 @@ internal static class ArchiKestrel {
// Add support for websockets that we use e.g. in /Api/NLog
app.UseWebSockets();
// Add support for output caching
if (ASF.GlobalConfig?.OptimizationMode != GlobalConfig.EOptimizationMode.MinMemoryUsage) {
app.UseOutputCache();
}
// Add additional endpoints provided by plugins
foreach (IWebServiceProvider plugin in PluginsCore.ActivePlugins.OfType<IWebServiceProvider>()) {
try {
@@ -261,7 +266,11 @@ internal static class ArchiKestrel {
app.MapControllers();
// Add support for OpenAPI, responsible for automatic API documentation generation, this should be on the end, once we're done with API
app.MapOpenApi("/swagger/{documentName}/swagger.json");
IEndpointConventionBuilder openApi = app.MapOpenApi("/swagger/{documentName}/swagger.json");
if (ASF.GlobalConfig?.OptimizationMode != GlobalConfig.EOptimizationMode.MinMemoryUsage) {
openApi.CacheOutput();
}
// Add support for swagger UI, this should be after swagger, obviously
app.MapScalarApiReference(
@@ -334,6 +343,11 @@ internal static class ArchiKestrel {
services.AddCors(static options => options.AddDefaultPolicy(static policyBuilder => policyBuilder.AllowAnyOrigin()));
}
// Add support for output caching
if (ASF.GlobalConfig?.OptimizationMode != GlobalConfig.EOptimizationMode.MinMemoryUsage) {
services.AddOutputCache();
}
// Add support for OpenAPI, responsible for automatic API documentation generation
services.AddOpenApi(
SharedInfo.ASF, static options => {

View File

@@ -2843,6 +2843,8 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
UpdateTokens(pollResult.AccessToken, pollResult.RefreshToken);
}
string machineNameFormat = !string.IsNullOrEmpty(BotConfig.MachineName) ? BotConfig.MachineName : "{0} ({1}/{2})";
SteamUser.LogOnDetails logOnDetails = new() {
AccessToken = RefreshToken,
CellID = ASF.GlobalDatabase?.CellID,
@@ -2850,6 +2852,7 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
ClientLanguage = CultureInfo.CurrentCulture.ToSteamClientLanguage(),
GamingDeviceType = BotConfig.GamingDeviceType,
LoginID = LoginID,
MachineName = string.Format(CultureInfo.CurrentCulture, machineNameFormat, Environment.MachineName, SharedInfo.PublicIdentifier, SharedInfo.Version),
ShouldRememberPassword = BotConfig.UseLoginKeys,
UIMode = BotConfig.UserInterfaceMode,
Username = username

View File

@@ -628,6 +628,37 @@ public sealed class ArchiHandler : ClientMsgHandler, IDisposable {
return response.Result;
}
[PublicAPI]
public async Task<EResult> RedeemPointsForBadgeLevel(uint definitionID, byte levels = 1) {
ArgumentOutOfRangeException.ThrowIfZero(definitionID);
ArgumentOutOfRangeException.ThrowIfZero(levels);
if (Client == null) {
throw new InvalidOperationException(nameof(Client));
}
if (!Client.IsConnected) {
return EResult.NoConnection;
}
CLoyaltyRewards_RedeemPointsForBadgeLevel_Request request = new() {
defid = definitionID,
num_levels = levels
};
SteamUnifiedMessages.ServiceMethodResponse<CLoyaltyRewards_RedeemPoints_Response> response;
try {
response = await UnifiedLoyaltyRewards.RedeemPointsForBadgeLevel(request).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return EResult.Timeout;
}
return response.Result;
}
[PublicAPI]
public async Task<bool> RemoveFriend(ulong steamID) {
if ((steamID == 0) || !new SteamID(steamID).IsIndividualAccount) {

View File

@@ -354,23 +354,23 @@ public sealed class Actions : IAsyncDisposable, IDisposable {
public async Task<EResult> RedeemPoints(uint definitionID, bool forced = false) {
ArgumentOutOfRangeException.ThrowIfZero(definitionID);
Dictionary<uint, LoyaltyRewardDefinition>? definitions = await Bot.Actions.GetRewardItems(new HashSet<uint>(1) { definitionID }).ConfigureAwait(false);
if (definitions == null) {
return EResult.Timeout;
}
if (!definitions.TryGetValue(definitionID, out LoyaltyRewardDefinition? definition)) {
return EResult.InvalidParam;
}
if (!forced) {
Dictionary<uint, LoyaltyRewardDefinition>? definitions = await Bot.Actions.GetRewardItems(new HashSet<uint>(1) { definitionID }).ConfigureAwait(false);
if (definitions == null) {
return EResult.Timeout;
}
if (!definitions.TryGetValue(definitionID, out LoyaltyRewardDefinition? definition)) {
return EResult.InvalidParam;
}
if (definition.point_cost > 0) {
return EResult.InvalidState;
}
}
return await Bot.ArchiHandler.RedeemPoints(definitionID).ConfigureAwait(false);
return definition.type == 2 ? await Bot.ArchiHandler.RedeemPointsForBadgeLevel(definitionID).ConfigureAwait(false) : await Bot.ArchiHandler.RedeemPoints(definitionID).ConfigureAwait(false);
}
[PublicAPI]

View File

@@ -72,6 +72,9 @@ public sealed class BotConfig {
[PublicAPI]
public const byte DefaultHoursUntilCardDrops = 3;
[PublicAPI]
public const string? DefaultMachineName = null;
[PublicAPI]
public const EPersonaStateFlag DefaultOnlineFlags = 0;
@@ -237,6 +240,9 @@ public sealed class BotConfig {
[JsonInclude]
public ImmutableHashSet<EAssetType> LootableTypes { get; init; } = DefaultLootableTypes;
[JsonInclude]
public string? MachineName { get; init; } = DefaultMachineName;
[JsonDisallowNull]
[JsonInclude]
public ImmutableHashSet<EAssetType> MatchableTypes { get; init; } = DefaultMatchableTypes;
@@ -409,6 +415,9 @@ public sealed class BotConfig {
[UsedImplicitly]
public bool ShouldSerializeLootableTypes() => !Saving || ((LootableTypes != DefaultLootableTypes) && !LootableTypes.SetEquals(DefaultLootableTypes));
[UsedImplicitly]
public bool ShouldSerializeMachineName() => !Saving || (MachineName != DefaultMachineName);
[UsedImplicitly]
public bool ShouldSerializeMatchableTypes() => !Saving || ((MatchableTypes != DefaultMatchableTypes) && !MatchableTypes.SetEquals(DefaultMatchableTypes));
@@ -490,6 +499,28 @@ public sealed class BotConfig {
return (false, Strings.FormatErrorConfigPropertyInvalid(nameof(BotBehaviour), BotBehaviour));
}
HashSet<EAssetType>? completeTypesToSendValidTypes = null;
foreach (EAssetType completableType in CompleteTypesToSend) {
if (!Enum.IsDefined(completableType)) {
return (false, Strings.FormatErrorConfigPropertyInvalid(nameof(CompleteTypesToSend), completableType));
}
if (completeTypesToSendValidTypes == null) {
SwaggerValidValuesAttribute? completeTypesToSendValidValues = typeof(BotConfig).GetProperty(nameof(CompleteTypesToSend))?.GetCustomAttribute<SwaggerValidValuesAttribute>();
if (completeTypesToSendValidValues?.ValidIntValues == null) {
throw new InvalidOperationException(nameof(completeTypesToSendValidValues));
}
completeTypesToSendValidTypes = completeTypesToSendValidValues.ValidIntValues.Select(static value => (EAssetType) value).ToHashSet();
}
if (!completeTypesToSendValidTypes.Contains(completableType)) {
return (false, Strings.FormatErrorConfigPropertyInvalid(nameof(CompleteTypesToSend), completableType));
}
}
if (!string.IsNullOrEmpty(CustomGamePlayedWhileFarming)) {
try {
// Test CustomGamePlayedWhileFarming against supported format, otherwise we'll throw later when used
@@ -519,25 +550,12 @@ public sealed class BotConfig {
return (false, Strings.FormatErrorConfigPropertyInvalid(nameof(LootableTypes), lootableType));
}
HashSet<EAssetType>? completeTypesToSendValidTypes = null;
foreach (EAssetType completableType in CompleteTypesToSend) {
if (!Enum.IsDefined(completableType)) {
return (false, Strings.FormatErrorConfigPropertyInvalid(nameof(CompleteTypesToSend), completableType));
}
if (completeTypesToSendValidTypes == null) {
SwaggerValidValuesAttribute? completeTypesToSendValidValues = typeof(BotConfig).GetProperty(nameof(CompleteTypesToSend))?.GetCustomAttribute<SwaggerValidValuesAttribute>();
if (completeTypesToSendValidValues?.ValidIntValues == null) {
throw new InvalidOperationException(nameof(completeTypesToSendValidValues));
}
completeTypesToSendValidTypes = completeTypesToSendValidValues.ValidIntValues.Select(static value => (EAssetType) value).ToHashSet();
}
if (!completeTypesToSendValidTypes.Contains(completableType)) {
return (false, Strings.FormatErrorConfigPropertyInvalid(nameof(CompleteTypesToSend), completableType));
if (!string.IsNullOrEmpty(MachineName)) {
try {
// Test MachineName against supported format, otherwise we'll throw later when used
string _ = string.Format(CultureInfo.CurrentCulture, MachineName, null, null, null);
} catch (FormatException e) {
return (false, Strings.FormatErrorConfigPropertyInvalid(nameof(MachineName), e.Message));
}
}

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>6.2.2.0</Version>
<Version>6.2.2.1</Version>
</PropertyGroup>
<PropertyGroup>

2
wiki

Submodule wiki updated: 893ba0c20f...4b2274ec5a