Compare commits

..
34 Commits
Author SHA1 Message Date
rmbgame f395383db8 修改steam社区商店页的代理上游
修复成就窗口关闭游戏依然运行
2020-12-27 14:29:15 +08:00
rmbgame f805911f4e 准备更新挂卡功能,修复托盘启动多个窗口问题 2020-12-27 12:53:50 +08:00
rmbgame b3d203fbda 1.0.3.2 2020-12-27 01:33:55 +08:00
rmbgame bb022f45fd 优化令牌的加载 2020-12-27 01:33:49 +08:00
rmbgame e4a97463f4 修复程序最小化启动时弹窗报错 2020-12-27 00:59:53 +08:00
rmbgame 11adabb749 添加steam图片修复和pixiv代理选项 2020-12-26 22:19:42 +08:00
rmbgame 8a7ad67363 修改初始化和steamapi连接方式 2020-12-26 20:02:15 +08:00
rmbgame 7af0888b0a 修复一个因为DNS解析错误会导致程序内存溢出闪退的BUG 2020-12-26 19:21:01 +08:00
rmbgame 42fc93a524 修复最小化UI错位BUG 2020-12-26 19:20:48 +08:00
rmbgame 5c832f489b 修复在令牌初始化时犯下的一个愚蠢问题导致令牌各种非空报错
修改帐户切换的最近登录时间为当前电脑时区显示
2020-12-26 19:19:50 +08:00
rmbgame 5e7ed26bc6 add static resources 2020-12-23 01:25:40 +08:00
rmbgame 085ad3d944 修改多语言文本
修改部分相对路径为绝对路径
2020-12-22 13:00:10 +08:00
rmbgame 334503445c edit text 2020-12-22 13:00:03 +08:00
rmbgame cf17ca8dd6 ready 1.0.2 2020-12-21 21:18:14 +08:00
rmbgame 0b88de7195 添加了自动更新检测功能 2020-12-21 21:17:49 +08:00
rmbgame 3342e35440 bug fix 2020-12-21 21:17:43 +08:00
rmbgame 56baba4a53 修复了443端口占用只会提示一次的问题 2020-12-21 21:17:38 +08:00
rmbgame 8b1a946fe2 添加discord代理选项 2020-12-20 14:57:34 +08:00
rmbgame 9e08c0b7c4 优化反代启用时内存占用
添加github图片资源文件代理服务支持
2020-12-20 14:57:18 +08:00
rmbgame 3a38333dfc 移除无用代码,修正一个命名错误 2020-12-20 14:57:04 +08:00
rmbgame 16d1bba515 update readme 2020-12-20 00:21:35 +08:00
rmbgame 00cf9da911 修复了程序启动时自动启动代理脚本不生效的问题
因为有问题暂时去掉了GOG Galaxy代理选项
增加捐助列表的展示
增加启动时程序最小化到托盘菜单设置
2020-12-20 00:14:22 +08:00
rmbgame 088256faf9 修复一个会导致steam未连接文字闪烁的BUG 2020-12-20 00:14:17 +08:00
rmbgame ca244edc51 sync gitee 2020-12-19 00:24:56 +08:00
rmbgame c91608da09 update readme 2020-12-19 00:23:49 +08:00
rmbgame 2945e9fa3e 更新了新的图标
增加steam启动参数设置
修复了一些文本bug
2020-12-19 00:22:54 +08:00
rmbgame 1f0a40cd3b 新增帐户切换删除功能(凑合用)
修复一个会导致程序启动没有反应的bug
修复托盘菜单steam昵称过长ui错位bug
修正了配置文件夹命名错误(1.0.0版本更新后设置会被重置)
2020-12-19 00:07:02 +08:00
rmbgame b1fbe64ab2 update readme 2020-12-17 17:19:28 +08:00
rmbgame 9a13665e68 ready 1.0.0 2020-12-17 12:09:47 +08:00
rmbgame 5c0f71f4a7 sync gitee 2020-12-16 10:45:03 +08:00
rmbgame 3e045e5db0 delete ref lib 2020-12-16 10:33:43 +08:00
rmbgame c4f99906ab update 2020-12-16 10:29:55 +08:00
rmbgame 94e50f663b 删除无用代码 2020-12-15 23:35:17 +08:00
rmbgame 49e08101c6 delete error ref 2020-12-15 23:29:36 +08:00
125 changed files with 2204 additions and 1646 deletions
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 427 KiB

+155
View File
@@ -0,0 +1,155 @@
[
{
"Index": 1,
"Name": "*瑞",
"Amount": 5,
"OrderNumber": "",
"PayType": 1,
"Remark": "请大佬喝瓶饮料",
"PayTime": "2020-12-17 19:41:57"
},
{
"Index": 2,
"Name": "**耀",
"Amount": 5,
"OrderNumber": "",
"PayType": 1,
"Remark": "小小支持一波!",
"PayTime": "2020-12-17 20:46:01"
},
{
"Index": 3,
"Name": "**皓",
"Amount": 1,
"OrderNumber": "",
"PayType": 1,
"Remark": "2077掏空了我,等挂卡出来。在。。em",
"PayTime": "2020-12-17 22:41:27"
},
{
"Index": 4,
"Name": "**宇",
"Amount": 1,
"OrderNumber": "",
"PayType": 1,
"Remark": "",
"PayTime": "2020-12-18 08:39:42"
},
{
"Index": 5,
"Name": "*钊",
"Amount": 20,
"OrderNumber": "",
"PayType": 1,
"Remark": "其乐坛友bzll6538一点心意",
"PayTime": "2020-12-19 17:10:44"
},
{
"Index": 6,
"Name": "R*n",
"Amount": 20,
"OrderNumber": "",
"PayType": 2,
"Remark": "绿豆",
"PayTime": "2020-12-17 14:32:00"
},
{
"Index": 7,
"Name": "*炜",
"Amount": 100,
"OrderNumber": "",
"PayType": 1,
"Remark": "其乐坛友Davyheaven",
"PayTime": "2020-12-20 12:02:17"
},
{
"Index": 8,
"Name": "**智",
"Amount": 20,
"OrderNumber": "",
"PayType": 1,
"Remark": "派大星",
"PayTime": "2020-12-20 12:21:04"
},
{
"Index": 9,
"Name": "*森",
"Amount": 66,
"OrderNumber": "",
"PayType": 1,
"Remark": "区区心意,不成敬意(三个六给不起)",
"PayTime": "2020-12-21 23:03:26"
},
{
"Index": 10,
"Name": "*珂",
"Amount": 50,
"OrderNumber": "",
"PayType": 1,
"Remark": "其乐YK93,支持大佬",
"PayTime": "2020-12-21 23:18:09"
},
{
"Index": 11,
"Name": "**丰",
"Amount": 1,
"OrderNumber": "",
"PayType": 1,
"Remark": "",
"PayTime": "2020-12-22 12:33:46"
},
{
"Index": 12,
"Name": "Ruby",
"Amount": 77,
"OrderNumber": "",
"PayType": 2,
"Remark": "资瓷一下",
"PayTime": "2020-12-24 19:40:25"
},
{
"Index": 13,
"Name": "**桐",
"Amount": 1,
"OrderNumber": "",
"PayType": 1,
"Remark": "",
"PayTime": "2020-12-26 09:32:57"
},
{
"Index": 14,
"Name": "**珂",
"Amount": 5,
"OrderNumber": "",
"PayType": 1,
"Remark": "其乐坛友wjkhj123,小小支持一波",
"PayTime": "2020-12-26 13:28:07"
},
{
"Index": 15,
"Name": "z.w",
"Amount": 10,
"OrderNumber": "",
"PayType": 2,
"Remark": "滋瓷一下",
"PayTime": "2020-12-26 15:34:50"
},
{
"Index": 16,
"Name": "**林",
"Amount": 6,
"OrderNumber": "",
"PayType": 2,
"Remark": "一丶心意,大佬加油!",
"PayTime": "2020-12-26 18:25:06"
},
{
"Index": 17,
"Name": "**立",
"Amount": 1,
"OrderNumber": "",
"PayType": 2,
"Remark": "",
"PayTime": "2020-12-26 18:56:57"
}
]
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
View File
Binary file not shown.
+1 -2
View File
@@ -1,6 +1,5 @@
# Steam++工具箱 v1.0
# Steam++ SteamTools
------
「Steam++」是一个包含多种Steam工具功能的工具箱。
+9 -6
View File
@@ -1,6 +1,4 @@
# Steam++工具箱 v1.0
------
# Steam++工具箱
「Steam++」是一个包含多种Steam工具功能的工具箱。
@@ -39,7 +37,7 @@
## 预计后续添加的功能
### Steam自动挂卡
尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内登录Steam即可直接获取徽章卡片信息并开始挂卡。
尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内无需登录Steam帐户即可直接获取徽章卡片信息并开始挂卡。
### Steam皮肤设计器
挖坑画大饼,可视化编辑Steam皮肤,而且如果软件能上架Steam的话打算支持创意工坊分享设计的Steam皮肤,短期内肯定做不完。
@@ -58,7 +56,10 @@
---
## 运行环境
> 程序使用C# WPF在 .NET Framework4.7.2环境下开发,如果无法运行请下载安装[.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)。
> 程序使用C# WPF在 .NET Framework4.7.2环境下开发,如果无法运行请下载安装[.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)。
> 缺失的程序集为我自己修改后的项目
* [Titanium-Web-Proxy](https://github.com/rmbadmin/Titanium-Web-Proxy)
* [MetroRadiance](https://github.com/rmbadmin/MetroRadiance)
---
@@ -83,4 +84,6 @@
* [SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)
* [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm)
* [WinAuth](https://github.com/winauth/winauth)
* [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
* [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
* [Gameloop.Vdf](https://github.com/shravan2x/Gameloop.Vdf)
* [Costura.Fody](https://github.com/Fody/Costura)
-249
View File
@@ -1,249 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using WinAuth;
namespace SteamTool.Auth
{
public static class AuthService
{
/// <summary>
/// Import a file containing authenticators in the KeyUriFormat. The file might be plain text, encrypted zip or encrypted pgp.
/// </summary>
/// <param name="parent">parent Form</param>
/// <param name="file">file name to import</param>
/// <returns>list of imported authenticators</returns>
public static List<WinAuthAuthenticator> ImportAuthenticators(string file)
{
List<WinAuthAuthenticator> authenticators = new List<WinAuthAuthenticator>();
StringBuilder lines = new StringBuilder();
bool retry;
do
{
retry = false;
lines.Length = 0;
// read a plain text file
lines.Append(File.ReadAllText(file));
} while (retry);
int linenumber = 0;
try
{
using (var sr = new StringReader(lines.ToString()))
{
string line;
while ((line = sr.ReadLine()) != null)
{
linenumber++;
// ignore blank lines or comments
line = line.Trim();
if (line.Length == 0 || line.IndexOf("#") == 0)
{
continue;
}
// bug if there is a hash before ?
var hash = line.IndexOf("#");
var qm = line.IndexOf("?");
if (hash != -1 && hash < qm)
{
line = line.Substring(0, hash) + "%23" + line.Substring(hash + 1);
}
// parse and validate URI
var uri = new Uri(line);
// we only support "otpauth"
if (uri.Scheme != "otpauth")
{
throw new ApplicationException("Import only supports otpauth://");
}
// we only support totp (not hotp)
if (uri.Host != "totp" && uri.Host != "hotp")
{
throw new ApplicationException("Import only supports otpauth://totp/ or otpauth://hotp/");
}
// get the label and optional issuer
string issuer = string.Empty;
string label = (string.IsNullOrEmpty(uri.LocalPath) == false ? uri.LocalPath.Substring(1) : string.Empty); // skip past initial /
int p = label.IndexOf(":");
if (p != -1)
{
issuer = label.Substring(0, p);
label = label.Substring(p + 1);
}
// + aren't decoded
label = label.Replace("+", " ");
var query = HttpUtility.ParseQueryString(uri.Query);
string secret = query["secret"];
if (string.IsNullOrEmpty(secret) == true)
{
throw new ApplicationException("Authenticator does not contain secret");
}
string counter = query["counter"];
if (uri.Host == "hotp" && string.IsNullOrEmpty(counter) == true)
{
throw new ApplicationException("HOTP authenticator should have a counter");
}
WinAuthAuthenticator importedAuthenticator = new WinAuthAuthenticator
{
AutoRefresh = false
};
//
Authenticator auth;
if (string.Compare(issuer, "BattleNet", true) == 0)
{
string serial = query["serial"];
if (string.IsNullOrEmpty(serial) == true)
{
throw new ApplicationException("Battle.net Authenticator does not have a serial");
}
serial = serial.ToUpper();
if (Regex.IsMatch(serial, @"^[A-Z]{2}-?[\d]{4}-?[\d]{4}-?[\d]{4}$") == false)
{
throw new ApplicationException("Invalid serial for Battle.net Authenticator");
}
auth = new BattleNetAuthenticator();
//char[] decoded = Base32.getInstance().Decode(secret).Select(c => Convert.ToChar(c)).ToArray(); // this is hex string values
//string hex = new string(decoded);
//((BattleNetAuthenticator)auth).SecretKey = Authenticator.StringToByteArray(hex);
((BattleNetAuthenticator)auth).SecretKey = Base32.getInstance().Decode(secret);
((BattleNetAuthenticator)auth).Serial = serial;
issuer = string.Empty;
}
else if (string.Compare(issuer, "Steam", true) == 0)
{
auth = new SteamAuthenticator();
((SteamAuthenticator)auth).SecretKey = Base32.getInstance().Decode(secret);
((SteamAuthenticator)auth).Serial = string.Empty;
((SteamAuthenticator)auth).DeviceId = query["deviceid"] ?? string.Empty;
((SteamAuthenticator)auth).SteamData = query["data"] ?? string.Empty;
issuer = string.Empty;
}
else if (uri.Host == "hotp")
{
auth = new HOTPAuthenticator();
((HOTPAuthenticator)auth).SecretKey = Base32.getInstance().Decode(secret);
((HOTPAuthenticator)auth).Counter = int.Parse(counter);
if (string.IsNullOrEmpty(issuer) == false)
{
auth.Issuer = issuer;
}
}
else // if (string.Compare(issuer, "Google", true) == 0)
{
auth = new GoogleAuthenticator();
((GoogleAuthenticator)auth).Enroll(secret);
if (string.Compare(issuer, "Google", true) == 0)
{
issuer = string.Empty;
}
else if (string.IsNullOrEmpty(issuer) == false)
{
auth.Issuer = issuer;
}
}
int period = 0;
int.TryParse(query["period"], out period);
if (period != 0)
{
auth.Period = period;
}
int digits = 0;
int.TryParse(query["digits"], out digits);
if (digits != 0)
{
auth.CodeDigits = digits;
}
Authenticator.HMACTypes hmactype;
if (Enum.TryParse<Authenticator.HMACTypes>(query["algorithm"], true, out hmactype) == true)
{
auth.HMACType = hmactype;
}
//
if (label.Length != 0)
{
importedAuthenticator.Name = (issuer.Length != 0 ? issuer + " (" + label + ")" : label);
}
else if (issuer.Length != 0)
{
importedAuthenticator.Name = issuer;
}
else
{
importedAuthenticator.Name = "Imported";
}
//
importedAuthenticator.AuthenticatorData = auth;
// sync
importedAuthenticator.Sync();
authenticators.Add(importedAuthenticator);
}
}
return authenticators;
}
catch (UriFormatException ex)
{
throw new ImportException(string.Format("Invalid authenticator at line {0}", linenumber), ex);
}
catch (Exception ex)
{
throw new ImportException(string.Format("Error importing at line {0}:{1}", ex.Message), ex);
}
}
public static string ExportAuthenticators(IList<WinAuthAuthenticator> authenticators, string password)
{
// create file in memory
using (var ms = new MemoryStream())
{
using (var sw = new StreamWriter(ms))
{
List<WinAuthAuthenticator> unprotected = new List<WinAuthAuthenticator>();
foreach (var auth in authenticators)
{
unprotected.Add(auth);
string line = auth.ToUrl();
sw.WriteLine(line);
}
// reprotect
foreach (var auth in unprotected)
{
auth.AuthenticatorData.Protect();
}
// reset and write stream out to disk or as zip
sw.Flush();
ms.Seek(0, SeekOrigin.Begin);
var result = Encoding.UTF8.GetString(ms.ToArray());
return result;
}
}
}
}
}
-19
View File
@@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SteamTool.Auth
{
/// <summary>
/// Exception class wrapper for importing error
/// </summary>
public class ImportException : ApplicationException
{
public ImportException() : base() { }
public ImportException(string message) : base(message) { }
public ImportException(string message, Exception ex) : base(message, ex) { }
}
}
-18
View File
@@ -1,18 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Platforms>AnyCPU;x86</Platforms>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\SteamTool.Authenticator\SteamTool.Authenticator.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="PresentationCore">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\PresentationCore.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
-22
View File
@@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace SteamTool.Auth.Win32
{
public class WinAPI
{
public const string LibraryName = "user32.dll";
[DllImport(LibraryName, CharSet = CharSet.Auto)]
internal static extern IntPtr GetOpenClipboardWindow();
[DllImport(LibraryName, SetLastError = true, CharSet = CharSet.Auto)]
internal static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport(LibraryName, CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
}
}
-597
View File
@@ -1,597 +0,0 @@
using SteamTool.Auth.Win32;
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows;
using System.Xml;
using WinAuth;
namespace SteamTool.Auth
{
public interface IWinAuthAuthenticatorChangedListener
{
void OnWinAuthAuthenticatorChanged(WinAuthAuthenticator sender, WinAuthAuthenticatorChangedEventArgs e);
}
/// <summary>
/// Wrapper for real authenticator data used to save to file with other application information
/// </summary>
public class WinAuthAuthenticator : ICloneable
{
/// <summary>
/// Event handler fired when property is changed
/// </summary>
public event WinAuthAuthenticatorChangedHandler OnWinAuthAuthenticatorChanged;
/// <summary>
/// Unique Id of authenticator saved in config
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Index for authenticator when in sorted list
/// </summary>
public int Index { get; set; }
/// <summary>
/// Actual authenticator data
/// </summary>
public Authenticator AuthenticatorData { get; set; }
/// <summary>
/// When this authenticator was created
/// </summary>
public DateTime Created { get; set; }
private string _name;
private bool _autoRefresh;
private bool _allowCopy;
private bool _copyOnCode;
private bool _hideSerial;
/// <summary>
/// Create the authenticator wrapper
/// </summary>
public WinAuthAuthenticator()
{
Id = Guid.NewGuid();
Created = DateTime.Now;
_autoRefresh = true;
}
/// <summary>
/// Clone this authenticator
/// </summary>
/// <returns></returns>
public object Clone()
{
WinAuthAuthenticator clone = this.MemberwiseClone() as WinAuthAuthenticator;
clone.Id = Guid.NewGuid();
clone.OnWinAuthAuthenticatorChanged = null;
clone.AuthenticatorData = (this.AuthenticatorData != null ? this.AuthenticatorData.Clone() as Authenticator : null);
return clone;
}
/// <summary>
/// Mark this authenticator as having changed
/// </summary>
public void MarkChanged()
{
if (OnWinAuthAuthenticatorChanged != null)
{
OnWinAuthAuthenticatorChanged(this, new WinAuthAuthenticatorChangedEventArgs());
}
}
/// <summary>
/// Get/set the name of this authenticator
/// </summary>
public string Name
{
get
{
return _name;
}
set
{
_name = value;
if (OnWinAuthAuthenticatorChanged != null)
{
OnWinAuthAuthenticatorChanged(this, new WinAuthAuthenticatorChangedEventArgs("Name"));
}
}
}
/// <summary>
/// Get/set auto refresh flag
/// </summary>
public bool AutoRefresh
{
get
{
if (this.AuthenticatorData != null && this.AuthenticatorData is HOTPAuthenticator)
{
return false;
}
else
{
return _autoRefresh;
}
}
set
{
// HTOP must always be false
if (this.AuthenticatorData != null && this.AuthenticatorData is HOTPAuthenticator)
{
_autoRefresh = false;
}
else
{
_autoRefresh = value;
}
if (OnWinAuthAuthenticatorChanged != null)
{
OnWinAuthAuthenticatorChanged(this, new WinAuthAuthenticatorChangedEventArgs("AutoRefresh"));
}
}
}
/// <summary>
/// Get/set allow copy flag
/// </summary>
public bool AllowCopy
{
get
{
return _allowCopy;
}
set
{
_allowCopy = value;
if (OnWinAuthAuthenticatorChanged != null)
{
OnWinAuthAuthenticatorChanged(this, new WinAuthAuthenticatorChangedEventArgs("AllowCopy"));
}
}
}
/// <summary>
/// Get/set auto copy flag
/// </summary>
public bool CopyOnCode
{
get
{
return _copyOnCode;
}
set
{
_copyOnCode = value;
if (OnWinAuthAuthenticatorChanged != null)
{
OnWinAuthAuthenticatorChanged(this, new WinAuthAuthenticatorChangedEventArgs("CopyOnCode"));
}
}
}
/// <summary>
/// Get/set hide serial flag
/// </summary>
public bool HideSerial
{
get
{
return _hideSerial;
}
set
{
_hideSerial = value;
if (OnWinAuthAuthenticatorChanged != null)
{
OnWinAuthAuthenticatorChanged(this, new WinAuthAuthenticatorChangedEventArgs("HideSerial"));
}
}
}
public string CurrentCode
{
get
{
if (this.AuthenticatorData == null)
{
return null;
}
string code = this.AuthenticatorData.CurrentCode;
if (this.AuthenticatorData is HOTPAuthenticator)
{
if (OnWinAuthAuthenticatorChanged != null)
{
OnWinAuthAuthenticatorChanged(this, new WinAuthAuthenticatorChangedEventArgs("HOTP", this.AuthenticatorData));
}
}
return code;
}
}
/// <summary>
/// Sync the current authenticator's time with its server
/// </summary>
public void Sync()
{
if (AuthenticatorData != null)
{
try
{
AuthenticatorData.Sync();
}
catch (EncryptedSecretDataException)
{
// reset lastsync to force sync on next decryption
}
}
}
/// <summary>
/// Copy the current code to the clipboard
/// </summary>
public void CopyCodeToClipboard(string code = null, bool showError = false)
{
if (code == null)
{
code = this.CurrentCode;
}
bool clipRetry = false;
do
{
bool failed = false;
// check if the clipboard is locked
IntPtr hWnd = WinAPI.GetOpenClipboardWindow();
if (hWnd != IntPtr.Zero)
{
int len = WinAPI.GetWindowTextLength(hWnd);
if (len == 0)
{
//WinAuthMain.LogException(new ApplicationException("Clipboard in use by another process"));
}
else
{
StringBuilder sb = new StringBuilder(len + 1);
WinAPI.GetWindowText(hWnd, sb, sb.Capacity);
//WinAuthMain.LogException(new ApplicationException("Clipboard in use by '" + sb.ToString() + "'"));
}
failed = true;
}
else
{
// Issue#170: can still get error copying even though it works, so just increase retries and ignore error
try
{
Clipboard.Clear();
// add delay for clip error
System.Threading.Thread.Sleep(100);
Clipboard.SetDataObject(code, true);
}
catch (ExternalException)
{
}
}
if (failed == true && showError == true)
{
// only show an error the first time
//clipRetry = (MessageBox.Show(form, strings.ClipboardInUse,
// WinAuthMain.APPLICATION_NAME,
// MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes);
}
}
while (clipRetry == true);
}
public bool ReadXml(XmlReader reader, string password)
{
bool changed = false;
Guid id;
if (Guid.TryParse(reader.GetAttribute("id"), out id) == true)
{
Id = id;
}
string authenticatorType = reader.GetAttribute("type");
if (string.IsNullOrEmpty(authenticatorType) == false)
{
Type type = typeof(Authenticator).Assembly.GetType(authenticatorType, false, true);
this.AuthenticatorData = Activator.CreateInstance(type) as Authenticator;
}
//string encrypted = reader.GetAttribute("encrypted");
//if (string.IsNullOrEmpty(encrypted) == false)
//{
// // read the encrypted text from the node
// string data = reader.ReadElementContentAsString();
// // decrypt
// Authenticator.PasswordTypes passwordType;
// data = Authenticator.DecryptSequence(data, encrypted, password, out passwordType);
// using (MemoryStream ms = new MemoryStream(Authenticator.StringToByteArray(data)))
// {
// reader = XmlReader.Create(ms);
// ReadXml(reader, password);
// }
// this.PasswordType = passwordType;
// this.Password = password;
// return;
//}
reader.MoveToContent();
if (reader.IsEmptyElement)
{
reader.Read();
return changed;
}
reader.Read();
while (reader.EOF == false)
{
if (reader.IsStartElement())
{
switch (reader.Name)
{
case "name":
Name = reader.ReadElementContentAsString();
break;
case "created":
long t = reader.ReadElementContentAsLong();
t += Convert.ToInt64(new TimeSpan(new DateTime(1970, 1, 1).Ticks).TotalMilliseconds);
t *= TimeSpan.TicksPerMillisecond;
Created = new DateTime(t).ToLocalTime();
break;
case "autorefresh":
_autoRefresh = reader.ReadElementContentAsBoolean();
break;
case "allowcopy":
_allowCopy = reader.ReadElementContentAsBoolean();
break;
case "copyoncode":
_copyOnCode = reader.ReadElementContentAsBoolean();
break;
case "hideserial":
_hideSerial = reader.ReadElementContentAsBoolean();
break;
case "authenticatordata":
try
{
// we don't pass the password as they are locked till clicked
changed = this.AuthenticatorData.ReadXml(reader) || changed;
}
catch (EncryptedSecretDataException)
{
// no action needed
}
catch (BadPasswordException)
{
// no action needed
}
break;
// v2
case "authenticator":
this.AuthenticatorData = Authenticator.ReadXmlv2(reader, password);
break;
// v2
case "servertimediff":
this.AuthenticatorData.ServerTimeDiff = reader.ReadElementContentAsLong();
break;
default:
reader.Skip();
break;
}
}
else
{
reader.Read();
break;
}
}
return changed;
}
/// <summary>
/// Write the data as xml into an XmlWriter
/// </summary>
/// <param name="writer">XmlWriter to write config</param>
public void WriteXmlString(XmlWriter writer)
{
writer.WriteStartElement(typeof(WinAuthAuthenticator).Name);
writer.WriteAttributeString("id", this.Id.ToString());
if (this.AuthenticatorData != null)
{
writer.WriteAttributeString("type", this.AuthenticatorData.GetType().FullName);
}
//if (this.PasswordType != Authenticator.PasswordTypes.None)
//{
// string data;
// using (MemoryStream ms = new MemoryStream())
// {
// XmlWriterSettings settings = new XmlWriterSettings();
// settings.Indent = true;
// settings.Encoding = Encoding.UTF8;
// using (XmlWriter encryptedwriter = XmlWriter.Create(ms, settings))
// {
// Authenticator.PasswordTypes savedpasswordType = PasswordType;
// PasswordType = Authenticator.PasswordTypes.None;
// WriteXmlString(encryptedwriter);
// PasswordType = savedpasswordType;
// }
// //data = Encoding.UTF8.GetString(ms.ToArray());
// data = Authenticator.ByteArrayToString(ms.ToArray());
// }
// string encryptedTypes;
// data = Authenticator.EncryptSequence(data, PasswordType, Password, out encryptedTypes);
// writer.WriteAttributeString("encrypted", encryptedTypes);
// writer.WriteString(data);
// writer.WriteEndElement();
// return;
//}
writer.WriteStartElement("name");
writer.WriteValue(this.Name ?? string.Empty);
writer.WriteEndElement();
writer.WriteStartElement("created");
writer.WriteValue(Convert.ToInt64((this.Created.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalMilliseconds));
writer.WriteEndElement();
writer.WriteStartElement("autorefresh");
writer.WriteValue(this.AutoRefresh);
writer.WriteEndElement();
//
writer.WriteStartElement("allowcopy");
writer.WriteValue(this.AllowCopy);
writer.WriteEndElement();
//
writer.WriteStartElement("copyoncode");
writer.WriteValue(this.CopyOnCode);
writer.WriteEndElement();
//
writer.WriteStartElement("hideserial");
writer.WriteValue(this.HideSerial);
writer.WriteEndElement();
//
// save the authenticator to the config file
if (this.AuthenticatorData != null)
{
this.AuthenticatorData.WriteToWriter(writer);
// save script with password and generated salt
//if (this.AutoLogin != null)
//{
// this.AutoLogin.WriteXmlString(writer, this.AuthenticatorData.PasswordType, this.AuthenticatorData.Password);
//}
}
writer.WriteEndElement();
}
/// <summary>
/// Create a KeyUriFormat compatible URL
/// See https://code.google.com/p/google-authenticator/wiki/KeyUriFormat
/// </summary>
/// <returns>string</returns>
public virtual string ToUrl(bool compat = false)
{
string type = "totp";
string extraparams = string.Empty;
Match match;
string issuer = this.AuthenticatorData.Issuer;
string label = this.Name;
if (string.IsNullOrEmpty(issuer) == true && (match = Regex.Match(label, @"^([^\(]+)\s+\((.*?)\)(.*)")).Success == true)
{
issuer = match.Groups[1].Value;
label = match.Groups[2].Value + match.Groups[3].Value;
}
if (string.IsNullOrEmpty(issuer) == false && (match = Regex.Match(label, @"^" + issuer + @"\s+\((.*?)\)(.*)")).Success == true)
{
label = match.Groups[1].Value + match.Groups[2].Value;
}
if (string.IsNullOrEmpty(issuer) == false)
{
extraparams += "&issuer=" + HttpUtility.UrlEncode(issuer);
}
if (this.AuthenticatorData.HMACType != Authenticator.DEFAULT_HMAC_TYPE)
{
extraparams += "&algorithm=" + this.AuthenticatorData.HMACType.ToString();
}
if (this.AuthenticatorData is BattleNetAuthenticator)
{
extraparams += "&serial=" + HttpUtility.UrlEncode(((BattleNetAuthenticator)this.AuthenticatorData).Serial.Replace("-", ""));
}
else if (this.AuthenticatorData is SteamAuthenticator)
{
if (compat == false)
{
extraparams += "&deviceid=" + HttpUtility.UrlEncode(((SteamAuthenticator)this.AuthenticatorData).DeviceId);
extraparams += "&data=" + HttpUtility.UrlEncode(((SteamAuthenticator)this.AuthenticatorData).SteamData);
}
}
else if (this.AuthenticatorData is HOTPAuthenticator)
{
type = "hotp";
extraparams += "&counter=" + ((HOTPAuthenticator)this.AuthenticatorData).Counter;
}
string secret = HttpUtility.UrlEncode(Base32.getInstance().Encode(this.AuthenticatorData.SecretKey));
if (this.AuthenticatorData.Period != Authenticator.DEFAULT_PERIOD)
{
extraparams += "&period=" + this.AuthenticatorData.Period;
}
var url = string.Format("otpauth://" + type + "/{0}?secret={1}&digits={2}{3}",
(string.IsNullOrEmpty(issuer) == false ? HttpUtility.UrlPathEncode(issuer) + ":" + HttpUtility.UrlPathEncode(label) : HttpUtility.UrlPathEncode(label)),
secret,
this.AuthenticatorData.CodeDigits,
extraparams);
return url;
}
}
/// <summary>
/// Delegate for ConfigChange event
/// </summary>
/// <param name="source"></param>
/// <param name="args"></param>
public delegate void WinAuthAuthenticatorChangedHandler(WinAuthAuthenticator source, WinAuthAuthenticatorChangedEventArgs args);
/// <summary>
/// Change event arguments
/// </summary>
public class WinAuthAuthenticatorChangedEventArgs : EventArgs
{
public string Property { get; private set; }
public Authenticator Authenticator { get; private set; }
/// <summary>
/// Default constructor
/// </summary>
public WinAuthAuthenticatorChangedEventArgs(string property = null, Authenticator authenticator = null)
{
Property = property;
Authenticator = authenticator;
}
}
}
+2 -2
View File
@@ -13,12 +13,12 @@ namespace SteamTool.Proxy
public static string GetPublicPemCertificateString(this X509Certificate2 @this)
{
StringBuilder builder = new StringBuilder();
builder.AppendLine(Const.HostTag);
builder.AppendLine(Const.HOST_TAG);
builder.AppendLine("-----BEGIN CERTIFICATE-----");
builder.AppendLine(
Convert.ToBase64String(@this.RawData, Base64FormattingOptions.InsertLineBreaks));
builder.AppendLine("-----END CERTIFICATE-----");
builder.AppendLine(Const.HostTag);
builder.AppendLine(Const.HOST_TAG);
return builder.ToString();
}
+12 -1
View File
@@ -1,12 +1,14 @@
using log4net;
using log4net.Config;
using log4net.Repository;
using SteamTool.Core.Properties;
using SteamTool.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
namespace SteamTool.Core.Common
{
@@ -21,7 +23,16 @@ namespace SteamTool.Core.Common
static Logger()
{
ILoggerRepository repository = LogManager.CreateRepository(Assembly.GetCallingAssembly().GetName().Name);
XmlConfigurator.Configure(repository, new FileInfo(@"log\Log4net.config"));
if (File.Exists(Path.Combine(AppContext.BaseDirectory, @"log\Log4net.config")))
{
XmlConfigurator.Configure(repository, new FileInfo(@"log\Log4net.config"));
}
else
{
var doc = new XmlDocument();
doc.LoadXml(Resources.Log4netXml);
XmlConfigurator.Configure(repository, doc.DocumentElement);
}
_textLog = LogManager.GetLogger(repository.Name, "TextLog");
}
+40 -10
View File
@@ -13,12 +13,25 @@ namespace SteamTool.Core
{
public class HostsService
{
public readonly static string HostsPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.System)}\drivers\etc\hosts";
public readonly static string HostsPath = @$"{Environment.SystemDirectory}\drivers\etc\hosts";
static HostsService()
{
if (!File.Exists(HostsPath))
{
using var fs = File.Create(HostsPath);
fs.Close();
}
}
public OperationResult<List<string>> ReadHostsAllLines()
{
var result = new OperationResult<List<string>>(OperationResultType.Error, Resources.Hosts_ReadError);
if (!File.Exists(HostsPath))
{
result.Message = "hosts file was not found";
return result;
}
try
{
var dataLines = File.ReadAllLines(HostsPath).ToList();
@@ -48,7 +61,11 @@ namespace SteamTool.Core
public OperationResult UpdateHosts(string ip, string domain)
{
var result = new OperationResult(OperationResultType.Error, Resources.Hosts_WirteError);
if (!File.Exists(HostsPath))
{
result.Message = "hosts file was not found";
return result;
}
//操作前取消只读属性
File.SetAttributes(HostsPath, FileAttributes.Normal);
@@ -74,7 +91,7 @@ namespace SteamTool.Core
try
{
dataLines.Add($"{ip} {domain} {Const.HostTag}");
dataLines.Add($"{ip} {domain} {Const.HOST_TAG}");
File.WriteAllLines(HostsPath, dataLines);
//File.SetAttributes(HostsPath, FileAttributes.ReadOnly);
@@ -94,8 +111,12 @@ namespace SteamTool.Core
public OperationResult UpdateHosts(List<(string ip, string domain)> hosts)
{
var result = new OperationResult(OperationResultType.Error, Resources.Hosts_WirteError);
if (hosts.Count == 0)
if (!File.Exists(HostsPath))
{
result.Message = "hosts file was not found";
return result;
}
if (hosts.Count == 0)
{
return result;
}
@@ -128,7 +149,7 @@ namespace SteamTool.Core
foreach (var (ip, domain) in hosts)
{
dataLines.Add($"{ip} {domain} {Const.HostTag}");
dataLines.Add($"{ip} {domain} {Const.HOST_TAG}");
}
try
{
@@ -150,7 +171,11 @@ namespace SteamTool.Core
public OperationResult RemoveHosts(string ip, string domain)
{
var result = new OperationResult(OperationResultType.Error, Resources.Hosts_WirteError);
if (!File.Exists(HostsPath))
{
result.Message = "hosts file was not found";
return result;
}
//操作前取消只读属性
File.SetAttributes(HostsPath, FileAttributes.Normal);
@@ -191,7 +216,11 @@ namespace SteamTool.Core
public OperationResult RemoveHostsByTag()
{
var result = new OperationResult(OperationResultType.Error, Resources.Hosts_WirteError);
if (!File.Exists(HostsPath))
{
result.Message = "hosts file was not found";
return result;
}
//操作前取消只读属性
File.SetAttributes(HostsPath, FileAttributes.Normal);
@@ -205,7 +234,7 @@ namespace SteamTool.Core
{
if (!temp[0].StartsWith("#"))
{
return !temp.Contains(Const.HostTag);
return !temp.Contains(Const.HOST_TAG);
}
}
return true;
@@ -228,7 +257,8 @@ namespace SteamTool.Core
return result;
}
public void StartNotepadEditHosts()
public void StartNotepadEditHosts()
{
System.Diagnostics.Process.Start("notepad.exe", HostsPath);
}
+1 -1
View File
@@ -15,7 +15,7 @@ namespace SteamTool.Core
{
private readonly HttpClient _client = new HttpClient();
public string UserAgent { get; set; } = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36";
public string UserAgent { get; set; } = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
public string Accept { get; set; } = "application/json";
+1 -1
View File
@@ -23,7 +23,7 @@ namespace SteamTool.Core
Kernel.Bind<SteamToolService>().ToSelf();
Kernel.Bind<VdfService>().To<VdfService>();
Kernel.Bind<HttpServices>().ToConstant(new HttpServices());
Kernel.Bind<HostsService>().To<HostsService>();
Kernel.Bind<HostsService>().ToConstant(new HostsService());
}
public TInterface Get<TInterface>()
+24 -2
View File
@@ -47,8 +47,8 @@ namespace SteamTool.Core.Properties {
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性
/// 重写当前线程的 CurrentUICulture 属性。
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
@@ -124,5 +124,27 @@ namespace SteamTool.Core.Properties {
return ResourceManager.GetString("Hosts_WirteError", resourceCulture);
}
}
/// <summary>
/// 查找类似 &lt;?xml version=&quot;1.0&quot;?&gt;
///&lt;configuration&gt;
/// &lt;configSections&gt;
/// &lt;section name=&quot;log4net&quot; type=&quot;log4net.Config.Log4NetConfigurationSectionHandler, log4net&quot;/&gt;
/// &lt;/configSections&gt;
/// &lt;log4net&gt;
/// &lt;logger name=&quot;TextLog&quot;&gt;
/// &lt;level value=&quot;ALL&quot; /&gt;
/// &lt;appender-ref ref=&quot;RollingLogFileAppender&quot; /&gt;
/// &lt;/logger&gt;
/// &lt;!--写文本--&gt;
/// &lt;appender name=&quot;RollingLogFileAppender&quot; type=&quot;log4net.Appender.RollingFileAppender&quot;&gt;
/// &lt;param name=&quot;File&quot; value=&quot;log\\&quot; /&gt;
/// &lt;param name=&quot;AppendToFile&quot; value=&quot;true&quot; [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string Log4netXml {
get {
return ResourceManager.GetString("Log4netXml", resourceCulture);
}
}
}
}
+29
View File
@@ -154,4 +154,33 @@
<data name="Hosts_WirteError" xml:space="preserve">
<value>写入Hosts时发生错误</value>
</data>
<data name="Log4netXml" xml:space="preserve">
<value>&lt;?xml version="1.0"?&gt;
&lt;configuration&gt;
&lt;configSections&gt;
&lt;section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/&gt;
&lt;/configSections&gt;
&lt;log4net&gt;
&lt;logger name="TextLog"&gt;
&lt;level value="ALL" /&gt;
&lt;appender-ref ref="RollingLogFileAppender" /&gt;
&lt;/logger&gt;
&lt;!--写文本--&gt;
&lt;appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"&gt;
&lt;param name="File" value="log\\" /&gt;
&lt;param name="AppendToFile" value="true" /&gt;
&lt;param name="MaxSizeRollBackups" value="200" /&gt;
&lt;param name="StaticLogFileName" value="false" /&gt;
&lt;param name="DatePattern" value="yyyyMM\\yyyyMMdd'.log'" /&gt;
&lt;param name="RollingStyle" value="Date" /&gt;
&lt;layout type="log4net.Layout.PatternLayout,log4net"&gt;
&lt;param name="ConversionPattern" value="%d %-5p &gt;&gt; %m%n" /&gt;
&lt;!--输出头部并换行--&gt;
&lt;!--&lt;param name="Header" value="&amp;#13;&amp;#10;———————————————————&amp;#13;&amp;#10;" /&gt;
&lt;param name="Footer" value="&amp;#13;&amp;#10;———————————————————&amp;#13;&amp;#10;" /&gt;--&gt;
&lt;/layout&gt;
&lt;/appender&gt;
&lt;/log4net&gt;
&lt;/configuration&gt;</value>
</data>
</root>
+15 -15
View File
@@ -35,6 +35,8 @@ namespace SteamTool.Core
public string SteamExePath { get; set; }
public const string UserDataDirectory = @"\userdata";
public const string UserVdfPath = @"\config\loginusers.vdf";
private const string SteamRegistryPath = @"SOFTWARE\Valve\Steam";
@@ -60,7 +62,7 @@ namespace SteamTool.Core
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
if (process.ProcessName.ToLower() == "steam" || process.ProcessName.ToLower() == "steamService" || process.ProcessName.ToLower() == "steamwebhelper")
if (process.ProcessName.Equals("steam", StringComparison.OrdinalIgnoreCase) || process.ProcessName.Equals("steamService", StringComparison.OrdinalIgnoreCase) || process.ProcessName.Equals("steamwebhelper", StringComparison.OrdinalIgnoreCase))
{
process.Kill();
}
@@ -106,7 +108,8 @@ namespace SteamTool.Core
RememberPassword = Convert.ToBoolean(Convert.ToInt64(i.RememberPassword?.ToString())),
Timestamp = Convert.ToInt64(i.Timestamp?.ToString())
};
user.LastLoginTime = new DateTime(1970, 1, 1, 8, 0, 0).AddSeconds(user.Timestamp);
user.LastLoginTime = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(user.Timestamp), TimeZoneInfo.Local);
if (i.mostrecent != null)//老版本Steam数据 小写mostrecent 支持
{
user.MostRecent = Convert.ToBoolean(Convert.ToInt64(i.mostrecent.ToString()));
@@ -134,7 +137,6 @@ namespace SteamTool.Core
registryKeyService.AddOrUpdateRegistryKey(Registry.CurrentUser, SteamRegistryPath, "AutoLoginUser", username, RegistryValueKind.String);
}
public List<SteamApp> GetAppListJson(string filepath)
{
if (!File.Exists(filepath))
@@ -154,7 +156,6 @@ namespace SteamTool.Core
return apps.AppList.Apps;
}
public bool UpdateAppListJson(List<SteamApp> apps, string filepath)
{
var json = JsonConvert.SerializeObject(apps);
@@ -184,28 +185,17 @@ namespace SteamTool.Core
return true;
}
public void SetWindowsStartupAutoRun(bool IsAutoRun, string Name = "Steam++")
{
// Get the service on the local machine
if (IsAutoRun)
{
using TaskDefinition td = TaskService.Instance.NewTask();
// Create a new task definition and assign properties
td.RegistrationInfo.Description = Name + "System Boot Run";
td.Settings.Priority = System.Diagnostics.ProcessPriorityClass.Normal;
// Create a trigger that will fire after the system boot
td.Triggers.Add(new LogonTrigger());
// Create an action that will launch Notepad whenever the trigger fires
td.Actions.Add(new ExecAction(Assembly.GetCallingAssembly().Location, "-minimized", Path.GetDirectoryName(Assembly.GetCallingAssembly().Location)));
if (IsAdministrator)
td.Principal.RunLevel = TaskRunLevel.Highest;
// Register the task in the root folder
TaskService.Instance.RootFolder.RegisterTaskDefinition(Name, td);
//TaskService.Instance.RootFolder.AddTask(Name, QuickTriggerType.Boot, Assembly.GetCallingAssembly().Location, "-a");
}
@@ -214,5 +204,15 @@ namespace SteamTool.Core
TaskService.Instance.RootFolder.DeleteTask(Name);
}
}
public void DeleteSteamLocalUserData(SteamUser user)
{
vdfService.DeleteVdfValueByKey(SteamPath + UserVdfPath, user.SteamId64.ToString());
var temp = SteamPath + Path.Combine(UserDataDirectory, user.SteamId3_Int.ToString());
if (Directory.Exists(temp))
{
Directory.Delete(temp, true);
}
}
}
}
+17 -5
View File
@@ -1,23 +1,23 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Gameloop.Vdf;
using Gameloop.Vdf;
using Gameloop.Vdf.Linq;
namespace SteamTool.Core
{
public class VdfService
{
/// <summary>
/// 获取VDF类型内容
/// </summary>
/// <param name="path">vdf文件内容</param>
/// <returns></returns>
public dynamic GetVdfModel(string text)
public VProperty GetVdfModel(string text)
{
return VdfConvert.Deserialize(text);
}
@@ -29,8 +29,20 @@ namespace SteamTool.Core
/// <returns></returns>
public dynamic GetVdfModelByPath(string path)
{
string text = File.ReadAllText(path,Encoding.UTF8);
return GetVdfModel(text); ;
string text = File.ReadAllText(path, Encoding.UTF8);
return GetVdfModel(text);
}
public void DeleteVdfValueByKey(string path, string key)
{
string text = File.ReadAllText(path, Encoding.UTF8);
//如此实现的功能非常简单,但是应付嵌套的格式时会有问题
var index = text.IndexOf($"\"{key}\"");
var lastIndex = text.IndexOf('}', index);
text = text.Remove(index, lastIndex - index + 1);
//Debug.WriteLine(text);
File.WriteAllText(path, text, Encoding.UTF8);
}
}
}
+11 -3
View File
@@ -7,8 +7,16 @@ namespace SteamTool.Model
public const string APP_LIST_FILE = "apps.json";
public const string SETTINGS_FILE = "settings.json";
public const string SCRIPT_DIR = "scripts";
public const string HostTag = "#S302";
public const string HOST_TAG = "#S302";
public const string REWARDMELIST_URL = "https://gitee.com/rmbgame/steam-tools_-data/raw/master/RewardRecord.json";
//public const string REWARDMELIST_URL = "https://raw.githubusercontent.com/rmbadmin/SteamTools/develop/Data/RewardRecord.json";
public const string GITHUB_LATEST_RELEASEAPI_URL = "https://api.github.com/repos/rmbadmin/SteamTools/releases/latest";
public const string GITHUB_RELEASEAPI_URL = "https://api.github.com/repos/rmbadmin/SteamTools/releases";
public const string GITHUB_URL = "https://github.com/rmbadmin/SteamTools";
public const string GITHUB_RELEASES_URL = "https://github.com/rmbadmin/SteamTools/releases";
public const string MY_PROFILE_URL = "https://steamcommunity.com/profiles/76561198289531723/";
public const string MY_WISHLIST_URL = "https://store.steampowered.com/wishlist/profiles/76561198289531723/";
public const string MY_MINIPROFILE_URL = "https://steamcommunity.com/miniprofile/329265995";
@@ -17,7 +25,7 @@ namespace SteamTool.Model
public const string STEAMAPP_LIST_URL = "https://api.steampowered.com/ISteamApps/GetAppList/v2";
public const string STORE_APP_URL = "https://store.steampowered.com/app/{0}";
public const string STEAMAPP_LOGO_URL = "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{0}/{1}.jpg";
public const string STEAMAPP_ICON_URL = "http://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{0}/{1}";
public const string STEAMAPP_ICON_URL = "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{0}/{1}";
public const string STEAMAPP_CAPSULE_URL = "https://steamcdn-a.akamaihd.net/steam/apps/{0}/capsule_184x69.jpg";
public const string STEAMAPP_HEADIMAGE_URL = "https://steamcdn-a.akamaihd.net/steam/apps/{0}/header.jpg";
public const string STEAM_MEDIA_URL = "https://steamcdn-a.akamaihd.net/steam/apps/{0}/movie_max.webm";
@@ -27,7 +35,7 @@ namespace SteamTool.Model
public const string STEAM_INSTALL_URL = "steam://install/{0}";
public const string STEAM_RUNGAME_URL = "steam://rungameid/{0}";
public const string STEAM_OPENURL = "steam://openurl/{0}";
public const string STEAM_RUN_KeyURL = "steam://openurl/https://store.steampowered.com/account/registerkey?key={0}";
public const string STEAM_RUN_KEYURL = "steam://openurl/https://store.steampowered.com/account/registerkey?key={0}";
public const string STEAMDB_USERINFO_URL = "https://api.steamdb.ml/v1/users/{0}";
public const string STEAMDB_APPINFO_URL = "https://api.steamdb.ml/v1/apps/{0}";
+2
View File
@@ -22,6 +22,8 @@ namespace SteamTool.Model
/// </summary>
public string OnlineState { get; set; }
public string IPCountry { get; set; }
/// <summary>
/// 公开状态
/// friendsonly
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SteamTool.Model.ToolModel
{
public class GithubReleaseModel
{
public string id { get; set; }
public string html_url { get; set; }
public string tag_name { get; set; }
public Version version => new Version(tag_name);
public string target_commitish { get; set; }
public string created_at { get; set; }
public string published_at { get; set; }
public List<Assets> assets { get; set; }
public string body { get; set; }
}
public class Assets
{
public string id { get; set; }
public string url { get; set; }
public string name { get; set; }
public string content_type { get; set; }
public string size { get; set; }
public string download_count { get; set; }
public string updated_at { get; set; }
public string browser_download_url { get; set; }
}
}
+72 -45
View File
@@ -13,6 +13,7 @@ using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
using SteamTool.Model;
using System.Security.Cryptography;
namespace SteamTool.Proxy
{
@@ -30,6 +31,7 @@ namespace SteamTool.Proxy
public HttpProxy(IReadOnlyCollection<ProxyDomainModel> proxyDomains, string certificateName)
{
proxyServer.ThreadPoolWorkerThread = Environment.ProcessorCount * 8;
ProxyDomains = proxyDomains;
CertificateName = certificateName;
}
@@ -38,6 +40,7 @@ namespace SteamTool.Proxy
public async Task OnRequest(object sender, SessionEventArgs e)
{
#if DEBUG
#region 测试用
/*
if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("steampowered.com"))
@@ -61,9 +64,20 @@ namespace SteamTool.Proxy
}
*/
#endregion
#if DEBUG
Debug.WriteLine("OnRequest" + e.HttpClient.Request.RequestUri.AbsoluteUri);
#endif
Debug.WriteLine("OnRequest " + e.HttpClient.Request.RequestUri.AbsoluteUri);
Debug.WriteLine("OnRequest Authority " + e.HttpClient.Request.RequestUri.Authority);
Logger.Info("OnRequest" + e.HttpClient.Request.RequestUri.AbsoluteUri);
#endif
await Dns.GetHostAddressesAsync(e.HttpClient.Request.Host).ContinueWith(s =>
{
//部分运营商将奇怪的域名解析到127.0.0.1 再此排除这些不支持的代理域名
if (IPAddress.IsLoopback(s.Result.FirstOrDefault())
&& ProxyDomains.Count(w => w.IsEnable && w.Hosts.Contains(e.HttpClient.Request.Host)) == 0)
{
e.Ok($"URL : {e.HttpClient.Request.RequestUri.AbsoluteUri} \r\n not support proxy");
return;
}
});
foreach (var item in ProxyDomains)
{
if (!item.IsEnable)
@@ -82,10 +96,7 @@ namespace SteamTool.Proxy
else
{
var iPs = await Dns.GetHostAddressesAsync(item.ToDomain);
if (iPs.Length > 0)
{
iP = iPs[0];
}
iP = iPs.FirstOrDefault();
}
if (iP != null)
{
@@ -115,6 +126,7 @@ namespace SteamTool.Proxy
//if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
#if DEBUG
Debug.WriteLine("OnResponse" + e.HttpClient.Request.RequestUri.AbsoluteUri);
Logger.Info("OnResponse" + e.HttpClient.Request.RequestUri.AbsoluteUri);
#endif
if (IsEnableScript)
{
@@ -164,7 +176,7 @@ namespace SteamTool.Proxy
//e.HttpClient.Response.Headers.AddHeader("Content-Security-Policy", result);
}
#if DEBUG
Debug.WriteLine(t);
Debug.WriteLine(e.HttpClient.Request.RequestUri.AbsoluteUri);
#endif
foreach (var req in script.Require)
{
@@ -216,7 +228,7 @@ namespace SteamTool.Proxy
//proxyServer.CertificateManager
// .CreateServerCertificate($"{Assembly.GetCallingAssembly().GetName().Name} Certificate")
// .ContinueWith(c => proxyServer.CertificateManager.RootCertificate = c.Result);
proxyServer.CertificateManager.PfxFilePath = $@"{CertificateName}.Certificate.pfx";
proxyServer.CertificateManager.PfxFilePath = Path.Combine(AppContext.BaseDirectory, $@"{CertificateName}.Certificate.pfx");
//proxyServer.CertificateManager.PfxPassword = $"{CertificateName}";
proxyServer.CertificateManager.RootCertificateIssuerName = CertificateName;
proxyServer.CertificateManager.RootCertificateName = $"{CertificateName} Certificate";
@@ -237,25 +249,58 @@ namespace SteamTool.Proxy
{
if (ProxyRunning)
return false;
using (var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser))
try
{
store.Open(OpenFlags.MaxAllowed);
//var test = store.Certificates.Find(X509FindType.FindByIssuerName, "titan", true);
var test = store.Certificates.Find(X509FindType.FindByIssuerName, CertificateName, true);
foreach (var item in test)
using (var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser))
{
store.Remove(item);
store.Open(OpenFlags.MaxAllowed);
//var test = store.Certificates.Find(X509FindType.FindByIssuerName, "titan", true);
var test = store.Certificates.Find(X509FindType.FindByIssuerName, CertificateName, true);
foreach (var item in test)
{
store.Remove(item);
}
//if (store.Certificates.Contains(proxyServer.CertificateManager.RootCertificate))
// store.Remove(proxyServer.CertificateManager.RootCertificate);
}
proxyServer.CertificateManager.ClearRootCertificate();
proxyServer.CertificateManager.RemoveTrustedRootCertificate(true);
proxyServer.CertificateManager.RemoveTrustedRootCertificateAsAdmin(true);
proxyServer.CertificateManager.CertificateStorage.Clear();
}
catch (Exception ex)
{
if (ex is CryptographicException)
{
//取消删除证书
}
else
{
throw;
}
//if (store.Certificates.Contains(proxyServer.CertificateManager.RootCertificate))
// store.Remove(proxyServer.CertificateManager.RootCertificate);
}
proxyServer.CertificateManager.ClearRootCertificate();
proxyServer.CertificateManager.RemoveTrustedRootCertificate(true);
proxyServer.CertificateManager.RemoveTrustedRootCertificateAsAdmin(true);
proxyServer.CertificateManager.CertificateStorage.Clear();
return true;
}
public static bool PortInUse(int port)
{
bool inUse = false;
var ipProperties = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
foreach (IPEndPoint endPoint in ipEndPoints)
{
if (endPoint.Port == port)
{
inUse = true;
break;
}
}
return inUse;
}
public bool StartProxy(bool IsProxyGOG = false)
{
if (!IsCertificateInstalled(proxyServer.CertificateManager.RootCertificate))
@@ -265,10 +310,10 @@ namespace SteamTool.Proxy
{
return false;
}
if (PortInUse(443))
{
return false;
}
}
if (PortInUse(443))
{
return false;
}
if (IsProxyGOG) { WirtePemCertificateToGoGSteamPlugins(); }
@@ -335,24 +380,6 @@ namespace SteamTool.Proxy
return true;
}
public static bool PortInUse(int port)
{
bool inUse = false;
var ipProperties = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
foreach (IPEndPoint endPoint in ipEndPoints)
{
if (endPoint.Port == port)
{
inUse = true;
break;
}
}
return inUse;
}
public void StopProxy()
{
@@ -382,14 +409,14 @@ namespace SteamTool.Proxy
if (File.Exists(certifi))
{
var file = File.ReadAllText(certifi);
var s = file.Substring(Const.HostTag, Const.HostTag, true);
var s = file.Substring(Const.HOST_TAG, Const.HOST_TAG, true);
if (string.IsNullOrEmpty(s))
{
File.AppendAllText(certifi, "\r\n" + pem);
}
else if (s.Trim() != pem.Trim())
{
var index = file.IndexOf(Const.HostTag);
var index = file.IndexOf(Const.HOST_TAG);
File.WriteAllText(certifi, file.Remove(index, s.Length) + pem);
}
return true;
@@ -80,5 +80,9 @@ namespace SteamTool.Proxy
GoogleCode = 8,
[Description("GOG.COM")]
GOG = 8,
[Description("Github图片修复")]
GithubContent = 9,
[Description("Pixiv")]
Pixiv = 10,
}
}
+18
View File
@@ -69,6 +69,15 @@ namespace SteamTool.Proxy.Properties {
}
}
/// <summary>
/// 查找类似 Github图片资源修复 的本地化字符串。
/// </summary>
public static string GithubContent {
get {
return ResourceManager.GetString("GithubContent", resourceCulture);
}
}
/// <summary>
/// 查找类似 GOG Galaxy 的本地化字符串。
/// </summary>
@@ -105,6 +114,15 @@ namespace SteamTool.Proxy.Properties {
}
}
/// <summary>
/// 查找类似 Pixiv 的本地化字符串。
/// </summary>
public static string Pixiv {
get {
return ResourceManager.GetString("Pixiv", resourceCulture);
}
}
/// <summary>
/// 查找类似 Steam好友聊天 的本地化字符串。
/// </summary>
@@ -120,6 +120,9 @@
<data name="Discord" xml:space="preserve">
<value>Discord语音</value>
</data>
<data name="GithubContent" xml:space="preserve">
<value>Github图片资源修复</value>
</data>
<data name="GOG" xml:space="preserve">
<value>GOG Galaxy</value>
</data>
@@ -132,6 +135,9 @@
<data name="OriginDownload" xml:space="preserve">
<value>Origin游戏下载(Akamai)</value>
</data>
<data name="Pixiv" xml:space="preserve">
<value>Pixiv</value>
</data>
<data name="SteamChat" xml:space="preserve">
<value>Steam好友聊天</value>
</data>
@@ -64,7 +64,7 @@ namespace SteamTool.Steam.Service.Local
Index = i + 1,
AppId = s.AppId,
Name = s.Name,
Type = Enum.TryParse<SteamAppTypeEnum>(SteamClient.SteamApps001.GetAppData(s.AppId, "type"), true, out var result) ? result : SteamAppTypeEnum.Unknown,
Type = Enum.TryParse<SteamAppTypeEnum>(GetAppData(s.AppId, "type"), true, out var result) ? result : SteamAppTypeEnum.Unknown,
//Logo = SteamClient.SteamApps001.GetAppData(s.AppId, "logo"),
IsInstalled = IsAppInstalled(s.AppId)
}).ToList();
+3 -1
View File
@@ -103,6 +103,8 @@ namespace SAM.API
return;
}
this._IsDisposed = true;
if (this.SteamClient != null && this._Pipe > 0)
{
if (this._User > 0)
@@ -115,7 +117,7 @@ namespace SAM.API
this._Pipe = 0;
}
this._IsDisposed = true;
this._IsDisposed = false;
}
public void Dispose()
-14
View File
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SteamTool.Composition.Interface
{
[PluginFeature]
public interface ITool
{
string Name { get; }
object View { get; }
}
}
@@ -1,9 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SteamTool.Composition
{
[AttributeUsage(AttributeTargets.Interface)]
public sealed class PluginFeatureAttribute : Attribute { }
}
@@ -1,10 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Configurations>Debug;Release;发布</Configurations>
<LangVersion>8.0</LangVersion>
<Platforms>AnyCPU;x86</Platforms>
</PropertyGroup>
</Project>
+1 -1
View File
@@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Proxy", "SteamToo
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Composition", "Composition", "{F62E508E-B374-4149-B9AC-0A8090AA6CD1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steam.Service", "SteamTools.Steam.Service\SteamTool.Steam.Service.csproj", "{2A155A7B-3DFD-4F16-929D-9693D2411B83}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steam.Service", "SteamTool.Steam.Service\SteamTool.Steam.Service.csproj", "{2A155A7B-3DFD-4F16-929D-9693D2411B83}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Core", "SteamTool.Core\SteamTool.Core.csproj", "{23E26040-19A5-4623-8863-B9ED539403B0}"
EndProject
+23 -11
View File
@@ -32,7 +32,7 @@ namespace SteamTools
public static App Instance => Current as App;
public DirectoryInfo LocalAppData = new DirectoryInfo(
Path.Combine(
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
ProductInfo.Company,
ProductInfo.Product));
@@ -68,6 +68,7 @@ namespace SteamTools
}
Logger.EnableTextLog = true;
#endif
App.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
DispatcherHelper.UIDispatcher = this.Dispatcher;
if (e.Args.ContainsArg("-log"))
@@ -83,17 +84,27 @@ namespace SteamTools
this.compositeDisposable.Add(ProxyService.Current.Shutdown);
this.compositeDisposable.Add(SteamConnectService.Current.Shutdown);
//托盘加载
GeneralSettings.Culture.Subscribe(x => ResourceService.Current.ChangeCulture(x)).AddTo(this);
WindowService.Current.AddTo(this).Initialize();
ProxyService.Current.Initialize();
SteamConnectService.Current.Initialize();
AuthService.Current.Initialize();
if (GeneralSettings.IsAutoCheckUpdate)
{
AutoUpdateService.Current.CheckUpdate();
}
//托盘加载
TaskbarService.Current.Taskbar = (TaskbarIcon)FindResource("Taskbar");
ThemeService.Current.Register(this, Theme.Windows, Accent.Windows);
this.MainWindow = WindowService.Current.GetMainWindow();
if (e.Args.ContainsArg("-minimized"))
if (e.Args.ContainsArg("-minimized") || GeneralSettings.IsStartupAppMinimized.Value)
{
//this.MainWindow.Show();
//(WindowService.Current.MainWindow as MainWindowViewModel).IsVisible = false;
(WindowService.Current.MainWindow as MainWindowViewModel).Initialize();
}
else
this.MainWindow.Show();
@@ -101,8 +112,8 @@ namespace SteamTools
appInstance.CommandLineArgsReceived += (sender, args) =>
{
// 检测到多次启动时将主窗口置于最前面
this.Dispatcher.Invoke(() => WindowService.Current.MainWindow.Activate());
//this.ProcessCommandLineParameter(args.CommandLineArgs);
this.Dispatcher.Invoke(() => { (WindowService.Current.MainWindow as MainWindowViewModel).IsVisible = true; });
this.ProcessCommandLineParameter(args.CommandLineArgs);
};
#endif
@@ -130,7 +141,7 @@ namespace SteamTools
catch (Exception ex)
{
Debug.WriteLine(ex);
MessageBox.Show(ex.Message, "Error");
MessageBox.Show(ex.Message, $"{ProductInfo.Title} {ProductInfo.VersionString} Error");
}
Current.Shutdown();
@@ -147,18 +158,18 @@ namespace SteamTools
//TaskbarService.Current.Taskbar.Icon = null; //避免托盘图标没有自动消失
TaskbarService.Current.Taskbar.Icon.Dispose();
}
base.OnExit(e);
this.compositeDisposable.Dispose();
base.OnExit(e);
}
private void ProcessCommandLineParameter(string[] args)
{
Debug.WriteLine("多重启动通知: " + args.ToString(" "));
// 当使用命令行参数多次启动时,您可以执行某些操作
//if (args.Length == 0)
//{
// this.Shutdown();
//}
if (args.Length == 0)
{
this.Shutdown();
}
if (args.ContainsArg("-log"))
{
Logger.EnableTextLog = true;
@@ -167,6 +178,7 @@ namespace SteamTools
}
if (args.ContainsArg("-app", out int appid))
{
App.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
ThemeService.Current.Register(this, Theme.Windows, Accent.Windows);
new SettingsPageViewModel();
WindowService.Current.AddTo(this).Initialize(appid);
+2
View File
@@ -33,6 +33,8 @@ namespace SteamTools.Models
new Library("ArchiSteamFarm", new Uri("https://github.com/JustArchiNET/ArchiSteamFarm")),
new Library("WinAuth", new Uri("https://github.com/winauth/winauth")),
new Library("SteamDesktopAuthenticator", new Uri("https://github.com/Jessecar96/SteamDesktopAuthenticator")),
new Library("Gameloop.Vdf", new Uri("https://github.com/shravan2x/Gameloop.Vdf")),
new Library("Costura.Fody", new Uri("https://github.com/Fody/Costura")),
//new Library("idle_master_extended", new Uri("https://github.com/JonasNilson/idle_master_extended")),
});
+18 -1
View File
@@ -33,6 +33,12 @@ namespace SteamTools.Models.Settings
public static SerializableProperty<bool> WindowsStartupAutoRun { get; }
= new SerializableProperty<bool>(GetKey(), Providers.Roaming, false) { AutoSave = true };
/// <summary>
/// 程序启动时最小化
/// </summary>
public static SerializableProperty<bool> IsStartupAppMinimized { get; }
= new SerializableProperty<bool>(GetKey(), Providers.Roaming, false) { AutoSave = true };
/// <summary>
/// 是否显示起始页
/// </summary>
@@ -40,11 +46,22 @@ namespace SteamTools.Models.Settings
= new SerializableProperty<bool>(GetKey(), Providers.Roaming, true) { AutoSave = true };
/// <summary>
/// 游戏列表本地缓存
/// 启用游戏列表本地缓存
/// </summary>
public static SerializableProperty<bool> IsSteamAppListLocalCache { get; }
= new SerializableProperty<bool>(GetKey(), Providers.Roaming, true) { AutoSave = true };
/// <summary>
/// Steam启动参数
/// </summary>
public static SerializableProperty<string> SteamStratParameter { get; }
= new SerializableProperty<string>(GetKey(), Providers.Local, string.Empty) { AutoSave = true };
/// <summary>
/// 自动检查更新
/// </summary>
public static SerializableProperty<bool> IsAutoCheckUpdate { get; }
= new SerializableProperty<bool>(GetKey(), Providers.Roaming, true) { AutoSave = true };
private static string GetKey([CallerMemberName] string propertyName = "")
{
+6 -6
View File
@@ -339,9 +339,9 @@ namespace SteamTools.Models
Created = new DateTime(t).ToLocalTime();
break;
case "autorefresh":
_autoRefresh = reader.ReadElementContentAsBoolean();
break;
//case "autorefresh":
// _autoRefresh = reader.ReadElementContentAsBoolean();
// break;
case "allowcopy":
_allowCopy = reader.ReadElementContentAsBoolean();
@@ -446,9 +446,9 @@ namespace SteamTools.Models
writer.WriteValue(Convert.ToInt64((this.Created.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalMilliseconds));
writer.WriteEndElement();
writer.WriteStartElement("autorefresh");
writer.WriteValue(this.AutoRefresh);
writer.WriteEndElement();
//writer.WriteStartElement("autorefresh");
//writer.WriteValue(this.AutoRefresh);
//writer.WriteEndElement();
//
writer.WriteStartElement("allowcopy");
writer.WriteValue(this.AllowCopy);
+35
View File
@@ -0,0 +1,35 @@
using SteamTool.Core.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SteamTools
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
try
{
if (args.ContainsArg("-log"))
{
Logger.EnableTextLog = true;
}
App app = new App();
app.InitializeComponent();
app.Run();
}
catch (Exception ex)
{
Logger.Error(ex);
}
}
}
}
Binary file not shown.
+38 -2
View File
@@ -78,6 +78,15 @@ namespace SteamTools.Properties {
}
}
/// <summary>
/// 查找类似 捐助记录 的本地化字符串。
/// </summary>
public static string About_DonateList {
get {
return ResourceManager.GetString("About_DonateList", resourceCulture);
}
}
/// <summary>
/// 查找类似 帮助 的本地化字符串。
/// </summary>
@@ -88,7 +97,7 @@ namespace SteamTools.Properties {
}
/// <summary>
/// 查找类似 开源许可 的本地化字符串。
/// 查找类似 开源协议 的本地化字符串。
/// </summary>
public static string About_OpenSourceLicensing {
get {
@@ -222,6 +231,15 @@ namespace SteamTools.Properties {
}
}
/// <summary>
/// 查找类似 交易确认 的本地化字符串。
/// </summary>
public static string Auth_TradeTitle {
get {
return ResourceManager.GetString("Auth_TradeTitle", resourceCulture);
}
}
/// <summary>
/// 查找类似 自动启动代理服务 的本地化字符串。
/// </summary>
@@ -456,6 +474,15 @@ namespace SteamTools.Properties {
}
}
/// <summary>
/// 查找类似 Github图片资源修复 的本地化字符串。
/// </summary>
public static string GithubContent {
get {
return ResourceManager.GetString("GithubContent", resourceCulture);
}
}
/// <summary>
/// 查找类似 GOG Galaxy 的本地化字符串。
/// </summary>
@@ -655,7 +682,7 @@ namespace SteamTools.Properties {
}
/// <summary>
/// 查找类似 复位成就和/统计 的本地化字符串。
/// 查找类似 复位成就和统计 的本地化字符串。
/// </summary>
public static string OnRest {
get {
@@ -825,6 +852,15 @@ namespace SteamTools.Properties {
}
}
/// <summary>
/// 查找类似 帐户切换设置 的本地化字符串。
/// </summary>
public static string Settings_AccountChange {
get {
return ResourceManager.GetString("Settings_AccountChange", resourceCulture);
}
}
/// <summary>
/// 查找类似 令牌设置 的本地化字符串。
/// </summary>
+3
View File
@@ -135,6 +135,9 @@
<data name="Settings" xml:space="preserve">
<value>Settings</value>
</data>
<data name="Settings_Language" xml:space="preserve">
<value>Language</value>
</data>
<data name="Steam302" xml:space="preserve">
<value>CommunityFix</value>
</data>
+14 -2
View File
@@ -126,11 +126,14 @@
<data name="About_Donate" xml:space="preserve">
<value>捐助</value>
</data>
<data name="About_DonateList" xml:space="preserve">
<value>捐助记录</value>
</data>
<data name="About_Help" xml:space="preserve">
<value>帮助</value>
</data>
<data name="About_OpenSourceLicensing" xml:space="preserve">
<value>开源许可</value>
<value>开源协议</value>
</data>
<data name="About_TheSoft" xml:space="preserve">
<value>此软件</value>
@@ -171,6 +174,9 @@
<data name="Auth_See" xml:space="preserve">
<value>查看令牌</value>
</data>
<data name="Auth_TradeTitle" xml:space="preserve">
<value>交易确认</value>
</data>
<data name="AutoRunProxyService" xml:space="preserve">
<value>自动启动代理服务</value>
</data>
@@ -249,6 +255,9 @@
<data name="Game_UnInstall" xml:space="preserve">
<value>未安装</value>
</data>
<data name="GithubContent" xml:space="preserve">
<value>Github图片资源修复</value>
</data>
<data name="GOG" xml:space="preserve">
<value>GOG Galaxy</value>
</data>
@@ -316,7 +325,7 @@
<value>刷新成绩和统计</value>
</data>
<data name="OnRest" xml:space="preserve">
<value>复位成就和/统计</value>
<value>复位成就和统计</value>
</data>
<data name="OnStore" xml:space="preserve">
<value>保存并应用成就和统计</value>
@@ -372,6 +381,9 @@
<data name="Settings_Accent" xml:space="preserve">
<value>颜色</value>
</data>
<data name="Settings_AccountChange" xml:space="preserve">
<value>帐户切换设置</value>
</data>
<data name="Settings_Auth" xml:space="preserve">
<value>令牌设置</value>
</data>
+2 -1
View File
@@ -1,7 +1,8 @@
{
"profiles": {
"SteamTools": {
"commandName": "Project"
"commandName": "Project",
"commandLineArgs": "-log"
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+12 -4
View File
@@ -45,7 +45,7 @@ namespace SteamTools.Services
#endregion
private BindingList<WinAuthAuthenticator> _Authenticators;
private BindingList<WinAuthAuthenticator> _Authenticators = new BindingList<WinAuthAuthenticator>();
public BindingList<WinAuthAuthenticator> Authenticators
{
@@ -60,11 +60,19 @@ namespace SteamTools.Services
}
}
public AuthService()
public void Initialize()
{
if (!string.IsNullOrEmpty(AuthSettings.Authenticators.Value))
{
Authenticators = new BindingList<WinAuthAuthenticator>(AuthService.LoadJsonAuthenticator(AuthSettings.Authenticators.Value.DecompressString()));
try
{
var auths = AuthService.LoadJsonAuthenticator(AuthSettings.Authenticators.Value.DecompressString());
Authenticators = new BindingList<WinAuthAuthenticator>(auths);
}
catch (Exception ex)
{
WindowService.Current.MainWindow.Dialog($"令牌同步服务器失败,错误信息:{ex.Message}");
}
}
else
{
@@ -525,7 +533,7 @@ namespace SteamTools.Services
}
if (reader.Name == "WinAuthAuthenticator")
{
var wa = new WinAuthAuthenticator();
var wa = new WinAuthAuthenticator() { AutoRefresh = false };
wa.ReadXml(reader, null);
list.Add(wa);
}
+120
View File
@@ -0,0 +1,120 @@
using SteamTool.Core;
using SteamTool.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using SteamTool.Model.ToolModel;
using SteamTools.Models;
using SteamTool.Core.Common;
using System.Net;
using System.IO;
using Livet;
using SteamTools.Properties;
namespace SteamTools.Services
{
public class AutoUpdateService : NotificationObject
{
#region static members
public static AutoUpdateService Current { get; } = new AutoUpdateService();
#endregion
private readonly HttpServices httpServices = SteamToolCore.Instance.Get<HttpServices>();
#region 更新进度变更通知
private double _ProgressValue;
public double ProgressValue
{
get => this._ProgressValue;
set
{
if (this._ProgressValue != value)
{
this._ProgressValue = value;
this.RaisePropertyChanged();
}
}
}
#endregion
#region 是否有更新
private bool _IsExistUpdate;
public bool IsExistUpdate
{
get => this._IsExistUpdate;
set
{
if (this._IsExistUpdate != value)
{
this._IsExistUpdate = value;
this.RaisePropertyChanged();
}
}
}
#endregion
public async void CheckUpdate()
{
try
{
StatusService.Current.Notify("正在从Github检查更新...");
var result = await httpServices.Get(Const.GITHUB_LATEST_RELEASEAPI_URL);
var model = JsonConvert.DeserializeObject<GithubReleaseModel>(result);
if (!(ProductInfo.Version < model.version))
{
IsExistUpdate = false;
StatusService.Current.Notify("当前已是最新版本");
return;
}
IsExistUpdate = true;
DownloadUpdate(model);
}
catch (Exception ex)
{
Logger.Error("更新出错:", ex);
WindowService.Current.ShowDialogWindow($"更新出错:{ex.Message}");
}
}
public async void DownloadUpdate(GithubReleaseModel model)
{
if (WindowService.Current.ShowDialogWindow($"检测到新版本更新内容:{model.body}\r\n是否立即更新?", $"{ProductInfo.Title} | 更新提示") == true)
{
//var name = model.assets.FirstOrDefault()?.name;
var name = Path.Combine(AppContext.BaseDirectory, @$"{ProductInfo.Title} {model.version}.zip");
if (File.Exists(name))
{
StatusService.Current.Notify("更新文件已经存在,不需要下载");
return;
}
var fileReq = WebRequest.Create(model.assets.FirstOrDefault()?.browser_download_url);
await fileReq?.GetResponseAsync().ContinueWith(s =>
{
long totalBytes = s.Result.ContentLength;
using Stream responseStream = s.Result.GetResponseStream();
using FileStream fileStream = new FileStream(name, FileMode.Create, FileAccess.Write);
long totalDownloadBytes = 0;
byte[] bs = new byte[4096];
int size = responseStream.Read(bs, 0, bs.Length);
while (size > 0)
{
totalDownloadBytes += size;
fileStream.Write(bs, 0, size);
ProgressValue = ((double)totalDownloadBytes / (double)totalBytes);
StatusService.Current.Set($"下载更新{ProgressValue:P}");
size = responseStream.Read(bs, 0, bs.Length);
}
fileStream.Flush();
fileStream.Close();
StatusService.Current.Set(Resources.Ready);
StatusService.Current.Notify($"{ProductInfo.Title} {model.version}版本已经下载到程序根目录下,暂时请手动替换更新");
});
}
}
}
}
+261 -181
View File
@@ -10,17 +10,20 @@ using System.IO;
using SteamTool.Model;
using SteamTools.Models;
using SteamTools.Models.Settings;
using SteamTool.Core;
namespace SteamTools.Services
{
public class ProxyService : NotificationObject
{
public static ProxyService Current { get; } = new ProxyService();
private readonly HostsService hostsService = new HostsService();
public HttpProxy Proxy { get; set; }
public void Initialize()
{
//启动时恢复host
hostsService.RemoveHostsByTag();
if (ProxySettings.SupportProxyServicesStatus.Value.Count > 0)
{
foreach (var item in ProxyDomains.Value)
@@ -33,188 +36,265 @@ namespace SteamTools.Services
}
Proxy = new HttpProxy(ProxyDomains.Value, ProductInfo.Product);
InitJsScript();
Proxy.IsEnableScript = IsEnableScript;
if (ProxySettings.ProgramStartupRunProxy.Value)
{
ProxyStatus = true;
}
}
private Lazy<IReadOnlyCollection<ProxyDomainModel>> _ProxyDomains = new Lazy<IReadOnlyCollection<ProxyDomainModel>>(() => new List<ProxyDomainModel>
{
new ProxyDomainModel{
Index=0,
Name=Resources.SteamCommunity,
Domains = new List<string>{"steamcommunity.com" },
ToDomain = "steamcommunity-a.akamaihd.net",
Hosts = new List<string>{ "steamcommunity.com", "www.steamcommunity.com"},
DomainTag = DomainTag.SteamCommunity,
IsEnable= true,
},
new ProxyDomainModel{
Index=1,
Name=Resources.SteamStore,
Domains = new List<string>{"steampowered.com" },
ToDomain = "steamstore-a.akamaihd.net",
Hosts = new List<string>{ "store.steampowered.com", "api.steampowered.com"},
DomainTag = DomainTag.SteamStore,
IsEnable= false,
},
//new ProxyDomainModel{
// Index=2,
// Name=Resources.SteamImage,
// Domains = new List<string>{"steamcdn-a.akamaihd.net" },
// ToDomain = "steamuserimages-a.akamaihd.net",
// Hosts = new List<string>{ "steamcdn-a.akamaihd.net"},
// DomainTag = DomainTag.SteamImage,
// IsEnable= false,
//},
new ProxyDomainModel{
Index=3,
Name=Resources.SteamChat,
Domains = new List<string>{"steam-chat.com" },
ToDomain = "s.team",
Hosts = new List<string>{ "steam-chat.com"},
DomainTag = DomainTag.SteamChat,
IsEnable= false,
},
//new ProxyDomainModel{
//Index=4,
// Name=Resources.Discord,
// Domains = new List<string>{ "discordapp.com" },
// ToDomain = "discord.com",
// //ProxyIPAddres="104.16.10.231",
// Hosts = new List<string>{
// "discordapp.com",
// "dl.discordapp.net",
// "media.discordapp.net",
// "images-ext-2.discordapp.net",
// "images-ext-1.discordapp.net",
// "support.discordapp.com",
// "url9177.discordapp.com",
// "canary-api.discordapp.com",
// "cdn-ptb.discordapp.com",
// "ptb.discordapp.com",
// "status.discordapp.com",
// "cdn-canary.discordapp.com",
// "cdn.discordapp.com",
// "streamkit.discordapp.com",
// "i18n.discordapp.com" ,
// "url9624.discordapp.com",
// "url7195.discordapp.com",
// "merch.discordapp.com",
// "printer.discordapp.com",
// "canary.discordapp.com",
// "apps.discordapp.com",
// "pax.discordapp.com",
// },
// DomainTag = DomainTag.Discord,
// IsEnable= false,
//},
new ProxyDomainModel{
Index=5,
Name=Resources.Twitch,
Domains = new List<string>{ "twitch.tv" },
ToDomain="twitch.map.fastly.net",
Hosts = new List<string>{
"twitch.tv",
"www.twitch.tv",
"m.twitch.tv",
"app.twitch.tv",
"music.twitch.tv",
"badges.twitch.tv",
"blog.twitch.tv",
"inspector.twitch.tv",
"stream.twitch.tv",
"dev.twitch.tv",
"clips.twitch.tv",
"spade.twitch.tv",
"gql.twitch.tv",
"vod-secure.twitch.tv",
"vod-storyboards.twitch.tv",
"trowel.twitch.tv",
"countess.twitch.tv",
"extension-files.twitch.tv",
"vod-metro.twitch.tv",
"pubster.twitch.tv",
"help.twitch.tv",
"passport.twitch.tv",
"id.twitch.tv",
"link.twitch.tv",
"id-cdn.twitch.tv",
"player.twitch.tv",
"api.twitch.tv",
"cvp.twitch.tv",
"clips-media-assets2.twitch.tv",
"client-event-reporter.twitch.tv",
"gds-vhs-drops-campaign-images.twitch.tv",
"us-west-2.uploads-regional.twitch.tv",
"assets.help.twitch.tv",
"discuss.dev.twitch.tv",
"pubsub-edge.twitch.tv",
"irc-ws.chat.twitch.tv",
"irc-ws-r.chat.twitch.tv",
//"platform.twitter.com",
//"usher.ttvnw.net",
},
DomainTag = DomainTag.Twitch,
IsEnable= false,
},
new ProxyDomainModel{
Index=6,
Name=Resources.OriginDownload,
Domains = new List<string>{"origin-a.akamaihd.net" },
ToDomain = "cctv4-lh.akamaihd.net",
Hosts = new List<string>{ "origin-a.akamaihd.net"},
DomainTag = DomainTag.OriginGameDownload,
IsEnable= false,
},
//new ProxyDomainModel{
// Name=Resources.UplayUpdate,
// Domains = new List<string>{"static3.cdn.ubi.com" },
// ToDomain = "static3.cdn.ubi.com",
// Hosts = new List<string>{ "static3.cdn.ubi.com"},
// DomainTag = DomainTag.UplayUpdate,
// IsEnable= false,
//},
new ProxyDomainModel{
Index=7,
Name=Resources.GOG,
Domains = new List<string>{ "gog.com" },
ToDomain = "api.gog.com",
Hosts = new List<string>{
"www.gog.com",
"images.gog.com",
"images-1.gog.com",
"images-2.gog.com",
"images-3.gog.com",
"images-4.gog.com",
"webinstallers.gog.com",
"menu.gog.com",
"auth.gog.com",
"login.gog.com",
//"api.gog.com",
"reviews.gog.com",
"insights-collector.gog.com",
"remote-config.gog.com",
"external-accounts.gog.com",
"chat.gog.com",
"presence.gog.com",
"external-users.gog.com",
"gamesdb.gog.com",
"gameplay.gog.com",
"cfg.gog.com",
"notifications.gog.com",
"users.gog.com",
},
DomainTag = DomainTag.GOG,
IsEnable= false,
},
new ProxyDomainModel{
Index=8,
Name=Resources.GoogleRecaptchaCode,
Domains = new List<string>{"www.google.com" },
ToDomain = "kh.google.com",
Hosts = new List<string>{ "www.google.com"},
DomainTag = DomainTag.GoogleCode,
IsEnable= false,
},
});
{
new ProxyDomainModel{
Index=0,
Name=Resources.SteamCommunity,
Domains = new List<string>{"steamcommunity.com" },
//ToDomain = "steamcommunity-a.akamaihd.net",
ToDomain = "steampowered.com",
Hosts = new List<string>{ "steamcommunity.com", "www.steamcommunity.com"},
DomainTag = DomainTag.SteamCommunity,
IsEnable= true,
},
new ProxyDomainModel{
Index=1,
Name=Resources.SteamStore,
Domains = new List<string>{"steampowered.com" },
//ToDomain = "steamstore-a.akamaihd.net",
ToDomain = "steampowered.com",
Hosts = new List<string>{ "store.steampowered.com", "api.steampowered.com"},
DomainTag = DomainTag.SteamStore,
IsEnable= false,
},
new ProxyDomainModel{
Index=2,
Name=Resources.SteamImage,
Domains = new List<string>{"steamcdn-a.akamaihd.net" },
ToDomain = "cdn.akamai.steamstatic.com",
//ProxyIPAddres = "184.50.87.34",
Hosts = new List<string>{ "steamcdn-a.akamaihd.net"},
DomainTag = DomainTag.SteamImage,
IsEnable= false,
},
new ProxyDomainModel{
Index=3,
Name=Resources.SteamChat,
Domains = new List<string>{"steam-chat.com" },
//ToDomain = "steamstore-a.akamaihd.net",
ToDomain = "steampowered.com",
Hosts = new List<string>{ "steam-chat.com"},
DomainTag = DomainTag.SteamChat,
IsEnable= false,
},
new ProxyDomainModel{
Index=4,
Name=Resources.Discord,
Domains = new List<string>{ "discordapp.com","discordapp.net" },
//ToDomain = "discord.com",
ProxyIPAddres="162.159.133.232",
Hosts = new List<string>{
"discordapp.com",
"dl.discordapp.net",
"media.discordapp.net",
"images-ext-2.discordapp.net",
"images-ext-1.discordapp.net",
"support.discordapp.com",
"url9177.discordapp.com",
"canary-api.discordapp.com",
"cdn-ptb.discordapp.com",
"ptb.discordapp.com",
"status.discordapp.com",
"cdn-canary.discordapp.com",
"cdn.discordapp.com",
"streamkit.discordapp.com",
"i18n.discordapp.com" ,
"url9624.discordapp.com",
"url7195.discordapp.com",
"merch.discordapp.com",
"printer.discordapp.com",
"canary.discordapp.com",
"apps.discordapp.com",
"pax.discordapp.com",
},
//ServerName= "discord.com",
DomainTag = DomainTag.Discord,
IsEnable= false,
},
new ProxyDomainModel{
Index=5,
Name=Resources.Twitch,
Domains = new List<string>{ "twitch.tv" ,"usher.ttvnw.net"},
ToDomain="twitch.map.fastly.net",
Hosts = new List<string>{
"twitch.tv",
"www.twitch.tv",
"m.twitch.tv",
"app.twitch.tv",
"music.twitch.tv",
"badges.twitch.tv",
"blog.twitch.tv",
"inspector.twitch.tv",
"stream.twitch.tv",
"dev.twitch.tv",
"clips.twitch.tv",
"spade.twitch.tv",
"gql.twitch.tv",
"vod-secure.twitch.tv",
"vod-storyboards.twitch.tv",
"trowel.twitch.tv",
"countess.twitch.tv",
"extension-files.twitch.tv",
"vod-metro.twitch.tv",
"pubster.twitch.tv",
"help.twitch.tv",
"passport.twitch.tv",
"id.twitch.tv",
"link.twitch.tv",
"id-cdn.twitch.tv",
"player.twitch.tv",
"api.twitch.tv",
"cvp.twitch.tv",
"clips-media-assets2.twitch.tv",
"client-event-reporter.twitch.tv",
"gds-vhs-drops-campaign-images.twitch.tv",
"us-west-2.uploads-regional.twitch.tv",
"assets.help.twitch.tv",
"discuss.dev.twitch.tv",
"pubsub-edge.twitch.tv",
"irc-ws.chat.twitch.tv",
"irc-ws-r.chat.twitch.tv",
//"platform.twitter.com",
"usher.ttvnw.net",
},
DomainTag = DomainTag.Twitch,
IsEnable= false,
},
new ProxyDomainModel{
Index=6,
Name=Resources.OriginDownload,
Domains = new List<string>{"origin-a.akamaihd.net" },
ToDomain = "cctv4-lh.akamaihd.net",
Hosts = new List<string>{ "origin-a.akamaihd.net"},
DomainTag = DomainTag.OriginGameDownload,
IsEnable= false,
},
//new ProxyDomainModel{
//Name=Resources.UplayUpdate,
//Domains = new List<string>{"static3.cdn.ubi.com" },
//ToDomain = "static3.cdn.ubi.com",
//Hosts = new List<string>{ "static3.cdn.ubi.com"},
//DomainTag = DomainTag.UplayUpdate,
//IsEnable= false,
//},
//new ProxyDomainModel{
//Index=7,
//Name=Resources.GOG,
//Domains = new List<string>{ "gog.com" },
//ToDomain = "api.gog.com",
//Hosts = new List<string>{
//"www.gog.com",
//"images.gog.com",
//"images-1.gog.com",
//"images-2.gog.com",
//"images-3.gog.com",
//"images-4.gog.com",
//"webinstallers.gog.com",
//"menu.gog.com",
//"auth.gog.com",
//"login.gog.com",
////"api.gog.com",
//"reviews.gog.com",
//"insights-collector.gog.com",
//"remote-config.gog.com",
//"external-accounts.gog.com",
//"chat.gog.com",
//"presence.gog.com",
//"external-users.gog.com",
//"gamesdb.gog.com",
//"gameplay.gog.com",
//"cfg.gog.com",
//"notifications.gog.com",
//"users.gog.com",
//},
//DomainTag = DomainTag.GOG,
//IsEnable= false,
//},
new ProxyDomainModel{
Index=8,
Name=Resources.GoogleRecaptchaCode,
Domains = new List<string>{"www.google.com" },
ToDomain = "kh.google.com",
Hosts = new List<string>{ "www.google.com"},
DomainTag = DomainTag.GoogleCode,
IsEnable= false,
},
new ProxyDomainModel{
Index=9,
Name=Resources.GithubContent,
Domains = new List<string>{"githubusercontent.com","raw.github.com" },
//ToDomain = "aw.githubusercontent.com",
ProxyIPAddres = "151.101.88.133",
Hosts = new List<string>{
"raw.github.com",
"raw.githubusercontent.com",
"camo.githubusercontent.com",
"cloud.githubusercontent.com",
"avatars0.githubusercontent.com",
"avatars1.githubusercontent.com",
"avatars2.githubusercontent.com",
"avatars3.githubusercontent.com",
"user-images.githubusercontent.com",
},
DomainTag = DomainTag.GithubContent,
IsEnable= false,
},
new ProxyDomainModel{
Index=10,
Name=Resources.Pixiv,
Domains = new List<string>{ "pixiv.net" },
ToDomain="www.fanbox.cc",
//ProxyIPAddres = "210.140.131.219",
Hosts = new List<string>{
"www.pixiv.net",
"touch.pixiv.net",
"source.pixiv.net",
"accounts.pixiv.net",
"imgaz.pixiv.net",
"app-api.pixiv.net",
"oauth.secure.pixiv.net",
"dic.pixiv.net",
"comic.pixiv.net",
"factory.pixiv.net",
"g-client-proxy.pixiv.net",
"sketch.pixiv.net",
"payment.pixiv.net",
"sensei.pixiv.net",
"novel.pixiv.net",
"ssl.pixiv.net",
"times.pixiv.net",
"recruit.pixiv.net",
"pixiv.net",
"p2.pixiv.net",
"matsuri.pixiv.net",
"m.pixiv.net",
"iracon.pixiv.net",
"inside.pixiv.net",
"i1.pixiv.net",
"help.pixiv.net",
"goods.pixiv.net",
"genepixiv.pr.pixiv.net",
"festa.pixiv.net",
"en.dic.pixiv.net",
"dev.pixiv.net",
"chat.pixiv.net",
"blog.pixiv.net",
"embed.pixiv.net",
"comic-api.pixiv.net",
"pay.pixiv.net",
},
DomainTag = DomainTag.GithubContent,
IsEnable= false,
},
});
public Lazy<IReadOnlyCollection<ProxyDomainModel>> ProxyDomains
{
get => _ProxyDomains;
@@ -295,7 +375,7 @@ namespace SteamTools.Services
public void InitJsScript()
{
var scripts = new List<ProxyScript>();
var dir = new DirectoryInfo(Const.SCRIPT_DIR);
var dir = new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, Const.SCRIPT_DIR));
if (!dir.Exists)
{
dir.Create();
+5 -5
View File
@@ -23,8 +23,8 @@ namespace SteamTools.Services
/// </summary>
private readonly string[] supportedCultureNames =
{
"zh-CN", // Resources.resx
"zh-TW",
"zh-Hans", // Resources.resx
"zh-Hant",
"en",
};
@@ -33,8 +33,8 @@ namespace SteamTools.Services
/// </summary>
private readonly Dictionary<string, string> supportedCultureSteamNames = new Dictionary<string, string>
{
{ "zh-CN","schinese"},
{ "zh-TW","tchinese"},
{ "zh-Hans","schinese"},
{ "zh-Hant","tchinese"},
{ "en","english"},
};
@@ -76,7 +76,7 @@ namespace SteamTools.Services
{
Resources.Culture = this.SupportedCultures.SingleOrDefault(x => x.Name == name);
GeneralSettings.Culture.Value = SteamTools.Properties.Resources.Culture?.Name;
Debug.WriteLine(SteamTools.Properties.Resources.ResourceManager.GetString("Welcome", Resources.Culture));
//Debug.WriteLine(SteamTools.Properties.Resources.ResourceManager.GetString("Welcome", Resources.Culture));
this.RaisePropertyChanged(nameof(this.Resources));
}
+46 -35
View File
@@ -94,43 +94,49 @@ namespace SteamTools.Services
public void Initialize()
{
Task.Run(async () =>
{
Thread.CurrentThread.IsBackground = true;
while (true)
{
if (Process.GetProcessesByName("steam").Length > 0)
{
if (!IsConnectToSteam)
{
IsConnectToSteam = ApiService.Initialize();
if (IsConnectToSteam)
{
var id = ApiService.GetSteamId64();
if (id == 76561197960265728)
{
//该64位id的steamID3等于0,是steam未获取到当前登录用户的默认返回值,所以直接重新获取
IsConnectToSteam = false;
continue;
}
CurrentSteamUser = await steamDbApiService.GetUserInfo(id);
var mainViewModel = (WindowService.Current.MainWindow as MainWindowViewModel);
mainViewModel.SteamAppPage.Initialize();
var t = new Task(async () =>
{
Thread.CurrentThread.IsBackground = true;
while (true)
{
if (Process.GetProcessesByName("steam").Length > 0)
{
if (!IsConnectToSteam)
{
if (ApiService.Initialize())
{
var id = ApiService.GetSteamId64();
if (id == 76561197960265728)
{
//该64位id的steamID3等于0,是steam未获取到当前登录用户的默认返回值,所以直接重新获取,
//希望这位用户不会用steam++,嗯...
ApiService.SteamClient.Dispose();
continue;
}
IsConnectToSteam = true;
CurrentSteamUser = await steamDbApiService.GetUserInfo(id);
CurrentSteamUser.IPCountry = ApiService.GetIPCountry();
var mainViewModel = (WindowService.Current.MainWindow as MainWindowViewModel);
await mainViewModel.SteamAppPage.Initialize();
#if DEBUG
mainViewModel.SystemTabItems[mainViewModel.SystemTabItems.Count - 1].Initialize();
await mainViewModel.SystemTabItems[mainViewModel.SystemTabItems.Count - 1].Initialize();
#endif
}
}
}
else
{
IsConnectToSteam = false;
//StatusService.Current.Notify(Resources.Steam_Not_Runing);
}
await Task.Delay(1000);
}
});
SteamConnectService.Current.DisposeSteamClient();
}
}
}
else
{
IsConnectToSteam = false;
//StatusService.Current.Notify(Resources.Steam_Not_Runing);
}
await Task.Delay(1500);
}
}, TaskCreationOptions.LongRunning);
t.ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted);
t.Start();
}
public void Initialize(int appid)
@@ -149,5 +155,10 @@ namespace SteamTools.Services
app.Process.Kill();
}
}
public void DisposeSteamClient()
{
ApiService.SteamClient.Dispose();
}
}
}
+6 -3
View File
@@ -55,12 +55,12 @@ namespace SteamTools.Services
throw new InvalidOperationException();
}
public DialogWindowViewModel ShowDialogWindow(string content)
public bool ShowDialogWindow(string content)
{
return ShowDialogWindow(content, ProductInfo.Title);
}
public DialogWindowViewModel ShowDialogWindow(string content, string title)
public bool ShowDialogWindow(string content, string title)
{
var dialog = new DialogWindowViewModel
{
@@ -70,7 +70,10 @@ namespace SteamTools.Services
var window = new MessageDialog { DataContext = dialog };
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
window.ShowDialog();
return dialog;
dialog.Topmost = true;
dialog.Activate();
dialog.Topmost = false;
return dialog.DialogResult;
}
#region disposable members
+32 -11
View File
@@ -32,13 +32,17 @@
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Description>Steam++</Description>
<Description>「Steam++」是一个包含多种Steam工具功能的工具箱。</Description>
<Platforms>AnyCPU;x86</Platforms>
<Product>SteamTools</Product>
<PackageId />
<Version>1.0.3.2</Version>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net472|AnyCPU'">
@@ -68,7 +72,6 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="LivetCask" Version="3.0.1" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.0.8" />
</ItemGroup>
@@ -78,17 +81,14 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="LivetCask" Version="3.0.1" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.14" />
</ItemGroup>
<!--<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PackageReference Include="LivetCask" Version="3.0.2" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.14" />
</ItemGroup>-->
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0-windows'">
<PackageReference Include="LivetCask" Version="3.0.2" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.14" />
</ItemGroup>
@@ -109,10 +109,14 @@
<None Remove="Resources\Asstes\save.png" />
<None Remove="Resources\Asstes\seek.png" />
<None Remove="Resources\Asstes\unlock.png" />
<None Remove="Resources\Asstes\wechatpay.png" />
<None Remove="Resources\Asstes\wechatdonate.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="LivetCask.Behaviors" Version="3.2.3.1" />
<PackageReference Include="LivetCask.EventListeners" Version="3.2.3.1" />
<PackageReference Include="LivetCask.Messaging" Version="3.2.3.1" />
<PackageReference Include="LivetCask.Mvvm" Version="3.2.3.1" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
@@ -137,7 +141,7 @@
<Resource Include="Resources\Asstes\save.png" />
<Resource Include="Resources\Asstes\seek.png" />
<Resource Include="Resources\Asstes\unlock.png" />
<Resource Include="Resources\Asstes\wechatpay.png" />
<Resource Include="Resources\Asstes\wechatdonate.png" />
</ItemGroup>
<ItemGroup>
@@ -193,7 +197,7 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.zh-TW.resx">
<EmbeddedResource Update="Properties\Resources.zh-Hant.resx">
<DependentUpon>Resources.resx</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Properties\Resources.en.resx">
@@ -237,6 +241,10 @@
<Page Update="Resources\Styles\Controls.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Content\About\AboutDonateList.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Content\About\AboutUpdateHistory.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
@@ -277,6 +285,9 @@
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Pages\SteamIdleCardPage.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
<Page Update="Views\Pages\SteamAppPage.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
@@ -296,6 +307,9 @@
<Page Update="Views\Pages\WelcomePage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Window\AuthTradeWindow.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
<Page Update="Views\Window\ShowAuthWindow.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
@@ -310,8 +324,7 @@
<ProjectReference Include="..\SteamTool.Authenticator\SteamTool.Authenticator.csproj" />
<ProjectReference Include="..\SteamTool.Core\SteamTool.Core.csproj" />
<ProjectReference Include="..\SteamTool.Proxy\SteamTool.Proxy.csproj" />
<ProjectReference Include="..\SteamTools.Composition\SteamTool.Composition.csproj" />
<ProjectReference Include="..\SteamTools.Steam.Service\SteamTool.Steam.Service.csproj" />
<ProjectReference Include="..\SteamTool.Steam.Service\SteamTool.Steam.Service.csproj" />
</ItemGroup>
<ItemGroup>
@@ -330,11 +343,14 @@
<Reference Include="MetroTrilithon.Desktop">
<HintPath>..\Lib\MetroTrilithon.Desktop.dll</HintPath>
</Reference>
<Reference Include="SimpleSyndicate.UriTemplate">
<HintPath>..\Lib\SimpleSyndicate.UriTemplate.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Update="log\Log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@@ -346,8 +362,13 @@
<None Update="scripts\Steam自动探索队列.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="scripts\Steam解锁不可描述游戏商店页.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="scripts\Steam解锁区域限制.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties /></VisualStudio></ProjectExtensions>
</Project>
+51 -50
View File
@@ -11,68 +11,69 @@ using SteamTools.Services;
namespace SteamTools.ViewModels
{
public abstract class TabItemViewModel : ItemViewModel, ITabItem
{
#region Name 変更通知
public abstract class TabItemViewModel : ItemViewModel, ITabItem
{
#region Name 変更通知
public abstract string Name { get; protected set; }
public abstract string Name { get; protected set; }
#endregion
#endregion
#region Badge 変更通知
#region Badge 変更通知
private int? _Badge;
private int? _Badge;
public virtual int? Badge
{
get { return this._Badge; }
protected set
{
if (this._Badge != value)
{
this._Badge = value;
this.RaisePropertyChanged();
}
}
}
public virtual int? Badge
{
get { return this._Badge; }
protected set
{
if (this._Badge != value)
{
this._Badge = value;
this.RaisePropertyChanged();
}
}
}
#endregion
#endregion
#region Status 変更通知
#region Status 変更通知
private ViewModel _Status;
private ViewModel _Status;
/// <summary>
/// 获取状态栏中显示的状态
/// </summary>
public virtual ViewModel Status
{
get { return this._Status; }
protected set
{
if (this._Status != value)
{
this._Status = value;
this.RaisePropertyChanged();
}
}
}
/// <summary>
/// 获取状态栏中显示的状态
/// </summary>
public virtual ViewModel Status
{
get { return this._Status; }
protected set
{
if (this._Status != value)
{
this._Status = value;
this.RaisePropertyChanged();
}
}
}
#endregion
#endregion
protected TabItemViewModel()
{
if (Models.Helper.IsInDesignMode) return;
protected TabItemViewModel()
{
if (Models.Helper.IsInDesignMode) return;
this.CompositeDisposable.Add(new PropertyChangedEventListener(ResourceService.Current)
{
(sender, args) => this.RaisePropertyChanged(nameof(this.Name)),
});
}
this.CompositeDisposable.Add(new PropertyChangedEventListener(ResourceService.Current)
{
(sender, args) => this.RaisePropertyChanged(nameof(this.Name)),
});
}
internal virtual void Initialize()
{
}
}
internal async virtual Task Initialize()
{
await Task.CompletedTask;
}
}
}
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows;
using SteamTools.Win32;
using MetroRadiance.Interop.Win32;
using System.Diagnostics;
using SteamTool.Core.Common;
using System.Runtime.InteropServices;
using SteamTools.Services;
using SteamTool.Core;
using System.IO;
using SteamTools.Properties;
using SteamTool.Model;
using Newtonsoft.Json;
using System.Threading;
namespace SteamTools.ViewModels
{
public class AboutDonateListViewModel : Livet.ViewModel
{
private readonly HttpServices httpServices = SteamToolCore.Instance.Get<HttpServices>();
public class DonateRecord
{
public long Index { get; set; }
public string Name { get; set; }
public decimal Amount { get; set; }
public string OrderNumber { get; set; }
public string Remark { get; set; }
public short PayType { get; set; }
public DateTime PayTime { get; set; }
}
private IReadOnlyCollection<DonateRecord> _DonateRecordList;
public IReadOnlyCollection<DonateRecord> DonateRecordList
{
get => this._DonateRecordList;
set
{
if (this._DonateRecordList != value)
{
this._DonateRecordList = value;
this.RaisePropertyChanged();
}
}
}
public AboutDonateListViewModel()
{
Task.Run(() =>
{
httpServices.Get(Const.REWARDMELIST_URL).ContinueWith(s =>
{
if (!string.IsNullOrEmpty(s.Result))
{
DonateRecordList = JsonConvert.DeserializeObject<List<DonateRecord>>(s.Result).OrderByDescending(o => o.PayTime).ToList();
}
});
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted);
}
}
}
@@ -69,7 +69,7 @@ namespace SteamTools.ViewModels
}
p.Close();
standardOutput.Close();
});
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted);
}
}
}
@@ -17,6 +17,7 @@ using SteamTool.Steam.Service;
using SteamTool.Model;
using Newtonsoft.Json;
using SteamTools.Models.Settings;
using System.IO;
namespace SteamTools.ViewModels
{
@@ -33,7 +34,7 @@ namespace SteamTools.ViewModels
{
if (IsRefreshGameListCache)
{
StatusService.Current.Notify("正在下在Steam游戏数据中...");
StatusService.Current.Notify("正在下载Steam游戏数据中...");
return;
}
StatusService.Current.Notify("刷新Steam游戏数据");
@@ -42,12 +43,12 @@ namespace SteamTools.ViewModels
{
var result = await SteamworksWebApi.GetAllSteamAppsString();
if (GeneralSettings.IsSteamAppListLocalCache)
SteamTool.UpdateAppListJson(result, Const.APP_LIST_FILE);
SteamTool.UpdateAppListJson(result, Path.Combine(AppContext.BaseDirectory, Const.APP_LIST_FILE));
var apps = JsonConvert.DeserializeObject<SteamApps>(result).AppList.Apps;
apps = apps.DistinctBy(d => d.AppId).ToList();
//SteamConnectService.Current.SteamApps = apps;
SteamConnectService.Current.SteamApps = SteamConnectService.Current.ApiService.OwnsApps(apps);
}).ContinueWith(s =>
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s =>
{
StatusService.Current.Notify("刷新Steam游戏数据完成");
IsRefreshGameListCache = false;
@@ -60,5 +61,10 @@ namespace SteamTools.ViewModels
StatusService.Current.Notify("未检测到Steam运行");
}
}
public void CheckUpdate_Click()
{
AutoUpdateService.Current.CheckUpdate();
}
}
}
@@ -46,7 +46,7 @@ namespace SteamTools.ViewModels
CanExecuteFunc = () => true,
CommandAction = () =>
{
var mainWindow = (App.Current.MainWindow.DataContext as MainWindowViewModel);
var mainWindow = (WindowService.Current.MainWindow as MainWindowViewModel);
mainWindow.IsVisible = true;
}
};
@@ -55,14 +55,11 @@ namespace SteamTools.ViewModels
public void ShowUrl()
{
//var mainWindow = (App.Current.MainWindow.DataContext as MainWindowViewModel);
//mainWindow.IsVisible = !mainWindow.IsVisible;
if (SteamConnectService.Current.IsConnectToSteam)
{
Process.Start(SteamConnectService.Current.CurrentSteamUser.ProfileUrl);
}
else
else
{
Process.Start(Const.MY_PROFILE_URL);
}
@@ -81,7 +78,7 @@ namespace SteamTools.ViewModels
/// </summary>
public void NavigateTabItem(string index)
{
var mainWindow = (App.Current.MainWindow.DataContext as MainWindowViewModel);
var mainWindow = (WindowService.Current.MainWindow as MainWindowViewModel);
mainWindow.IsVisible = true;
int.TryParse(index, out int i);
if (i < 0)
+18 -16
View File
@@ -14,6 +14,8 @@ using System.Windows.Interop;
using SteamTools.Services;
using SteamTools.Properties;
using MetroRadiance.Interop.Win32;
using SteamTool.Core.Common;
using SteamTools.Models.Settings;
namespace SteamTools.ViewModels
{
@@ -70,10 +72,11 @@ namespace SteamTools.ViewModels
ChangeWindowVisible();
if (value)
{
App.Current.MainWindow.Topmost = true;
App.Current.MainWindow.WindowState = WindowState.Normal;
User32Window.FlashWindow(new WindowInteropHelper(App.Current.MainWindow).Handle);
App.Current.MainWindow.Topmost = false;
//App.Current.MainWindow.Topmost = true;
this.Activate();
//User32Window.FlashWindow(new WindowInteropHelper(App.Current.MainWindow).Handle);
//App.Current.MainWindow.Topmost = false;
}
}
}
@@ -122,24 +125,22 @@ namespace SteamTools.ViewModels
if (!this.IsInitialized)
{
base.Initialize();
await Task.Yield();
await Task.Run(() =>
await Task.Run(async () =>
{
foreach (var item in this.TabItems)
{
if (item == SteamAppPage)
continue;
item.Initialize();
await item.Initialize().ContinueWith(s =>
{
Logger.Error(s.Exception);
WindowService.Current.ShowDialogWindow(s.Exception.Message);
}, TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s => s.Dispose());
}
}).ContinueWith(s => s.Dispose());
//foreach (var item in this.TabItems)
//{
// if (item == SteamAppPage)
// continue;
// item.Initialize();
//}
StatusService.Current.Set(Resources.Ready);
});
this.IsInitialized = true;
StatusService.Current.Set(Resources.Ready);
}
}
@@ -148,18 +149,19 @@ namespace SteamTools.ViewModels
/// </summary>
public void ChangeWindowVisible()
{
App.Current.MainWindow = App.Current.MainWindow ?? new MainWindow();
App.Current.MainWindow = App.Current.MainWindow ?? WindowService.Current.GetMainWindow();
if (IsVisible)
{
App.Current.MainWindow.Show();
//App.Current.MainWindow.Focus();
App.Current.MainWindow.WindowState = WindowState.Normal;
this.Activate();
User32Window.FlashWindow(new WindowInteropHelper(App.Current.MainWindow).Handle);
}
else
{
App.Current.MainWindow.WindowState = WindowState.Minimized;
App.Current.MainWindow.Hide();
//App.Current.MainWindow.Visibility = Visibility.Collapsed;
}
}
}
@@ -26,14 +26,6 @@ namespace SteamTools.ViewModels
protected set { throw new NotImplementedException(); }
}
internal override void Initialize()
{
if (ProxySettings.ProgramStartupRunProxy.Value)
{
ProxyService.Current.ProxyStatus = true;
}
}
public void SetupCertificate_OnClick()
{
ProxyService.Current.Proxy.SetupCertificate();
@@ -62,7 +54,7 @@ namespace SteamTools.ViewModels
{
foreach (var file in fileDialog.FileNames)
{
File.Copy(file, $@"{Const.SCRIPT_DIR}\{Path.GetFileName(file)}", true);
File.Copy(file, $@"{Path.Combine(AppContext.BaseDirectory, Const.SCRIPT_DIR)}\{Path.GetFileName(file)}", true);
}
ProxyService.Current.InitJsScript();
}
@@ -70,7 +62,7 @@ namespace SteamTools.ViewModels
public void OpenScriptFileDir_Click()
{
Process.Start(Const.SCRIPT_DIR);
Process.Start(Path.Combine(AppContext.BaseDirectory, Const.SCRIPT_DIR));
}
public void DeleteScript_OnClick(string path)
@@ -1,4 +1,5 @@
using MetroRadiance.Platform;
using SteamTool.Core.Common;
using SteamTool.Steam.Service.Local;
using SteamTools.Services;
using System;
@@ -36,14 +37,16 @@ namespace SteamTools.ViewModels
}
internal override void Initialize()
internal async override Task Initialize()
{
Task.Run(() =>
await Task.Run(() =>
{
DebugText += SteamConnectService.Current.IsConnectToSteam;
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.GetSteamId64();
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.CurrentSteamUser.SteamId3_Int;
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.SteamClient.SteamUtils.GetAppId();
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.SteamClient.SteamApps008.IsAppInstalled(730);
@@ -52,11 +55,28 @@ namespace SteamTools.ViewModels
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.SteamClient.SteamApps008.GetAppInstallDir(730);
DebugText += Environment.NewLine;
}).ContinueWith(s => s.Dispose());
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s => s.Dispose());
}
public void Test_OnClick()
{
Task.Run(() =>
{
DebugText += SteamConnectService.Current.IsConnectToSteam;
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.GetSteamId64();
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.CurrentSteamUser.SteamId3_Int;
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.SteamClient.SteamUtils.GetAppId();
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.SteamClient.SteamApps008.IsAppInstalled(730);
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.SteamClient.SteamApps008.IsSubscribedFromFamilySharing();
DebugText += Environment.NewLine;
DebugText += SteamConnectService.Current.ApiService.SteamClient.SteamApps008.GetAppInstallDir(730);
DebugText += Environment.NewLine;
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s => s.Dispose());
}
}
}
@@ -26,21 +26,6 @@ namespace SteamTools.ViewModels
protected set { throw new NotImplementedException(); }
}
private BindingList<WinAuthAuthenticator> _Authenticators;
public BindingList<WinAuthAuthenticator> Authenticators
{
get => this._Authenticators;
set
{
if (this._Authenticators != value)
{
this._Authenticators = value;
this.RaisePropertyChanged();
}
}
}
public bool _IsEdit;
public bool IsEdit
{
@@ -55,10 +40,16 @@ namespace SteamTools.ViewModels
}
}
public LocalAuthPageViewModel()
{
//AuthService.Current.Subscribe(nameof(AuthService.Current.Authenticators),
// () => { Authenticators = new BindingList<WinAuthAuthenticator>(AuthService.Current.Authenticators); }).AddTo(this);
}
public void ImageDelete_Click(WinAuthAuthenticator auth)
{
Authenticators.Remove(auth);
if (Authenticators.Count == 0)
AuthService.Current.Authenticators.Remove(auth);
if (AuthService.Current.Authenticators.Count == 0)
{
AuthSettings.Authenticators.Value = null;
IsEdit = false;
@@ -94,40 +85,35 @@ namespace SteamTools.ViewModels
TaskbarService.Current.Notify("已复制令牌");
}
internal override void Initialize()
{
AuthService.Current.Subscribe(nameof(AuthService.Current.Authenticators), this.Update).AddTo(this);
//Task.Run(() =>
//{
//});
}
private void Update()
{
Authenticators = AuthService.Current.Authenticators;
}
public void AddAuth_Click()
{
new AddAuthWindow() { DataContext = new AddAuthWindowViewModel() }.ShowDialog();
new AddAuthWindow() { DataContext = new AddAuthWindowViewModel() }.Show();
}
public void EditAuth_Click()
{
if (Authenticators.Count < 1)
if (AuthService.Current.Authenticators == null || !AuthService.Current.Authenticators.Any())
{
StatusService.Current.Notify("没有可编辑的令牌");
return;
}
this.IsEdit = !IsEdit;
if (!IsEdit)
{
AuthSettings.Authenticators.Value = AuthService.ConvertJsonAuthenticator(Authenticators.ToList()).CompressString();
AuthSettings.Authenticators.Value = AuthService.ConvertJsonAuthenticator(AuthService.Current.Authenticators.ToList()).CompressString();
}
}
public void ImageShowAuth_Click(WinAuthAuthenticator auth)
{
new ShowAuthWindow() { DataContext = new ShowAuthWindowViewModel(auth) }.ShowDialog();
new ShowAuthWindow() { DataContext = new ShowAuthWindowViewModel(auth) }.Show();
}
public void ImageAuthTrade_Click(WinAuthAuthenticator auth)
{
new AuthTradeWindow() { DataContext = new AuthTradeWindowViewModel(auth) }.Show();
}
}
}
@@ -13,6 +13,8 @@ using System.Diagnostics;
using SteamTool.Steam.Service.Web;
using SteamTool.Steam.Service;
using SteamTools.Services;
using SteamTool.Core.Common;
using SteamTools.Models.Settings;
namespace SteamTools.ViewModels
{
@@ -30,9 +32,9 @@ namespace SteamTools.ViewModels
/// <summary>
/// steam记住的用户列表
/// </summary>
private List<SteamUser> _steamUsers;
private BindingList<SteamUser> _steamUsers;
public List<SteamUser> SteamUsers
public BindingList<SteamUser> SteamUsers
{
get => this._steamUsers;
set
@@ -45,12 +47,16 @@ namespace SteamTools.ViewModels
}
}
internal override void Initialize()
internal async override Task Initialize()
{
StatusService.Current.Notify("加载本地Steam用户数据");
Task.Run(async () =>
await Task.Run(async () =>
{
SteamUsers = steamService.GetAllUser();
SteamUsers = new BindingList<SteamUser>(steamService.GetAllUser());
if (SteamUsers?.Count < 1)
{
StatusService.Current.Notify("没有检测到Steam用户数据");
}
var users = SteamUsers.ToArray();
for (var i = 0; i < SteamUsers.Count; i++)
{
@@ -62,16 +68,9 @@ namespace SteamTools.ViewModels
users[i].Timestamp = temp.Timestamp;
users[i].LastLoginTime = temp.LastLoginTime;
}
if (SteamUsers.Count > 0)
{
SteamUsers = users.OrderByDescending(o => o.MostRecent).ThenByDescending(o => o.RememberPassword).ThenByDescending(o => o.LastLoginTime).ToList();
StatusService.Current.Notify("加载本地Steam用户数据完成");
}
else
{
StatusService.Current.Notify("没有检测到Steam用户数据");
}
}).ContinueWith(s => s.Dispose());
SteamUsers = new BindingList<SteamUser>(users.OrderByDescending(o => o.MostRecent).ThenByDescending(o => o.RememberPassword).ThenByDescending(o => o.LastLoginTime).ToList());
StatusService.Current.Notify("加载本地Steam用户数据完成");
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s => s.Dispose());
}
@@ -79,7 +78,7 @@ namespace SteamTools.ViewModels
{
steamService.SetCurrentUser(parameter);
steamService.KillSteamProcess();
steamService.StartSteam();
steamService.StartSteam(GeneralSettings.SteamStratParameter.Value);
SteamConnectService.Current.IsConnectToSteam = false;
}
@@ -87,5 +86,15 @@ namespace SteamTools.ViewModels
{
Process.Start(parameter);
}
public void DeleteAccount_OnClick(SteamUser user)
{
var result = WindowService.Current.MainWindow.Dialog("确定要删除这条本地记录帐户数据吗?\r\n这将会删除此账户在本地的Steam缓存数据。");
if (result)
{
steamService.DeleteSteamLocalUserData(user);
SteamUsers.Remove(user);
}
}
}
}
@@ -101,41 +101,46 @@ namespace SteamTools.ViewModels
AppTypeFilter = new SteamAppTypeFilter(this.Update);
}
internal override void Initialize()
internal override async Task Initialize()
{
StatusService.Current.Notify("加载Steam游戏数据");
Task.Run(async () =>
{
var apps = SteamTool.GetAppListJson(Const.APP_LIST_FILE);
if (apps == null || !apps.Any())
{
var result = await SteamworksWebApi.GetAllSteamAppsString();
if (string.IsNullOrEmpty(result))
{
StatusService.Current.Notify("下载Steam游戏数据失败,请尝试开启社区反代刷新");
}
if (GeneralSettings.IsSteamAppListLocalCache)
SteamTool.UpdateAppListJson(result, Const.APP_LIST_FILE);
apps = JsonConvert.DeserializeObject<SteamApps>(result).AppList.Apps;
}
apps = apps.DistinctBy(d => d.AppId).ToList();
//SteamConnectService.Current.SteamApps = apps;
SteamConnectService.Current.SteamApps = SteamConnectService.Current.ApiService.OwnsApps(apps);
await Task.Run(async () =>
{
var apps = SteamTool.GetAppListJson(Path.Combine(AppContext.BaseDirectory, Const.APP_LIST_FILE));
if (apps == null || !apps.Any())
{
var result = await SteamworksWebApi.GetAllSteamAppsString();
if (string.IsNullOrEmpty(result))
{
StatusService.Current.Notify("下载Steam游戏数据失败,请尝试开启社区反代刷新");
return;
}
if (GeneralSettings.IsSteamAppListLocalCache)
SteamTool.UpdateAppListJson(result, Path.Combine(AppContext.BaseDirectory, Const.APP_LIST_FILE));
apps = JsonConvert.DeserializeObject<SteamApps>(result).AppList.Apps;
}
apps = apps.DistinctBy(d => d.AppId).ToList();
//SteamConnectService.Current.SteamApps = apps;
SteamConnectService.Current.SteamApps = SteamConnectService.Current.ApiService.OwnsApps(apps);
this.updateSource
.Do(_ => this.IsReloading = true)
.SelectMany(x => this.UpdateAsync())
.Do(_ => this.IsReloading = false)
.Subscribe()
.AddTo(this);
this.updateSource
.Do(_ => this.IsReloading = true)
.SelectMany(x => this.UpdateAsync())
.Do(_ => this.IsReloading = false)
.Subscribe()
.AddTo(this);
SteamConnectService.Current.Subscribe(nameof(SteamConnectService.Current.SteamApps), this.Update).AddTo(this);
SteamConnectService.Current.Subscribe(nameof(SteamConnectService.Current.SteamApps), this.Update).AddTo(this);
}).ContinueWith(s =>
{
StatusService.Current.Notify("加载Steam游戏数据完成");
s.Dispose();
});
}).ContinueWith(s =>
{
Logger.Error(s.Exception);
WindowService.Current.ShowDialogWindow(s.Exception.Message, "加载Steam游戏数据失败");
}, TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s =>
{
StatusService.Current.Notify("加载Steam游戏数据完成");
s.Dispose();
});
}
public void Update()
@@ -9,29 +9,29 @@ using SteamTools.Services;
namespace SteamTools.ViewModels
{
public class WelcomePageViewModel: TabItemViewModel
{
public class WelcomePageViewModel : TabItemViewModel
{
public override string Name
{
get { return Properties.Resources.Welcome; }
protected set { throw new NotImplementedException(); }
}
public override bool IsShowTab
{
get { return GeneralSettings.IsShowStartPage.Value; }
}
public override string Name
{
get { return Properties.Resources.Welcome; }
protected set { throw new NotImplementedException(); }
}
public override bool IsShowTab
{
get { return GeneralSettings.IsShowStartPage.Value; }
}
public MainWindowViewModel Content { get; }
public MainWindowViewModel Content { get; }
public WelcomePageViewModel(MainWindowViewModel owner)
{
this.Content = owner;
}
public WelcomePageViewModel(MainWindowViewModel owner)
{
this.Content = owner;
}
internal override void Initialize()
{
}
internal async override Task Initialize()
{
await Task.CompletedTask;
}
}
}
@@ -1,6 +1,7 @@
using MetroTrilithon.Mvvm;
using SAM.API.Types;
using SteamTool.Core;
using SteamTool.Core.Common;
using SteamTool.Model;
using SteamTool.Steam.Service;
using SteamTools.Properties;
@@ -138,7 +139,7 @@ namespace SteamTools.ViewModels
SteamConnectService.Current.ApiService.RunCallbacks(false);
await Task.Delay(1500);
}
});
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted);
this.RefreshStats_Click();
//this.Initialize();
@@ -149,10 +149,6 @@ namespace SteamTools.ViewModels
if (File.Exists(WinAuthFileName))
{
StatusService.Current.Set("导入WinAuth令牌中...");
//Task.Run(() =>
//{
//});
AuthService.Current.ImportAuthenticators(WinAuthFileName);
AuthSettings.Authenticators.Value = AuthService.ConvertJsonAuthenticator(AuthService.Current.Authenticators).CompressString();
//(WindowService.Current.MainWindow as MainWindowViewModel).LocalAuthPage
@@ -0,0 +1,36 @@
using Microsoft.Win32;
using SteamTools.Models;
using SteamTools.Models.Settings;
using SteamTools.Properties;
using SteamTools.Services;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using SteamTool.Core.Common;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using WinAuth;
namespace SteamTools.ViewModels
{
public class AuthTradeWindowViewModel : MainWindowViewModelBase
{
private SteamAuthenticator _Authenticator;
public AuthTradeWindowViewModel()
{
this.Title = ProductInfo.Title + " | " + Resources.Auth_TradeTitle;
}
public AuthTradeWindowViewModel(WinAuthAuthenticator auth)
{
_Authenticator = auth.AuthenticatorData as SteamAuthenticator;
this.Title = ProductInfo.Title + " | " + Resources.Auth_TradeTitle;
}
}
}
@@ -48,7 +48,7 @@
<LineBreak />
<Run Text="微信" FontSize="16"/>
<LineBreak/>
<Image Source="pack://application:,,,/Resources/Asstes/wechatpay.png" Height="300"></Image>
<Image Source="pack://application:,,,/Resources/Asstes/wechatdonate.png" Height="300"></Image>
<LineBreak/>
<LineBreak/>
<LineBreak/>
@@ -0,0 +1,53 @@
<UserControl x:Class="SteamTools.Views.Content.AboutDonateList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SteamTools.Views.Content"
xmlns:viewModel="clr-namespace:SteamTools.ViewModels"
xmlns:services="clr-namespace:SteamTools.Services"
xmlns:metro="http://schemes.grabacr.net/winfx/2014/controls"
xmlns:metro2="http://schemes.grabacr.net/winfx/2015/personal/controls"
xmlns:model="clr-namespace:SteamTool.Model;assembly=SteamTool.Model"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:livet="http://schemas.livet-mvvm.net/2011/wpf"
mc:Ignorable="d"
d:DesignHeight="400"
d:DesignWidth="600"
Padding="8"
Background="{DynamicResource ThemeBrushKey}"
d:DataContext="{d:DesignInstance viewModel:AboutDonateListViewModel}">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..\Common.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<DockPanel>
<TextBlock DockPanel.Dock="Top" Text="{Binding Resources.About_DonateList, Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
Style="{DynamicResource SettingsHeaderTextStyleKey}" />
<DockPanel Grid.Column="1">
<TextBlock DockPanel.Dock="Top">
<Run Text="十分感谢此列表的大佬们对我的支持与捐助,此工具的完善离不开以下大佬的支持:" Style="{StaticResource DetailTextElementStyleKey}" />
</TextBlock>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding DonateRecordList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel Margin="8">
<WrapPanel VerticalAlignment="Center">
<TextBlock Text="{Binding Name}" Foreground="{StaticResource ActiveForegroundBrushKey}" Margin="10,0,0,0" Width="50"></TextBlock>
<TextBlock Text="{Binding Amount,StringFormat={}{0:F2}元}" Foreground="{StaticResource ActiveForegroundBrushKey}" Margin="30,0,0,0" Width="70"></TextBlock>
<TextBlock Text="{Binding Remark}" Foreground="{StaticResource ActiveForegroundBrushKey}" Margin="30,0,0,0"></TextBlock>
</WrapPanel>
<TextBlock Text="{Binding PayTime,StringFormat='{}{0:yyyy年MM月dd日}',ConverterCulture=zh-CN}" Foreground="{StaticResource ActiveForegroundBrushKey}" Margin="10" HorizontalAlignment="Right"></TextBlock>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!--<WebBrowser x:Name="web" Opacity="0.2"></WebBrowser>-->
</DockPanel>
</DockPanel>
</UserControl>
@@ -0,0 +1,44 @@
using SteamTool.Core;
using SteamTool.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SteamTools.Views.Content
{
/// <summary>
/// AboutDonate.xaml 的交互逻辑
/// </summary>
public partial class AboutDonateList : UserControl
{
//private readonly HttpServices httpServices = SteamToolCore.Instance.Get<HttpServices>();
public AboutDonateList()
{
InitializeComponent();
}
//private void UserControl_Loaded(object sender, RoutedEventArgs e)
//{
// httpServices.Get(Const.REWARDMELIST_URL).ContinueWith(s =>
// {
// web.Dispatcher.Invoke(() =>
// {
// web.NavigateToString(s.Result);
// });
// });
//}
}
}
@@ -22,35 +22,121 @@
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<ScrollViewer Padding="8" VerticalScrollBarVisibility="Auto">
<DockPanel>
<TextBlock DockPanel.Dock="Top" Text="{Binding Resources.AboutUpdateHistory, Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
<DockPanel Margin="8">
<TextBlock DockPanel.Dock="Top" Text="{Binding Resources.AboutUpdateHistory, Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
Style="{DynamicResource SettingsHeaderTextStyleKey}" />
<Border Grid.Column="1">
<FlowDocumentScrollViewer Padding="0,-18,0,0"
<Border Grid.Column="1">
<FlowDocumentScrollViewer Padding="0,-18,0,0"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
<FlowDocument FontSize="12"
<FlowDocument FontSize="12"
Foreground="{DynamicResource ForegroundBrushKey}"
FontFamily="Meiryo UI"
TextAlignment="Left"
MaxPageWidth="900">
<Paragraph Language="zh-cn">
<Run Text="Steam++ v1.0.0" FontSize="16"/>
<Run Text="&#160;"/>
<Run Text="2020-12-14" FontSize="10" />
<LineBreak />
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="发布第一个版本" />
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="主要功能:社区反代,帐户切换,成就解锁,本地令牌。"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="次要功能:强制无边框窗口化以及CSGO VAC屏蔽修复。"></Run>
</Paragraph>
</FlowDocument>
</FlowDocumentScrollViewer>
</Border>
</DockPanel>
</ScrollViewer>
<Paragraph Language="zh-cn">
<Run Text="Steam++ v1.0.3" FontSize="16"/>
<Run Text="&#160;"/>
<Run Text="2020-12-26" FontSize="10" />
<LineBreak />
<Run Text="更新内容"></Run>
<LineBreak />
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="新增pixiv本地反代服务支持" />
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="新增在欢迎页steam昵称后显示steam的登陆区域" />
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="添加steam图片修复的本地反代支持" />
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="修复最小化恢复时UI边框错位的BUG"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="修复令牌编辑和导入时出现的非空报错"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="帐户切换功能的最近登陆时间从北京时间改为当前系统时区时间"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="修复一个因为DNS解析错误会导致程序内存溢出闪退的BUG"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="SDA令牌导入不再支持导入加密文件,如果要导入加密的maFile请先在SDA移除加密"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="修改初始化的方式和steam api的连接逻辑来避免steam游戏掉帧的BUG"></Run>
<LineBreak/>
<LineBreak />
<Run Text="已知的未修复问题"></Run>
<LineBreak />
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="部分用户无法加载游戏列表,无法复现,原因暂时不明。(也可能是加载太慢,过半小时才能加载出来)" />
</Paragraph>
<Paragraph Language="zh-cn">
<Run Text="Steam++ v1.0.2" FontSize="16"/>
<Run Text="&#160;"/>
<Run Text="2020-12-21" FontSize="10" />
<LineBreak />
<Run Text="更新内容"></Run>
<LineBreak />
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="更新了由Benares制作的图标" />
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="新增帐户切换删除功能" />
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="添加github图片资源文件代理服务与discord代理服务支持" />
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="因为有问题暂时去掉了GOG Galaxy代理选项"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="修复一个会导致程序启动没有反应的bug"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="修复托盘菜单steam昵称过长ui错位bug"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="新增steam启动参数设置"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="新增启动时程序最小化到托盘菜单设置"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="新增捐助列表的展示"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="新增工具自动更新功能"></Run>
<LineBreak />
<LineBreak />
<Run Text="已知的未修复问题"></Run>
<LineBreak />
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="(严重)经反馈,程序运行时可能会影响部分steam游戏掉帧,GPU占用率变低,这个BUG目前在作者的机器上无法复现所以暂时没有修复,如果你遇到这个问题可以手动关闭steam++解决。" />
<LineBreak />
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="程序在高DPI缩放分辨率下可能会UI布局错位,目前暂时拖动程序可恢复。" />
<LineBreak />
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="部分用户无法加载游戏列表,无法复现,原因暂时不明。" />
</Paragraph>
<Paragraph Language="zh-cn">
<Run Text="Steam++ v1.0.0" FontSize="16"/>
<Run Text="&#160;"/>
<Run Text="2020-12-14" FontSize="10" />
<LineBreak />
<Run Text="发布第一个版本" />
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="主要功能:社区反代,帐户切换,成就解锁,本地令牌。"></Run>
<LineBreak/>
<Run Text="&#160;&#160;&#160;&#160;"/>
<Run Text="次要功能:强制无边框窗口化以及CSGO VAC屏蔽修复。"></Run>
</Paragraph>
</FlowDocument>
</FlowDocumentScrollViewer>
</Border>
</DockPanel>
</UserControl>
@@ -23,6 +23,7 @@ namespace SteamTools.Views.Content
public AboutUpdateHistory()
{
InitializeComponent();
}
}
}
@@ -47,14 +47,14 @@
</StackPanel>
<TextBlock Style="{StaticResource DetailTextStyleKey}" Margin="20,6,0,0">
<Run Text="CSGO的Vac屏蔽问题是个老玄学问题了,就算是V社官方也不能确定原因。"></Run>
<Run Text="CSGO的Vac屏蔽问题是个老玄学问题了,就算是V社官方也只能给个排查范围。"></Run>
<metro2:HyperlinkEx Uri="https://support.steampowered.com/kb_article.php?ref=2117-ILZV-2837">
<Run Text="V社官方说明"></Run>
</metro2:HyperlinkEx>
<LineBreak/>
<Run Text="如果尝试后无效只能依次在尝试验证游戏完整性,重启电脑,实在不行(大概)就只有重装CSGO了。"/>
<LineBreak/>
<Run Text="*功能实现使用了狙击手Ricky的批处理指令。"></Run>
<Run Text="功能实现使用了狙击手Ricky的批处理指令。"></Run>
</TextBlock>
<metro:PromptTextBox
@@ -136,7 +136,7 @@
</Button>
</StackPanel>
<TextBlock Style="{StaticResource DetailTextStyleKey}" Margin="20,6,0,0">
<Run Text="*置于壁纸层的游戏可能会无法操控,这个问题可以解决但是目前发开精力不在这,目前这个功能就这样了。游戏结束后桌面会依然留下冻结的画面,这时可以点击刷新壁纸来恢复默认壁纸。"/>
<Run Text="*置于壁纸层的游戏可能会无法操控,这个问题可以解决但是目前开发精力不在这,目前这个功能就这样了。游戏结束后桌面会依然留下冻结的画面,这时可以点击刷新壁纸来恢复默认壁纸。"/>
<Run Text="并且将窗口放置于桌面壁纸层功能与Wallpaper Engine和其它动态桌面软件不兼容,使用时注意关掉Wallpaper Engine等软件。"/>
</TextBlock>
<Rectangle Style="{DynamicResource SeparatorStyleKey}" />
@@ -15,7 +15,6 @@
mc:Ignorable="d"
d:DesignHeight="400"
d:DesignWidth="600"
Padding="8"
Background="{DynamicResource ThemeBrushKey}"
d:DataContext="{d:DesignInstance viewModel:SettingsGeneralViewModel}">
@@ -51,6 +50,37 @@
<TextBlock Text="开机自启动"></TextBlock>
</CheckBox>
<Separator Opacity="0" Height="10"/>
<WrapPanel>
<CheckBox
HorizontalAlignment="Left"
IsChecked="{Binding Source={x:Static ms:GeneralSettings.IsStartupAppMinimized}, Path=Value, Mode=TwoWay}">
<TextBlock Text="启动时最小化到托盘菜单"></TextBlock>
</CheckBox>
<TextBlock Style="{StaticResource DetailTextStyleKey}" Margin="10,0,0,0">
<Run Text="*此设置不影响开机自启动时最小化"></Run>
</TextBlock>
</WrapPanel>
<Separator Opacity="0" Height="10"/>
<CheckBox
HorizontalAlignment="Left"
IsChecked="{Binding Source={x:Static ms:GeneralSettings.IsAutoCheckUpdate}, Path=Value, Mode=TwoWay}">
<TextBlock Text="启动时自动检查更新"></TextBlock>
</CheckBox>
<Separator Opacity="0" Height="10"/>
<WrapPanel>
<metro2:CallMethodButton Content="检查更新"
Width="80"
Height="30"
HorizontalAlignment="Left"
MethodName="CheckUpdate_Click"
MethodTarget="{Binding}"/>
<TextBlock Style="{StaticResource DetailTextStyleKey}" Margin="10,0,0,0">
<Run Text="手动检查更新"></Run>
</TextBlock>
</WrapPanel>
<!--<Separator Opacity="0" Height="10"/>-->
<Border Height="1"
@@ -58,6 +88,23 @@
Margin="-20,8" />
</StackPanel>
<StackPanel Margin="20,0,0,0">
<TextBlock Margin="-20,0,0,10" Text="Steam启动参数" Style="{DynamicResource SettingsHeaderTextStyleKey}" />
<metro:PromptTextBox Prompt="自定义Steam启动参数"
Text="{Binding Source={x:Static ms:GeneralSettings.SteamStratParameter}, Path=Value, Mode=TwoWay}"
Width="400"
HorizontalAlignment="Left"
TextWrapping="Wrap"
AcceptsReturn="True"
VerticalScrollBarVisibility="Visible"
MaxLines="3"></metro:PromptTextBox>
<TextBlock Style="{StaticResource DetailTextStyleKey}" Margin="0,6,0,0">
<Run Text="在帐户切换启动Steam时会带上这些参数启动Steam。"></Run>
</TextBlock>
<Border Height="1"
Background="{DynamicResource BorderBrushKey}"
Margin="-20,8" />
</StackPanel>
<StackPanel Margin="20,0,0,0">
<TextBlock Margin="-20,0,0,10" Text="{Binding Resources.Settings_GameList, Source={x:Static services:ResourceService.Current}, Mode=OneWay}" Style="{DynamicResource SettingsHeaderTextStyleKey}" />
@@ -68,7 +115,7 @@
<TextBlock Text="启用游戏列表本地缓存"></TextBlock>
</CheckBox>
<TextBlock Style="{StaticResource DetailTextStyleKey}" Margin="0,6,0,0">
<Run Text="取消本地缓存后每次启动都将从Steam服务器加载最新游戏列表数据,加载速度会变慢。"></Run>
<Run Text="取消本地缓存后每次启动都将从Steam服务器加载最新游戏列表数据,但每次启动时加载速度会变慢。"></Run>
</TextBlock>
<Separator Opacity="0" Height="10"/>
@@ -81,9 +128,9 @@
MethodTarget="{Binding}"/>
<TextBlock Style="{StaticResource DetailTextStyleKey}" Margin="0,6,0,0">
<Run Text="因为从Steam获取游戏列表数据时会很慢,为了避免加载缓慢所以在本地会缓存一份游戏列表的数据。"></Run>
<Run Text="因为从Steam获取游戏列表数据时很慢,为了避免加载缓慢所以在本地会缓存一份游戏列表的数据。"></Run>
<LineBreak/>
<Run Text="但是数据因为数据是默认10天更新一次,因此如果您发现在游戏列表搜索不到新发布的游戏时,可以考虑手动刷新游戏列表缓存。"/>
<Run Text="游戏列表缓存默认10天更新一次,因此如果您发现在游戏列表搜索不到新发布的游戏时,可以考虑手动刷新游戏列表缓存。"/>
</TextBlock>
<Border Height="1"
+6 -3
View File
@@ -9,7 +9,7 @@
xmlns:vm="clr-namespace:SteamTools.ViewModels"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="780"
d:DataContext="{d:DesignInstance vm:StatusBarViewModel}">
d:DataContext="{d:DesignInstance vm:StatusBarViewModel}">
<Grid Grid.Row="2" Background="{DynamicResource AccentBrushKey}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
@@ -18,12 +18,15 @@
<ColumnDefinition Width="23" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Source={x:Static services:StatusService.Current}, Path=Message}"
FontSize="13"
Style="{DynamicResource DefaultTextStyleKey}"
Foreground="{DynamicResource AccentForegroundBrushKey}"
TextWrapping="NoWrap"
Margin="8,0" />
Margin="8,0" >
<Run
Text="{Binding Source={x:Static services:StatusService.Current}, Path=Message}"/>
</TextBlock>
<ContentControl Grid.Column="1"
Content="{Binding}">
<ContentControl.Resources>
+11 -7
View File
@@ -11,8 +11,12 @@
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:livet="http://schemas.livet-mvvm.net/2011/wpf"
mc:Ignorable="d"
Height="345" Width="180"
Height="350" Width="180"
FontSize="14"
UseLayoutRounding="True"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
SnapsToDevicePixels="True"
Foreground="{DynamicResource ForegroundBrushKey}"
d:DataContext="{d:DesignInstance vm:TaskBarViewModel}">
<Border>
@@ -28,11 +32,11 @@
BorderThickness=".99">
<Grid Margin="8,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="70"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<WrapPanel Grid.Row="0" Margin="0,8,0,0" Visibility="{Binding ElementName=user,Path=IsVisible,Converter={StaticResource ReverseBooleanToVisibilityConverter}}">
<DockPanel Grid.Row="0" Margin="0,8,0,0" Visibility="{Binding ElementName=user,Path=IsVisible,Converter={StaticResource ReverseBooleanToVisibilityConverter}}">
<Image Source="pack://application:,,,/Resources/Asstes/app.ico" Width="64" Height="64" Cursor="Hand">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
@@ -41,15 +45,15 @@
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
<StackPanel VerticalAlignment="Center" >
<StackPanel VerticalAlignment="Center">
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.WinTitle,Mode=OneWay}"
Foreground="{DynamicResource HighlightForegroundBrushKey}" Style="{StaticResource HeaderTextStyleKey}" FontSize="16"/>
<TextBlock Text="{Binding Source={x:Static models:ProductInfo.VersionString}, StringFormat=版本 {0}, Mode=OneWay}"
Foreground="{DynamicResource HighlightForegroundBrushKey}" Style="{StaticResource DetailTextStyleKey}"/>
</StackPanel>
</WrapPanel>
<WrapPanel x:Name="user" Grid.Row="0" Margin="0,8,0,0" Visibility="{Binding CurrentSteamUser,Source={x:Static services:SteamConnectService.Current},Mode=OneWay,Converter={StaticResource NullToVisibilityConverter}}">
</DockPanel>
<DockPanel x:Name="user" Grid.Row="0" Margin="0,8,0,0" Visibility="{Binding CurrentSteamUser,Source={x:Static services:SteamConnectService.Current},Mode=OneWay,Converter={StaticResource NullToVisibilityConverter}}">
<Image Source="{Binding CurrentSteamUser.AvatarMedium,Source={x:Static services:SteamConnectService.Current},Mode=OneWay}" Width="64" Height="64" Cursor="Hand">
<Image.Clip>
<!--设置图像如何显示-->
@@ -74,7 +78,7 @@
<Run Text="{Binding Source={x:Static models:ProductInfo.VersionString}, StringFormat=版本 {0}, Mode=OneWay}"></Run>
</TextBlock>
</StackPanel>
</WrapPanel>
</DockPanel>
<StackPanel Grid.Row="1">
<Rectangle Height=".99"
Fill="{DynamicResource InactiveForegroundBrushKey}"
+4 -1
View File
@@ -20,9 +20,9 @@
Foreground="{DynamicResource ActiveForegroundBrushKey}"
FontFamily="{StaticResource DefaultFontFamilyKey}"
UseLayoutRounding="True"
SnapsToDevicePixels="True"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
SnapsToDevicePixels="True"
WindowStartupLocation="CenterScreen"
IsRestoringWindowPlacement="True"
d:DataContext="{d:DesignInstance vm:MainWindowViewModel}"
@@ -175,6 +175,9 @@
<DataTemplate DataType="{x:Type vm:SteamAccountPageViewModel}">
<pages:SwitchSteamAccountPage />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SteamIdlePageViewModel}">
<pages:SteamIdleCardPage />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:CommunityProxyPageViewModel}">
<pages:CommunityProxyPage />
</DataTemplate>

Some files were not shown because too many files have changed in this diff Show More