Compare commits

...

8 Commits

Author SHA1 Message Date
wangyingpan 6a726e151b 🎨 调整代码结构 2024-06-06 14:38:09 +08:00
wangyingpan 979cd83662 解决冲突 2024-06-05 09:50:36 +08:00
wangyingpan 48234a8a7e 🎨 调整提示文本 2024-06-04 17:43:17 +08:00
wangyingpan 513f32c309 🎨 改善共存令牌处理逻辑,优化文本 2024-06-04 17:43:14 +08:00
wangyingpan bbe6e4f68f ✨ 导入steam令牌 新增添加 联合steam 令牌方式 2024-06-04 17:42:36 +08:00
wangyingpan 58e5147e14 🎨 调整提示文本 2024-06-04 17:10:33 +08:00
wangyingpan 11ea59fb3b 🎨 改善共存令牌处理逻辑,优化文本 2024-06-04 16:55:57 +08:00
wangyingpan 8b6010b36a ✨ 导入steam令牌 新增添加 联合steam 令牌方式 2024-05-30 15:21:26 +08:00
7 changed files with 1750 additions and 983 deletions
@@ -90,6 +90,9 @@
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="UI\Views\Pages\JoinSteamAuthenticatorPage.axaml.cs">
<DependentUpon>JoinSteamAuthenticatorPage.axaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
@@ -1,6 +1,6 @@
using SJsonSerializer = System.Text.Json.JsonSerializer;
using BD.WTTS.UI.Views.Pages;
using WinAuth;
using SJsonSerializer = System.Text.Json.JsonSerializer;
namespace BD.WTTS.UI.ViewModels;
@@ -26,6 +26,8 @@ public class AuthenticatorImportPageViewModel : ViewModelBase
if (await AuthenticatorHelper.VerifyMaxValue())
await ImportFromSdaFile();
})),
new AuthenticatorImportMethod(Strings.LocalAuth_Import.Format(Strings.LocalAuth_JoinSteamAuthenticator), Strings.LocalAuth_JoinSteamAuthenticatorDesc,
PageType: typeof(JoinSteamAuthenticatorPage)),
new AuthenticatorImportMethod(Strings.LocalAuth_Import.Format(Strings.WattToolKitV2), Strings.LocalAuth_WattToolKitV2Import,
Command: ReactiveCommand.Create(async () =>
{
@@ -123,6 +125,7 @@ public class AuthenticatorImportPageViewModel : ViewModelBase
? Strings.LocalAuth_AddAuthSuccess
: Strings.LocalAuth_AddAuth_PartSuccess);
break;
case IAccountPlatformAuthenticatorRepository.ImportResultCode.SecondaryPasswordFail:
Toast.Show(ToastIcon.Warning, Strings.LocalAuth_ProtectionAuth_PasswordErrorTip);
var textViewModel =
@@ -136,6 +139,7 @@ public class AuthenticatorImportPageViewModel : ViewModelBase
}
await ImportFromWattToolKitV2(exportPassword, password, isLocalProtect, filePath);
break;
default:
Toast.Show(ToastIcon.Error, Strings.LocalAuth_ExportAuth_Error.Format(result.resultCode));
break;
@@ -0,0 +1,442 @@
using BD.SteamClient.Models;
using BD.SteamClient.Services;
using WinAuth;
using AppResources = BD.WTTS.Client.Resources.Strings;
namespace BD.WTTS.UI.ViewModels;
/// <summary>
/// 联合Steam令牌页面
/// </summary>
public sealed partial class JoinSteamAuthenticatorPageViewModel : ViewModelBase
{
#region 步骤索引常量
const int STEPINDEX_LOGIN = 0;
const int STEPINDEX_VERIFY = 1;
const int STEPINDEX_DONE = 2;
#endregion 步骤索引常量
#region 页面属性
/// <summary>
/// 用户填入的 Steam 令牌验证码
/// </summary>
[Reactive]
public string? Code { get; set; }
/// <summary>
/// 用户名
/// </summary>
[Reactive]
public string? UserNameText { get; set; }
/// <summary>
/// 密码
/// </summary>
[Reactive]
public string? PasswordText { get; set; }
/// <summary>
/// 验证码
/// </summary>
[Reactive]
public string? VerifyCodeText { get; set; }
/// <summary>
/// 恢复代码
/// </summary>
[Reactive]
public string? RevocationCodeText { get; set; }
/// <summary>
/// 当前步骤
/// </summary>
[Reactive]
public int SelectIndex { get; set; } = STEPINDEX_LOGIN;
/// <summary>
/// 加载
/// </summary>
[Reactive]
public bool Loading { get; set; } = false;
/// <summary>
/// 是否需要验证码
/// </summary>
[Reactive]
public bool RequireVerifyCode { get; set; } = false;
#endregion 页面属性
#region 私有变量
/// <summary>
/// Steam 账号服务
/// </summary>
private static readonly ISteamAccountService _steamAccountService = Ioc.Get<ISteamAccountService>();
/// <summary>
/// 当前页面待导入的 Steam Authenticator
/// </summary>
private SteamAuthenticator? _currentSteamAuthenticator;
private SteamLoginState? _currentSteamLoginState;
#endregion 私有变量
#region 联合 Steam令牌 页面流程
/// <summary>
/// 登录
/// </summary>
/// <returns></returns>
public async Task LoginAsync()
{
if (Loading)
return;
Loading = true;
try
{
if (string.IsNullOrEmpty(UserNameText) || string.IsNullOrEmpty(PasswordText))
{
Toast.Show(ToastIcon.Error, AppResources.Error_PleaseEnterUsernamePassword);
return;
}
// 初始化登录状态
var loginState = _currentSteamLoginState ??= new SteamLoginState();
loginState.Username = UserNameText;
loginState.Password = PasswordText;
loginState.Language = ResourceService.GetCurrentCultureSteamLanguageName();
if (RequireVerifyCode && loginState.RequiresEmailAuth)
{
loginState.EmailCode = VerifyCodeText;
}
try
{
// 开始登录
await _steamAccountService.DoLoginV2Async(loginState);
}
catch (HttpRequestException)
{
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_LoginRequestError);
return;
}
// 登陆结果
if (!loginState.Success)
{
if (loginState.RequiresEmailAuth)
{
RequireVerifyCode = true;
Toast.Show(ToastIcon.Info, Strings.LocalAuth_EmailCodeTip);
return;
}
else if (loginState.Requires2FA)
{
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_SteamUser_Requires2FA);
return;
}
else
{
Toast.Show(ToastIcon.Error, loginState.Message ?? string.Empty);
}
return;
}
// 根据登录信息 获取/初始化 TwoFA Steam Authenticator 信息
var (initialized, errMsg) = await InitTwoFASteamAuthenticatorAsync(loginState);
if (!initialized)
{
Toast.Show(ToastIcon.Error, errMsg);
return;
}
RevocationCodeText = _currentSteamAuthenticator!.RecoveryCode;
// 跳转到验证页面
SelectIndex = STEPINDEX_VERIFY;
}
finally
{
Loading = false;
}
}
/// <summary>
/// 校验验证码
/// </summary>
/// <returns></returns>
public async Task VerifyCodeAsync()
{
if (Loading)
return;
Loading = true;
try
{
if (string.IsNullOrWhiteSpace(Code))
{
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_SteamGuardCodeEmptyError);
return;
}
var equals = await CompareCodeAsync();
if (!equals)
{
Toast.Show(ToastIcon.Warning,
$@"{AppResources.LocalAuth_JoinSteamAuthenticator_VerifySteamGuardCodeError}: {Code} != {_currentSteamAuthenticator?.CurrentCode}");
return;
}
RevocationCodeText = _currentSteamAuthenticator!.RecoveryCode;
SelectIndex = STEPINDEX_DONE;
}
finally
{
Loading = false;
}
}
/// <summary>
/// 保存令牌
/// </summary>
/// <returns></returns>
public async Task SaveAsync()
{
if (Loading)
return;
Loading = true;
try
{
if (_currentSteamAuthenticator == null)
{
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_InitLocalAuthenticatorError);
SelectIndex = STEPINDEX_LOGIN;
return;
}
if (string.IsNullOrEmpty(Code))
{
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_SteamGuardCodeEmptyError);
SelectIndex = STEPINDEX_VERIFY;
return;
}
if (!await SaveAuthenticatorAsync(UserNameText!, _currentSteamAuthenticator))
{
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_SaveLocalAuthenticatorError);
return;
}
// 保存完成重置
Reset();
}
finally
{
Loading = false;
}
}
/// <summary>
/// 重置恢复代码
/// </summary>
/// <returns></returns>
public async Task ResetRevocationCodeAsync()
{
if (_currentSteamLoginState == null)
{
return;
}
// 根据登录信息 获取/初始化 TwoFA Steam Authenticator 信息
var (initialized, errMsg) = await InitTwoFASteamAuthenticatorAsync(_currentSteamLoginState);
if (!initialized)
{
Toast.Show(ToastIcon.Error, errMsg);
return;
}
RevocationCodeText = _currentSteamAuthenticator!.RecoveryCode;
}
#endregion 联合 Steam令牌 页面流程
#region 辅助方法
/// <summary>
/// 初始化 TwoFA Steam Authenticator 信息
/// </summary>
/// <param name="loginState"></param>
/// <returns></returns>
private async Task<(bool initialized, string errorMsg)> InitTwoFASteamAuthenticatorAsync(SteamLoginState loginState)
{
_currentSteamAuthenticator = new SteamAuthenticator();
string? steamId = loginState.SteamId != default
? loginState.SteamId.ToString()
: null;
if (string.IsNullOrEmpty(steamId))
return (false, $"{AppResources.LocalAuth_JoinSteamAuthenticator_InitLocalAuthenticatorError}:{nameof(steamId)}");
string deviceId = CreateNewDeviceId();
var client = _currentSteamAuthenticator.GetClient();
string authenticatorJson;
try
{
authenticatorJson = await client
.AddAuthenticatorAsync(
steamId,
DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(),
deviceId,
loginState.AccessToken ?? string.Empty
);
}
catch (Exception ex)
{
return (false, $"{AppResources.LocalAuth_JoinSteamAuthenticator_RequestUser2FAInfoError}:{ex.Message}");
}
if (string.IsNullOrEmpty(authenticatorJson))
return (false, AppResources.LocalAuth_JoinSteamAuthenticator_RequestUser2FAInfoError);
var (initialized, msg) = TryParseSteamAuthenticator(authenticatorJson, out var parsedSteamData)
? (true, string.Empty)
: (false, AppResources.LocalAuth_JoinSteamAuthenticator_ParseUser2FAInfoError);
// 解析响应之后赋值给当前本地令牌
if (initialized)
{
_currentSteamAuthenticator.DeviceId = deviceId;
_currentSteamAuthenticator.SteamData = SystemTextJsonSerializer.Serialize(parsedSteamData!, SteamJsonContext.Default.SteamConvertSteamDataJsonStruct);
_currentSteamAuthenticator.SecretKey = Base64Extensions.Base64DecodeToByteArray_Nullable(parsedSteamData!.SharedSecret);
_currentSteamAuthenticator.Serial = parsedSteamData.SerialNumber;
}
return (initialized, msg);
}
/// <summary>
/// 验证令牌验证码
/// </summary>
/// <returns></returns>
private async Task<bool> CompareCodeAsync()
{
if (_currentSteamAuthenticator == null)
{
return false;
}
try
{
await Task.Yield();
_currentSteamAuthenticator.Sync();
}
catch (Exception ex)
{
ex.LogAndShowT();
return false;
}
bool compareResult = string.Equals(Code, _currentSteamAuthenticator?.CurrentCode, StringComparison.OrdinalIgnoreCase);
return compareResult;
}
/// <summary>
/// 解析 Steam Authenticator json响应
/// </summary>
/// <param name="authenticatorJson"></param>
/// <param name="parsedSteamAuthenticator">已解析的响应信息</param>
/// <returns></returns>
private static bool TryParseSteamAuthenticator(string authenticatorJson, out SteamConvertSteamDataJsonStruct? parsedSteamAuthenticator)
{
parsedSteamAuthenticator = default;
SteamDoLoginTfaJsonStruct? authenticatorDataResp;
try
{
authenticatorDataResp = SystemTextJsonSerializer.Deserialize(
authenticatorJson,
SteamJsonContext.Default.SteamDoLoginTfaJsonStruct
);
}
catch (Exception)
{
return false;
}
if (authenticatorDataResp == null || authenticatorDataResp.Response == null)
return false;
parsedSteamAuthenticator = authenticatorDataResp.Response;
// 目前只需要知道是否含有令牌数据信息
// 不需要知道当前状态可不可以绑定,绑定操作在 Steam App 中完成
// 这里只是将令牌数据保存到本地 以便后续计算
return parsedSteamAuthenticator != null;
}
/// <summary>
/// 保存令牌
/// </summary>
/// <param name="authenticatorName"></param>
/// <param name="authenticator"></param>
/// <returns></returns>
private static Task<bool> SaveAuthenticatorAsync(string authenticatorName, SteamAuthenticator authenticator)
{
var iADTO = new AuthenticatorDTO
{
Name = $"Steam({authenticatorName})",
Value = authenticator,
Created = DateTimeOffset.Now,
};
return AuthenticatorHelper.SaveAuthenticator(iADTO);
}
/// <summary>
/// 创建新的设备ID
/// </summary>
/// <returns></returns>
private static string CreateNewDeviceId() => $"android:{Guid.NewGuid()}";
/// <summary>
/// 重置页面绑定信息
/// </summary>
public void Reset()
{
UserNameText = default;
PasswordText = default;
Code = default;
VerifyCodeText = default;
RequireVerifyCode = default;
RevocationCodeText = default;
SelectIndex = STEPINDEX_LOGIN;
_currentSteamAuthenticator = default;
_currentSteamLoginState = default;
}
#endregion 辅助方法
}
@@ -0,0 +1,149 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:s="https://steampp.net/services"
xmlns:spp="https://steampp.net/ui"
x:CompileBindings="True"
x:DataType="spp:JoinSteamAuthenticatorPageViewModel"
x:Class="BD.WTTS.UI.Views.Pages.JoinSteamAuthenticatorPage"
mc:Ignorable="d">
<Grid RowDefinitions="Auto,*">
<spp:Stepper SelectedIndex="{Binding SelectIndex}">
<spp:StepperItem Content="{Binding Path=Res.Steam_Login, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<spp:StepperItem Content="{Binding Path=Res.LocalAuth_JoinSteamAuthenticator_ConfirmSteamAppAuthenticatorCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<spp:StepperItem Content="{Binding Path=Res.Btn_Text_Complete, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</spp:Stepper>
<spp:ContentLoader
Grid.Row="1"
MinWidth="600"
MinHeight="400"
IsLoading="{Binding Loading}"
IsShowNoResultText="False">
<Carousel IsVisible="{Binding !Loading}" SelectedIndex="{Binding SelectIndex}">
<Panel>
<spp:Snackbar
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
VerticalAlignment="Top"
IsClosable="False"
IsOpen="True"
IsVisible="{Binding RequireVerifyCode}"
Message="{Binding Path=Res.LocalAuth_EmailCodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<PathIcon
Width="88"
Height="88"
Data="{StaticResource Steam}" />
<TextBox
MaxWidth="280"
Text="{Binding UserNameText}"
Watermark="{Binding Path=Res.Steam_User, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="PasswordText"
MaxWidth="280"
Classes="revealPasswordButton"
PasswordChar="{StaticResource PasswordChar}"
Text="{Binding PasswordText}"
Watermark="{Binding Path=Res.Steam_Password, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
IsVisible="{Binding RequireVerifyCode}"
Watermark="{Binding Path=Res.EmailCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Text="{Binding VerifyCodeText}" />
<Button
MinWidth="280"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
HorizontalContentAlignment="Center"
Command="{Binding LoginAsync}"
Content="{Binding Path=Res.Login, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Panel>
<Panel>
<spp:Snackbar
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
VerticalAlignment="Top"
IsClosable="False"
IsOpen="True"
Message="{Binding Path=Res.LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCodeTips, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<DockPanel>
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
Text="{Binding Path=Res.RecoveryCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
MaxWidth="300"
Text="{Binding RevocationCodeText}"
IsReadOnly="True" />
<!--<Button
Content="重新生成"
Command="{Binding ResetRevocationCodeAsync}" />-->
</DockPanel>
<DockPanel>
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
Text="{Binding Path=Res.LocalAuth_JoinSteamAuthenticator_SteamAppAuthenticatorCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
MaxWidth="300"
Watermark="{Binding Path=Res.LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Text="{Binding Code}" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding VerifyCodeAsync}"
Content="{Binding Path=Res.Continue, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Panel>
<Panel>
<spp:Snackbar
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
VerticalAlignment="Top"
IsClosable="False"
IsOpen="True"
Message="{Binding Path=Res.RecoveryCode_RememberTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Success" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<DockPanel>
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
Text="{Binding Path=Res.RecoveryCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
MaxWidth="300"
Text="{Binding RevocationCodeText}"
IsReadOnly="True" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding SaveAsync}"
Content="{Binding Path=Res.Confirm, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Panel>
</Carousel>
</spp:ContentLoader>
</Grid>
</UserControl>
@@ -0,0 +1,13 @@
using Avalonia.Controls;
namespace BD.WTTS.UI.Views.Pages;
public partial class JoinSteamAuthenticatorPage : UserControl
{
public JoinSteamAuthenticatorPage()
{
InitializeComponent();
DataContext = new JoinSteamAuthenticatorPageViewModel();
}
}
+117
View File
@@ -4195,6 +4195,123 @@ namespace BD.WTTS.Client.Resources {
}
}
/// <summary>
/// 查找类似 共存令牌 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator", resourceCulture);
}
}
/// <summary>
/// 查找类似 确认 Steam App 令牌验证码 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_ConfirmSteamAppAuthenticatorCode {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_ConfirmSteamAppAuthenticatorCode", resourceCulture);
}
}
/// <summary>
/// 查找类似 初始化本地令牌错误 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_InitLocalAuthenticatorError {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_InitLocalAuthenticatorError", resourceCulture);
}
}
/// <summary>
/// 查找类似 请输入 Steam App 中显示的令牌验证码 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCode {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCode", resourceCulture);
}
}
/// <summary>
/// 查找类似 打开 Steam App 绑定令牌后在此页面输入验证 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCodeTips {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCodeTips", resourceCulture);
}
}
/// <summary>
/// 查找类似 登录请求错误 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_LoginRequestError {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_LoginRequestError", resourceCulture);
}
}
/// <summary>
/// 查找类似 解析用户 Steam 令牌信息失败 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_ParseUser2FAInfoError {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_ParseUser2FAInfoError", resourceCulture);
}
}
/// <summary>
/// 查找类似 获取用户 Steam 令牌信息失败 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_RequestUser2FAInfoError {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_RequestUser2FAInfoError", resourceCulture);
}
}
/// <summary>
/// 查找类似 保存令牌失败 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_SaveLocalAuthenticatorError {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_SaveLocalAuthenticatorError", resourceCulture);
}
}
/// <summary>
/// 查找类似 Steam App 令牌验证码 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_SteamAppAuthenticatorCode {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_SteamAppAuthenticatorCode", resourceCulture);
}
}
/// <summary>
/// 查找类似 请输入已在 Steam App 中绑定的令牌当前的令牌验证码 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_SteamGuardCodeEmptyError {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_SteamGuardCodeEmptyError", resourceCulture);
}
}
/// <summary>
/// 查找类似 验证令牌错误 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticator_VerifySteamGuardCodeError {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_VerifySteamGuardCodeError", resourceCulture);
}
}
/// <summary>
/// 查找类似 在 Watt Toolkit 中与官方 Steam App 中使用相同的令牌信息 的本地化字符串。
/// </summary>
public static string LocalAuth_JoinSteamAuthenticatorDesc {
get {
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticatorDesc", resourceCulture);
}
}
/// <summary>
/// 查找类似 确定要注销当前令牌登录的账号信息吗? 的本地化字符串。
/// </summary>
File diff suppressed because it is too large Load Diff