Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf17ca8dd6 | ||
|
|
0b88de7195 | ||
|
|
3342e35440 | ||
|
|
56baba4a53 | ||
|
|
8b1a946fe2 | ||
|
|
9e08c0b7c4 | ||
|
|
3a38333dfc | ||
|
|
16d1bba515 | ||
|
|
00cf9da911 | ||
|
|
088256faf9 | ||
|
|
ca244edc51 | ||
|
|
c91608da09 | ||
|
|
2945e9fa3e | ||
|
|
1f0a40cd3b | ||
|
|
b1fbe64ab2 | ||
|
|
9a13665e68 | ||
|
|
5c0f71f4a7 | ||
|
|
3e045e5db0 | ||
|
|
c4f99906ab | ||
|
|
94e50f663b | ||
|
|
49e08101c6 |
@@ -26,6 +26,7 @@ bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ib/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
[
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 18 KiB |
@@ -1,6 +1,5 @@
|
||||
# Steam++工具箱 v1.0
|
||||
# Steam++ SteamTools
|
||||
|
||||
------
|
||||
|
||||
「Steam++」是一个包含多种Steam工具功能的工具箱。
|
||||
|
||||
@@ -8,14 +7,11 @@
|
||||
|
||||
------
|
||||
|
||||
## 主要功能
|
||||
## 核心功能
|
||||
|
||||
### 1. 反代Steam的社区网页使其能正常访问
|
||||
|
||||
功能类似羽翼城大佬的Steam302,相比之下有:
|
||||
|
||||
- [X] 更快的启动速度
|
||||
- [X] 支持脚本注入
|
||||
功能类似羽翼城大佬的Steam302,使用[Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)开源项目进行本地反代,相比302工具具有更快的启动速度,以及支持简单的脚本注入。
|
||||
|
||||
---
|
||||
### 2. 快速切换当前PC已经记住登陆的Steam账号
|
||||
@@ -24,12 +20,12 @@
|
||||
|
||||
---
|
||||
### 3. Steam游戏的成就统计管理功能
|
||||
功能类似[SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager),实现也参考了SAM,并且略作修改了,游戏列表的读取,解锁成就的逻辑。
|
||||
功能参考[SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)进行二次开发,修改了游戏列表的加载和操作易用性。
|
||||
|
||||
---
|
||||
|
||||
### 4. Steam本地两步身份验证器
|
||||
可以使您不用启动移动版Steam App也能查看您的令牌,功能类似的软件有[WinAuth](https://github.com/winauth/winauth)、[SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)。
|
||||
功能参考[WinAuth](https://github.com/winauth/winauth)开发,可以使您不用启动移动版Steam App也能查看您的令牌,功能类似的软件有[WinAuth](https://github.com/winauth/winauth)、[SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)。
|
||||
|
||||
---
|
||||
|
||||
@@ -38,3 +34,52 @@
|
||||
这一块是随缘做一些我经常用或者闲着没事捣鼓的功能。
|
||||
|
||||
---
|
||||
|
||||
## 预计后续添加的功能
|
||||
|
||||
### Steam自动挂卡
|
||||
尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内登录Steam即可直接获取徽章卡片信息并开始挂卡。
|
||||
|
||||
### Steam皮肤设计器
|
||||
挖坑画大饼,可视化编辑Steam皮肤,而且如果软件能上架Steam的话打算支持创意工坊分享设计的Steam皮肤,短期内肯定做不完。
|
||||
|
||||
### 插件形式加载运行ASF
|
||||
以插件形式支持ASF在工具内运行并增强ASF在Windows Desktop环境下的使用。
|
||||
|
||||
### Steam自定义封面管理
|
||||
增强Steam自定义封面的管理以及从[SteamGridDB](https://www.steamgriddb.com/)快速匹配下载应用封面。
|
||||
|
||||
### 更多其它游戏平台功能
|
||||
|
||||
|
||||
### 更多非作弊游戏功能
|
||||
|
||||
---
|
||||
|
||||
## 运行环境
|
||||
> 程序使用C# WPF在 .NET Framework4.7.2环境下开发,如果无法运行请下载安装[.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)。
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
> [GPL-3.0 License](LICENSE.txt)
|
||||
> 根据GPLv3许可发布的开源/免费软件。
|
||||
|
||||
---
|
||||
|
||||
## 感谢以下开源项目
|
||||
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
||||
* [MetroRadiance](https://github.com/Grabacr07/MetroRadiance)
|
||||
* [MetroTrilithon](https://github.com/Grabacr07/MetroTrilithon)
|
||||
* [Livet](https://github.com/runceel/Livet)
|
||||
* [StatefulModel](https://github.com/Grabacr07/MetroTrilithonhttps://github.com/ugaya40/StatefulModel)
|
||||
* [Hardcodet.NotifyIcon](https://github.com/HavenDV/Hardcodet.NotifyIcon.Wpf.NetCore)
|
||||
* [System.Reactive](https://github.com/dotnet/reactive)
|
||||
* [Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)
|
||||
* [Ninject](https://github.com/ninject/Ninject)
|
||||
* [log4net](https://github.com/apache/logging-log4net)
|
||||
* [SteamDB-API](https://github.com/SteamDB-API/api)
|
||||
* [SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)
|
||||
* [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm)
|
||||
* [WinAuth](https://github.com/winauth/winauth)
|
||||
* [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
|
||||
@@ -1,6 +1,4 @@
|
||||
# Steam++工具箱 v1.0
|
||||
|
||||
------
|
||||
# Steam++工具箱
|
||||
|
||||
「Steam++」是一个包含多种Steam工具功能的工具箱。
|
||||
|
||||
@@ -8,14 +6,11 @@
|
||||
|
||||
------
|
||||
|
||||
## 主要功能
|
||||
## 核心功能
|
||||
|
||||
### 1. 反代Steam的社区网页使其能正常访问
|
||||
|
||||
功能类似羽翼城大佬的Steam302,相比之下有:
|
||||
|
||||
- [X] 更快的启动速度
|
||||
- [X] 支持脚本注入
|
||||
功能类似羽翼城大佬的Steam302,使用[Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)开源项目进行本地反代,相比302工具具有更快的启动速度,以及支持简单的脚本注入。
|
||||
|
||||
---
|
||||
### 2. 快速切换当前PC已经记住登陆的Steam账号
|
||||
@@ -24,12 +19,12 @@
|
||||
|
||||
---
|
||||
### 3. Steam游戏的成就统计管理功能
|
||||
功能类似[SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager),实现也参考了SAM,并且略作修改了,游戏列表的读取,解锁成就的逻辑。
|
||||
功能参考[SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)进行二次开发,修改了游戏列表的加载和操作易用性。
|
||||
|
||||
---
|
||||
|
||||
### 4. Steam本地两步身份验证器
|
||||
可以使您不用启动移动版Steam App也能查看您的令牌,功能类似的软件有[WinAuth](https://github.com/winauth/winauth)、[SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)。
|
||||
功能参考[WinAuth](https://github.com/winauth/winauth)开发,可以使您不用启动移动版Steam App也能查看您的令牌,功能类似的软件有[WinAuth](https://github.com/winauth/winauth)、[SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)。
|
||||
|
||||
---
|
||||
|
||||
@@ -38,3 +33,57 @@
|
||||
这一块是随缘做一些我经常用或者闲着没事捣鼓的功能。
|
||||
|
||||
---
|
||||
|
||||
## 预计后续添加的功能
|
||||
|
||||
### Steam自动挂卡
|
||||
尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内无需登录Steam帐户即可直接获取徽章卡片信息并开始挂卡。
|
||||
|
||||
### Steam皮肤设计器
|
||||
挖坑画大饼,可视化编辑Steam皮肤,而且如果软件能上架Steam的话打算支持创意工坊分享设计的Steam皮肤,短期内肯定做不完。
|
||||
|
||||
### 插件形式加载运行ASF
|
||||
以插件形式支持ASF在工具内运行并增强ASF在Windows Desktop环境下的使用。
|
||||
|
||||
### Steam自定义封面管理
|
||||
增强Steam自定义封面的管理以及从[SteamGridDB](https://www.steamgriddb.com/)快速匹配下载应用封面。
|
||||
|
||||
### 更多其它游戏平台功能
|
||||
|
||||
|
||||
### 更多非作弊游戏功能
|
||||
|
||||
---
|
||||
|
||||
## 运行环境
|
||||
> 程序使用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)
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
> [GPL-3.0 License](LICENSE.txt)
|
||||
> 根据GPLv3许可发布的开源/免费软件。
|
||||
|
||||
---
|
||||
|
||||
## 感谢以下开源项目
|
||||
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
||||
* [MetroRadiance](https://github.com/Grabacr07/MetroRadiance)
|
||||
* [MetroTrilithon](https://github.com/Grabacr07/MetroTrilithon)
|
||||
* [Livet](https://github.com/runceel/Livet)
|
||||
* [StatefulModel](https://github.com/Grabacr07/MetroTrilithonhttps://github.com/ugaya40/StatefulModel)
|
||||
* [Hardcodet.NotifyIcon](https://github.com/HavenDV/Hardcodet.NotifyIcon.Wpf.NetCore)
|
||||
* [System.Reactive](https://github.com/dotnet/reactive)
|
||||
* [Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)
|
||||
* [Ninject](https://github.com/ninject/Ninject)
|
||||
* [log4net](https://github.com/apache/logging-log4net)
|
||||
* [SteamDB-API](https://github.com/SteamDB-API/api)
|
||||
* [SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)
|
||||
* [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm)
|
||||
* [WinAuth](https://github.com/winauth/winauth)
|
||||
* [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
|
||||
* [Gameloop.Vdf](https://github.com/shravan2x/Gameloop.Vdf)
|
||||
* [Costura.Fody](https://github.com/Fody/Costura)
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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) { }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ 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.GetFolderPath(Environment.SpecialFolder.System)}\\drivers\\etc\\hosts";
|
||||
|
||||
|
||||
public OperationResult<List<string>> ReadHostsAllLines()
|
||||
@@ -74,7 +74,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);
|
||||
@@ -95,7 +95,7 @@ namespace SteamTool.Core
|
||||
{
|
||||
var result = new OperationResult(OperationResultType.Error, Resources.Hosts_WirteError);
|
||||
|
||||
if (hosts.Count == 0)
|
||||
if (hosts.Count == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -128,7 +128,7 @@ namespace SteamTool.Core
|
||||
|
||||
foreach (var (ip, domain) in hosts)
|
||||
{
|
||||
dataLines.Add($"{ip} {domain} {Const.HostTag}");
|
||||
dataLines.Add($"{ip} {domain} {Const.HOST_TAG}");
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -205,7 +205,7 @@ namespace SteamTool.Core
|
||||
{
|
||||
if (!temp[0].StartsWith("#"))
|
||||
{
|
||||
return !temp.Contains(Const.HostTag);
|
||||
return !temp.Contains(Const.HOST_TAG);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -228,7 +228,7 @@ namespace SteamTool.Core
|
||||
return result;
|
||||
}
|
||||
|
||||
public void StartNotepadEditHosts()
|
||||
public void StartNotepadEditHosts()
|
||||
{
|
||||
System.Diagnostics.Process.Start("notepad.exe", HostsPath);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -134,7 +136,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 +155,6 @@ namespace SteamTool.Core
|
||||
return apps.AppList.Apps;
|
||||
}
|
||||
|
||||
|
||||
public bool UpdateAppListJson(List<SteamApp> apps, string filepath)
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(apps);
|
||||
@@ -184,28 +184,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 +203,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,14 @@ 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_RELEASEAPI_URL = "https://api.github.com/repos/rmbadmin/SteamTools/releases/latest";
|
||||
|
||||
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";
|
||||
@@ -27,7 +33,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}";
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
@@ -38,6 +39,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,7 +63,6 @@ namespace SteamTool.Proxy
|
||||
}
|
||||
*/
|
||||
#endregion
|
||||
#if DEBUG
|
||||
Debug.WriteLine("OnRequest" + e.HttpClient.Request.RequestUri.AbsoluteUri);
|
||||
#endif
|
||||
foreach (var item in ProxyDomains)
|
||||
@@ -107,6 +108,7 @@ namespace SteamTool.Proxy
|
||||
}
|
||||
}
|
||||
}
|
||||
//GC.Collect();
|
||||
}
|
||||
public async Task OnResponse(object sender, SessionEventArgs e)
|
||||
{
|
||||
@@ -164,7 +166,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)
|
||||
{
|
||||
@@ -237,25 +239,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 +300,10 @@ namespace SteamTool.Proxy
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (PortInUse(443))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (PortInUse(443))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (IsProxyGOG) { WirtePemCertificateToGoGSteamPlugins(); }
|
||||
|
||||
@@ -335,24 +370,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 +399,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,7 @@ namespace SteamTool.Proxy
|
||||
GoogleCode = 8,
|
||||
[Description("GOG.COM")]
|
||||
GOG = 8,
|
||||
[Description("Github图片修复")]
|
||||
GithubContent = 9,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
@@ -83,16 +83,16 @@ 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();
|
||||
//托盘加载
|
||||
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)
|
||||
(WindowService.Current.MainWindow as MainWindowViewModel).Initialize();
|
||||
else
|
||||
this.MainWindow.Show();
|
||||
@@ -102,7 +102,7 @@ namespace SteamTools
|
||||
{
|
||||
// 检测到多次启动时将主窗口置于最前面
|
||||
this.Dispatcher.Invoke(() => WindowService.Current.MainWindow.Activate());
|
||||
//this.ProcessCommandLineParameter(args.CommandLineArgs);
|
||||
this.ProcessCommandLineParameter(args.CommandLineArgs);
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -155,10 +155,10 @@ namespace SteamTools
|
||||
{
|
||||
Debug.WriteLine("多重启动通知: " + args.ToString(" "));
|
||||
// 当使用命令行参数多次启动时,您可以执行某些操作
|
||||
//if (args.Length == 0)
|
||||
//{
|
||||
// this.Shutdown();
|
||||
//}
|
||||
if (args.Length == 0)
|
||||
{
|
||||
this.Shutdown();
|
||||
}
|
||||
if (args.ContainsArg("-log"))
|
||||
{
|
||||
Logger.EnableTextLog = true;
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace SteamTools.Models
|
||||
private static readonly Lazy<string> versionLazy = new Lazy<string>(() => $"{Version.ToString(3)}{(IsBetaRelease ? " β" : "")}{(Version.Revision == 0 ? "" : " rev." + Version.Revision)}");
|
||||
private static readonly Lazy<IReadOnlyCollection<Library>> librariesLazy = new Lazy<IReadOnlyCollection<Library>>(() => new List<Library>
|
||||
{
|
||||
new Library("Newtonsoft.Json", new Uri("https://github.com/JamesNK/Newtonsoft.Json")),
|
||||
new Library("MetroRadiance", new Uri("https://github.com/Grabacr07/MetroRadiance")),
|
||||
new Library("MetroTrilithon", new Uri("https://github.com/Grabacr07/MetroTrilithon")),
|
||||
new Library("Livet", new Uri("https://github.com/runceel/Livet")),
|
||||
@@ -25,11 +26,15 @@ namespace SteamTools.Models
|
||||
new Library("Hardcodet.NotifyIcon", new Uri("https://github.com/HavenDV/Hardcodet.NotifyIcon.Wpf.NetCore")),
|
||||
new Library("System.Reactive", new Uri("https://github.com/dotnet/reactive")),
|
||||
new Library("Titanium-Web-Proxy", new Uri("https://github.com/justcoding121/Titanium-Web-Proxy")),
|
||||
new Library("Ninject", new Uri("http://www.ninject.org/")),
|
||||
new Library("log4net", new Uri("https://logging.apache.org/log4net/")),
|
||||
new Library("Ninject", new Uri("https://github.com/ninject/Ninject")),
|
||||
new Library("log4net", new Uri("https://github.com/apache/logging-log4net")),
|
||||
new Library("SteamDB-API", new Uri("https://github.com/SteamDB-API/api")),
|
||||
new Library("SteamAchievementManager", new Uri("https://github.com/gibbed/SteamAchievementManager")),
|
||||
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")),
|
||||
});
|
||||
|
||||
|
||||
@@ -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 = "")
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,15 @@ namespace SteamTools.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 捐助纪录 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string About_DonateList {
|
||||
get {
|
||||
return ResourceManager.GetString("About_DonateList", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 帮助 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -456,6 +465,15 @@ namespace SteamTools.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Github图片资源修复 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GithubContent {
|
||||
get {
|
||||
return ResourceManager.GetString("GithubContent", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 GOG Galaxy 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -655,7 +673,7 @@ namespace SteamTools.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 复位成就和/统计 的本地化字符串。
|
||||
/// 查找类似 复位成就和统计 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string OnRest {
|
||||
get {
|
||||
@@ -825,6 +843,15 @@ namespace SteamTools.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 帐户切换设置 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Settings_AccountChange {
|
||||
get {
|
||||
return ResourceManager.GetString("Settings_AccountChange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 令牌设置 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -126,6 +126,9 @@
|
||||
<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>
|
||||
@@ -249,6 +252,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 +322,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 +378,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>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"SteamTools": {
|
||||
"commandName": "Project"
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "-log"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 35 KiB |
@@ -60,15 +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()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Authenticators = new BindingList<WinAuthAuthenticator>();
|
||||
try
|
||||
{
|
||||
var auths = AuthService.LoadJsonAuthenticator(AuthSettings.Authenticators.Value.DecompressString());
|
||||
Authenticators = new BindingList<WinAuthAuthenticator>(auths);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WindowService.Current.MainWindow.Dialog($"令牌同步服务器失败,错误信息:{ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
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
|
||||
|
||||
public async void CheckUpdate()
|
||||
{
|
||||
try
|
||||
{
|
||||
StatusService.Current.Notify("正在从Github检查更新...");
|
||||
var result = await httpServices.Get(Const.GITHUB_RELEASEAPI_URL);
|
||||
var model = JsonConvert.DeserializeObject<GithubReleaseModel>(result);
|
||||
if (!(ProductInfo.Version < model.version))
|
||||
{
|
||||
StatusService.Current.Notify("当前已是最新版本");
|
||||
return;
|
||||
}
|
||||
if (WindowService.Current.MainWindow.Dialog($"检测到新版本更新内容:{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.ToString("P")}");
|
||||
size = responseStream.Read(bs, 0, bs.Length);
|
||||
}
|
||||
fileStream.Flush();
|
||||
fileStream.Close();
|
||||
StatusService.Current.Set(Resources.Ready);
|
||||
StatusService.Current.Notify($"{ProductInfo.Title} {model.version}版本已经下载到程序根目录下,暂时请手动替换更新");
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("更新出错:", ex);
|
||||
WindowService.Current.MainWindow.Dialog($"更新出错:{ex.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,6 +36,11 @@ 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>
|
||||
@@ -73,43 +81,43 @@ namespace SteamTools.Services
|
||||
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=4,
|
||||
Name=Resources.Discord,
|
||||
Domains = new List<string>{ "discordapp.com","discordapp.net" },
|
||||
//ToDomain = "discord.com",
|
||||
ProxyIPAddres="162.159.130.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",
|
||||
},
|
||||
DomainTag = DomainTag.Discord,
|
||||
IsEnable= false,
|
||||
},
|
||||
new ProxyDomainModel{
|
||||
Index=5,
|
||||
Name=Resources.Twitch,
|
||||
Domains = new List<string>{ "twitch.tv" },
|
||||
Domains = new List<string>{ "twitch.tv" ,"usher.ttvnw.net"},
|
||||
ToDomain="twitch.map.fastly.net",
|
||||
Hosts = new List<string>{
|
||||
"twitch.tv",
|
||||
@@ -150,7 +158,7 @@ namespace SteamTools.Services
|
||||
"irc-ws.chat.twitch.tv",
|
||||
"irc-ws-r.chat.twitch.tv",
|
||||
//"platform.twitter.com",
|
||||
//"usher.ttvnw.net",
|
||||
"usher.ttvnw.net",
|
||||
},
|
||||
DomainTag = DomainTag.Twitch,
|
||||
IsEnable= false,
|
||||
@@ -172,39 +180,39 @@ namespace SteamTools.Services
|
||||
// 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=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,
|
||||
@@ -214,6 +222,26 @@ namespace SteamTools.Services
|
||||
DomainTag = DomainTag.GoogleCode,
|
||||
IsEnable= false,
|
||||
},
|
||||
new ProxyDomainModel{
|
||||
Index=9,
|
||||
Name=Resources.GithubContent,
|
||||
Domains = new List<string>{"githubusercontent.com","raw.github.com" },
|
||||
//ToDomain = "github.map.fastly.net",
|
||||
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,
|
||||
},
|
||||
});
|
||||
public Lazy<IReadOnlyCollection<ProxyDomainModel>> ProxyDomains
|
||||
{
|
||||
|
||||
@@ -96,22 +96,24 @@ namespace SteamTools.Services
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
Thread.CurrentThread.IsBackground = true;
|
||||
while (true)
|
||||
{
|
||||
if (Process.GetProcessesByName("steam").Length > 0)
|
||||
{
|
||||
if (!IsConnectToSteam)
|
||||
{
|
||||
IsConnectToSteam = ApiService.Initialize();
|
||||
if (IsConnectToSteam)
|
||||
if (ApiService.Initialize())
|
||||
{
|
||||
var id = ApiService.GetSteamId64();
|
||||
if (id == 76561197960265728)
|
||||
{
|
||||
//该64位id的steamID3等于0,是steam未获取到当前登录用户的默认返回值,所以直接重新获取
|
||||
IsConnectToSteam = false;
|
||||
//该64位id的steamID3等于0,是steam未获取到当前登录用户的默认返回值,所以直接重新获取,
|
||||
//希望这位用户不会用steam++,嗯...
|
||||
ApiService.SteamClient.Dispose();
|
||||
continue;
|
||||
}
|
||||
IsConnectToSteam = true;
|
||||
CurrentSteamUser = await steamDbApiService.GetUserInfo(id);
|
||||
var mainViewModel = (WindowService.Current.MainWindow as MainWindowViewModel);
|
||||
mainViewModel.SteamAppPage.Initialize();
|
||||
@@ -126,9 +128,9 @@ namespace SteamTools.Services
|
||||
IsConnectToSteam = false;
|
||||
//StatusService.Current.Notify(Resources.Steam_Not_Runing);
|
||||
}
|
||||
await Task.Delay(1000);
|
||||
await Task.Delay(1500);
|
||||
}
|
||||
});
|
||||
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted);
|
||||
}
|
||||
|
||||
public void Initialize(int appid)
|
||||
|
||||
@@ -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,7 @@ namespace SteamTools.Services
|
||||
var window = new MessageDialog { DataContext = dialog };
|
||||
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
window.ShowDialog();
|
||||
return dialog;
|
||||
return dialog.DialogResult;
|
||||
}
|
||||
|
||||
#region disposable members
|
||||
|
||||
@@ -32,13 +32,15 @@
|
||||
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
|
||||
<Description>Steam++</Description>
|
||||
<Description>「Steam++」是一个包含多种Steam工具功能的工具箱。</Description>
|
||||
|
||||
<Platforms>AnyCPU;x86</Platforms>
|
||||
|
||||
<Product>SteamTools</Product>
|
||||
|
||||
<PackageId />
|
||||
|
||||
<Version>1.0.2</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net472|AnyCPU'">
|
||||
@@ -109,7 +111,7 @@
|
||||
<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>
|
||||
@@ -137,7 +139,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>
|
||||
@@ -237,6 +239,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>
|
||||
@@ -310,8 +316,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,6 +335,9 @@
|
||||
<Reference Include="MetroTrilithon.Desktop">
|
||||
<HintPath>..\Lib\MetroTrilithon.Desktop.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimpleSyndicate.UriTemplate">
|
||||
<HintPath>..\Lib\SimpleSyndicate.UriTemplate.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -346,8 +354,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>
|
||||
@@ -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 List<DonateRecord> _DonateRecordList;
|
||||
public List<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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace SteamTools.ViewModels
|
||||
{
|
||||
if (IsRefreshGameListCache)
|
||||
{
|
||||
StatusService.Current.Notify("正在下在Steam游戏数据中...");
|
||||
StatusService.Current.Notify("正在下载Steam游戏数据中...");
|
||||
return;
|
||||
}
|
||||
StatusService.Current.Notify("刷新Steam游戏数据");
|
||||
@@ -47,7 +47,7 @@ namespace SteamTools.ViewModels
|
||||
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 +60,10 @@ namespace SteamTools.ViewModels
|
||||
StatusService.Current.Notify("未检测到Steam运行");
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckUpdate_Click()
|
||||
{
|
||||
AutoUpdateService.Current.CheckUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,8 +72,8 @@ namespace SteamTools.ViewModels
|
||||
ChangeWindowVisible();
|
||||
if (value)
|
||||
{
|
||||
App.Current.MainWindow.Topmost = true;
|
||||
App.Current.MainWindow.WindowState = WindowState.Normal;
|
||||
App.Current.MainWindow.Topmost = true;
|
||||
User32Window.FlashWindow(new WindowInteropHelper(App.Current.MainWindow).Handle);
|
||||
App.Current.MainWindow.Topmost = false;
|
||||
}
|
||||
@@ -131,13 +133,13 @@ namespace SteamTools.ViewModels
|
||||
continue;
|
||||
item.Initialize();
|
||||
}
|
||||
}).ContinueWith(s => s.Dispose());
|
||||
//foreach (var item in this.TabItems)
|
||||
//{
|
||||
// if (item == SteamAppPage)
|
||||
// continue;
|
||||
// item.Initialize();
|
||||
//}
|
||||
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted)
|
||||
.ContinueWith(s => s.Dispose());
|
||||
AuthService.Current.Initialize();
|
||||
if (GeneralSettings.IsAutoCheckUpdate)
|
||||
{
|
||||
AutoUpdateService.Current.CheckUpdate();
|
||||
}
|
||||
StatusService.Current.Set(Resources.Ready);
|
||||
this.IsInitialized = true;
|
||||
}
|
||||
@@ -152,14 +154,15 @@ namespace SteamTools.ViewModels
|
||||
if (IsVisible)
|
||||
{
|
||||
App.Current.MainWindow.Show();
|
||||
//App.Current.MainWindow.Focus();
|
||||
App.Current.MainWindow.WindowState = WindowState.Normal;
|
||||
App.Current.MainWindow.Activate();
|
||||
User32Window.FlashWindow(new WindowInteropHelper(App.Current.MainWindow).Handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
App.Current.MainWindow.WindowState = WindowState.Minimized;
|
||||
//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();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using MetroRadiance.Platform;
|
||||
using SteamTool.Core.Common;
|
||||
using SteamTool.Steam.Service.Local;
|
||||
using SteamTools.Services;
|
||||
using System;
|
||||
@@ -44,6 +45,8 @@ namespace SteamTools.ViewModels
|
||||
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,7 +55,7 @@ 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()
|
||||
|
||||
@@ -96,15 +96,8 @@ namespace SteamTools.ViewModels
|
||||
|
||||
internal override void Initialize()
|
||||
{
|
||||
AuthService.Current.Subscribe(nameof(AuthService.Current.Authenticators), this.Update).AddTo(this);
|
||||
//Task.Run(() =>
|
||||
//{
|
||||
//});
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
Authenticators = AuthService.Current.Authenticators;
|
||||
AuthService.Current.Subscribe(nameof(AuthService.Current.Authenticators),
|
||||
()=> { Authenticators = AuthService.Current.Authenticators; }).AddTo(this);
|
||||
}
|
||||
|
||||
public void AddAuth_Click()
|
||||
@@ -114,9 +107,10 @@ namespace SteamTools.ViewModels
|
||||
|
||||
public void EditAuth_Click()
|
||||
{
|
||||
if (Authenticators.Count < 1)
|
||||
if (Authenticators?.Count < 1)
|
||||
{
|
||||
StatusService.Current.Notify("没有可编辑的令牌");
|
||||
return;
|
||||
}
|
||||
this.IsEdit = !IsEdit;
|
||||
if (!IsEdit)
|
||||
|
||||
@@ -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
|
||||
@@ -50,7 +52,11 @@ namespace SteamTools.ViewModels
|
||||
StatusService.Current.Notify("加载本地Steam用户数据");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace SteamTools.ViewModels
|
||||
|
||||
SteamConnectService.Current.Subscribe(nameof(SteamConnectService.Current.SteamApps), this.Update).AddTo(this);
|
||||
|
||||
}).ContinueWith(s =>
|
||||
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s =>
|
||||
{
|
||||
StatusService.Current.Notify("加载Steam游戏数据完成");
|
||||
s.Dispose();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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="100"></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);
|
||||
// });
|
||||
// });
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="400"
|
||||
d:DesignWidth="600"
|
||||
Padding="8"
|
||||
Background="{DynamicResource ThemeBrushKey}">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
@@ -23,33 +22,83 @@
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top" Text="{Binding Resources.AboutUpdateHistory, Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
|
||||
<ScrollViewer Padding="8" VerticalScrollBarVisibility="Auto">
|
||||
<DockPanel>
|
||||
<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=" "/>
|
||||
<Run Text="2020-12-14" FontSize="10" />
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="发布第一个版本" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="主要功能:社区反代,帐户切换,成就解锁,本地令牌。"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="次要功能:强制无边框窗口化以及CSGO VAC屏蔽修复。"></Run>
|
||||
</Paragraph>
|
||||
</FlowDocument>
|
||||
</FlowDocumentScrollViewer>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
<Paragraph Language="zh-cn">
|
||||
<Run Text="Steam++ v1.0.2" FontSize="16"/>
|
||||
<Run Text=" "/>
|
||||
<Run Text="2020-12-21" FontSize="10" />
|
||||
<LineBreak />
|
||||
<Run Text="更新内容"></Run>
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="更新了由Benares制作的图标" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增帐户切换删除功能" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="添加github图片资源文件代理服务与discord代理服务支持" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="因为有问题暂时去掉了GOG Galaxy代理选项"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="修复一个会导致程序启动没有反应的bug"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="修复托盘菜单steam昵称过长ui错位bug"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增steam启动参数设置"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增启动时程序最小化到托盘菜单设置"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增捐助列表的展示"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增工具自动更新功能"></Run>
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Run Text="已知的未修复问题"></Run>
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="(严重)经反馈,程序运行时可能会影响部分steam游戏掉帧,GPU占用率变低,这个BUG目前在作者的机器上无法复现所以暂时没有修复,如果你遇到这个问题可以手动关闭steam++解决。" />
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="程序在高DPI缩放分辨率下可能会UI布局错位,目前暂时拖动程序可恢复。" />
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="部分用户无法加载游戏列表,无法复现,原因暂时不明。" />
|
||||
</Paragraph>
|
||||
<Paragraph Language="zh-cn">
|
||||
<Run Text="Steam++ v1.0.0" FontSize="16"/>
|
||||
<Run Text=" "/>
|
||||
<Run Text="2020-12-14" FontSize="10" />
|
||||
<LineBreak />
|
||||
<Run Text="发布第一个版本" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="主要功能:社区反代,帐户切换,成就解锁,本地令牌。"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="次要功能:强制无边框窗口化以及CSGO VAC屏蔽修复。"></Run>
|
||||
</Paragraph>
|
||||
</FlowDocument>
|
||||
</FlowDocumentScrollViewer>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -47,12 +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了。"/>
|
||||
<Run Text="如果尝试后无效只能依次在尝试验证游戏完整性,重启电脑,实在不行(大概)就只有重装CSGO了。"/>
|
||||
<LineBreak/>
|
||||
<Run Text="功能实现使用了狙击手Ricky的批处理指令。"></Run>
|
||||
</TextBlock>
|
||||
|
||||
<metro:PromptTextBox
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -43,7 +43,19 @@
|
||||
</TabItem.Header>
|
||||
<contents:AboutDonate></contents:AboutDonate>
|
||||
</TabItem>
|
||||
|
||||
|
||||
<TabItem>
|
||||
<TabItem.Header>
|
||||
<TextBlock Text="{Binding Resources.About_DonateList,Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
|
||||
Style="{StaticResource TabHeaderTextStyleKey}" />
|
||||
</TabItem.Header>
|
||||
<contents:AboutDonateList>
|
||||
<contents:AboutDonateList.DataContext>
|
||||
<viewModel:AboutDonateListViewModel></viewModel:AboutDonateListViewModel>
|
||||
</contents:AboutDonateList.DataContext>
|
||||
</contents:AboutDonateList>
|
||||
</TabItem>
|
||||
|
||||
<TabItem>
|
||||
<TabItem.Header>
|
||||
<TextBlock Text="{Binding Resources.AboutUpdateHistory,Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
|
||||
@@ -59,15 +71,18 @@
|
||||
</TabItem.Header>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Visibility="Collapsed">
|
||||
<TabItem>
|
||||
<TabItem.Header>
|
||||
<TextBlock Text="{Binding Resources.About_OpenSourceLicensing,Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
|
||||
Style="{StaticResource TabHeaderTextStyleKey}" />
|
||||
</TabItem.Header>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="8">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource HeaderTextStyleKey}" FontSize="20">
|
||||
<Run Text="此软件的诞生离不开以下开源软件"/>
|
||||
<Run Text="{Binding Resources.About_OpenSourceLicensing,Source={x:Static services:ResourceService.Current}, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource DetailTextStyleKey}">
|
||||
<Run Text="此软件的诞生离不开以下开源项目:"/>
|
||||
<LineBreak/>
|
||||
</TextBlock>
|
||||
<ItemsControl ItemsSource="{Binding Source={x:Static models:ProductInfo.Libraries}}">
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="10">
|
||||
<Grid Margin="8,0,8,8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
</Border>
|
||||
<!--</Expander>-->
|
||||
|
||||
|
||||
<!--Content-->
|
||||
<Border Grid.Row="1" Margin="8"
|
||||
BorderBrush="{DynamicResource BorderBrushKey}"
|
||||
|
||||
@@ -92,17 +92,27 @@
|
||||
<!--<TextBlock Text="最近登录的账户" Foreground="Green" Visibility="{Binding MostRecent,Converter={StaticResource BooleanToVisibilityConverter}}"></TextBlock>-->
|
||||
<!--</StackPanel>-->
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<Separator Opacity="0" Width="30"/>
|
||||
|
||||
<!--<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">-->
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<!--<Image Source="pack://application:,,,/Resources/Asstes/time.png" Width="20" HorizontalAlignment="Right" Margin="0,0,5,0" Visibility="{Binding MostRecent,Converter={StaticResource BooleanToVisibilityConverter}}"></Image>-->
|
||||
<TextBlock HorizontalAlignment="Right"
|
||||
<TextBlock HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
TextAlignment="Center" Width="Auto"
|
||||
Text="{Binding LastLoginTime,StringFormat={x:Static prop:Resources.LastloginTime},Mode=OneWay}"/>
|
||||
<!--</StackPanel>-->
|
||||
<Image HorizontalAlignment="Right" Source="/Resources/Asstes/delete.png" Width="16" Height="16" Cursor="Hand" ToolTip="{Binding Resources.Delete,Source={x:Static services:ResourceService.Current}}" Margin="10,0,0,0">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonUp">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="DeleteAccount_OnClick"
|
||||
MethodParameter="{Binding}"
|
||||
MethodTarget="{Binding DataContext,ElementName=u}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Image>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
<Rectangle Height=".99"
|
||||
Fill="{DynamicResource InactiveForegroundBrushKey}"
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="0,0,30,-4"
|
||||
Opacity="0.25">
|
||||
Opacity="0.30">
|
||||
</Image>
|
||||
<Border Grid.Column="0"
|
||||
BorderBrush="{DynamicResource BorderBrushKey}"
|
||||
@@ -75,8 +75,8 @@
|
||||
|
||||
<LineBreak />
|
||||
<Run Text="程序图标:" />
|
||||
<metro2:HyperlinkEx Uri="https://keylol.com/">
|
||||
<Run Text="@Keylol" />
|
||||
<metro2:HyperlinkEx Uri="https://steamcommunity.com/profiles/76561198110756239/">
|
||||
<Run Text="@Benares" />
|
||||
</metro2:HyperlinkEx>
|
||||
</TextBlock>
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<Run Text="请不要使用修改版魔改版程序。"></Run>
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Run Text="程序完全免费,"></Run>
|
||||
<Run Text="程序完全免费并开源于Github,"></Run>
|
||||
<LineBreak />
|
||||
<Run Text="若在任意渠道购买请差评退款。"></Run>
|
||||
<LineBreak />
|
||||
@@ -139,7 +139,7 @@
|
||||
<Run Text="此工具的大部分功能都是需要您下载安装Steam才能使用。" />
|
||||
</Paragraph>
|
||||
<Paragraph Language="zh-cn">
|
||||
<Run Text="主要功能" FontSize="18"/>
|
||||
<Run Text="核心功能" FontSize="18"/>
|
||||
<LineBreak/>
|
||||
<LineBreak />
|
||||
<Run Text=" "></Run>
|
||||
@@ -151,17 +151,16 @@
|
||||
<LineBreak/>
|
||||
<LineBreak />
|
||||
<Run Text=" "></Run>
|
||||
<Run Text="3.Steam游戏的成就统计管理功能,该功能的实现是调用了Steam客户端的接口。" />
|
||||
<Run Text="3.Steam成就统计信息修改,该功能的实现与SAM是一样的。" />
|
||||
<LineBreak/>
|
||||
<LineBreak />
|
||||
<Run Text=" "></Run>
|
||||
<Run Text="4.Steam本地两步身份验证器的实现,可以使您不用启动移动版Steam App也能查看您的令牌。" />
|
||||
<LineBreak/>
|
||||
<Run Text="4.Steam本地两步身份验证器,可以使您不用启动移动版Steam App也能查看您的令牌。" />
|
||||
<Run Text="(暂时还不支持进行市场交易确认,计划后续添加支持)"/>
|
||||
<LineBreak/>
|
||||
<LineBreak />
|
||||
<Run Text=" "></Run>
|
||||
<Run Text="5.一些游戏工具,目前已有强制游戏无边框窗口化,CSGO修复VAC屏蔽。" />
|
||||
<Run Text="5.一些游戏工具类功能(不会开发作弊相关功能),目前已有强制游戏无边框窗口化,CSGO修复VAC屏蔽。" />
|
||||
<Run Text="(正在开发...)"></Run>
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
@@ -169,13 +168,13 @@
|
||||
<LineBreak/>
|
||||
<LineBreak/>
|
||||
<Run Text=" "></Run>
|
||||
<Run Text="尝试用社区反代和成就管理的API实现一个全自动的挂卡功能。" />
|
||||
<Run Text="Steam自动挂卡,尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内登录Steam即可直接获取徽章卡片信息并开始挂卡。" />
|
||||
<Run Text="(接下来要做的...)"></Run>
|
||||
<LineBreak/>
|
||||
<LineBreak />
|
||||
<Run Text=" "></Run>
|
||||
<Run Text="Steam皮肤的可视化设计编辑功能。" />
|
||||
<Run Text="(短期内应该做不完...)"></Run>
|
||||
<Run Text="(挖坑画大饼,可视化编辑Steam皮肤,而且如果软件能上架Steam的话打算支持创意工坊分享设计的Steam皮肤,短期内肯定做不完...)"></Run>
|
||||
<LineBreak/>
|
||||
<LineBreak />
|
||||
<Run Text=" "></Run>
|
||||
@@ -219,19 +218,27 @@
|
||||
<metro2:HyperlinkEx Uri="https://spp.rmbgame.net">
|
||||
<Run Text="https://spp.rmbgame.net" />
|
||||
</metro2:HyperlinkEx>-->
|
||||
<Run Text="Release:" />
|
||||
<metro2:HyperlinkEx Uri="https://github.com/rmbadmin/Steam-PlusPlus/releases">
|
||||
<Run Text="https://github.com/rmbadmin/Steam-PlusPlus/releases" />
|
||||
|
||||
<Run Text="开源地址:" />
|
||||
<metro2:HyperlinkEx Uri="https://github.com/rmbadmin/SteamTools">
|
||||
<Run Text="https://github.com/rmbadmin/SteamTools" />
|
||||
</metro2:HyperlinkEx>
|
||||
<LineBreak />
|
||||
<Run Text="发布地址:" />
|
||||
<metro2:HyperlinkEx Uri="https://github.com/rmbadmin/SteamTools/releases">
|
||||
<Run Text="https://github.com/rmbadmin/SteamTools/releases" />
|
||||
</metro2:HyperlinkEx>
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Run Text="BUG&建议反馈:" />
|
||||
<metro2:HyperlinkEx Uri="https://github.com/rmbadmin/SteamTools/issues">
|
||||
<Run Text="https://github.com/rmbadmin/SteamTools/issues" />
|
||||
</metro2:HyperlinkEx>
|
||||
<LineBreak />
|
||||
<Run Text="或者发送到我的邮箱:"></Run>
|
||||
<metro2:HyperlinkEx Uri="rmb@rmbgame.net">
|
||||
<Run Text="rmb@rmbgame.net" />
|
||||
</metro2:HyperlinkEx>
|
||||
<Run Text="开源地址:" />
|
||||
<metro2:HyperlinkEx Uri="https://github.com/rmbadmin/Steam-PlusPlus.git">
|
||||
<Run Text="https://github.com/rmbadmin/Steam-PlusPlus.git" />
|
||||
</metro2:HyperlinkEx>
|
||||
</Paragraph>
|
||||
</FlowDocument>
|
||||
</FlowDocumentScrollViewer>
|
||||
|
||||
@@ -232,7 +232,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Margin="0,2"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right" Foreground="{DynamicResource AccentForegroundBrushKey}">
|
||||
HorizontalAlignment="Right" Foreground="{DynamicResource ActiveForegroundBrushKey}">
|
||||
<Run Text="{Binding Resources.Search,Source={x:Static services:ResourceService.Current},Mode=OneWay}" />
|
||||
<Run Text=":" />
|
||||
</TextBlock>
|
||||
|
||||
@@ -260,9 +260,9 @@
|
||||
<metro:PromptTextBox Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
TextWrapping="Wrap"
|
||||
AcceptsReturn="True"
|
||||
VerticalScrollBarVisibility="Visible"
|
||||
MaxLines="3"
|
||||
AcceptsReturn="True"
|
||||
VerticalScrollBarVisibility="Visible"
|
||||
MaxLines="3"
|
||||
Text="{Binding SteamGuard, Mode=TwoWay}"
|
||||
Prompt="" />
|
||||
<!--<metro2:CallMethodButton Width="80"
|
||||
|
||||
@@ -29,16 +29,16 @@
|
||||
<!-- Windows Vista -->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||
|
||||
<!--Windows 7
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
|
||||
<!--Windows 7-->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||
|
||||
<!--Windows 8
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
||||
<!--Windows 8-->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||
|
||||
Windows 8.1
|
||||
<!--Windows 8.1-->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||
|
||||
Windows 10
|
||||
<!--Windows 10-->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
|
||||
</application>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// ==UserScript==
|
||||
// @name Steam解锁不可描述游戏商店页
|
||||
// @namespace http://tampermonkey.net/
|
||||
// @version 1.1
|
||||
// @description Steam Store (Turn on mature content in some region)
|
||||
// @author Dogfight360
|
||||
// @match http*://store.steampowered.com/
|
||||
// @icon http://store.steampowered.com/favicon.ico
|
||||
// @namespace https://greasyfork.org/
|
||||
// @enable true
|
||||
// @grant none
|
||||
// ==/UserScript==
|
||||
|
||||
(function() {
|
||||
document.cookie="wants_mature_content=1"
|
||||
document.cookie="birthtime=22503171"
|
||||
})();
|
||||
@@ -0,0 +1,99 @@
|
||||
# 前言
|
||||
|
||||
Steam++项目创建于2018年5月8日,不过并不是耗时两年才做出来,之前一直由于工作原因,并没有多少空闲时间,直到今年中旬辞职了,才开始猛肝。
|
||||
本来是想一直做到完全体了,才考虑发布,不过现在感慨一下,果然是没法这么快就整完的,所以还是一版一版更新做到完全体吧。
|
||||
Steam++只在keylol论坛与github发布,为了账号安全,请不要到其它不明地方下载。
|
||||
已经收到了B叔制作的图标,下个版本可以换上更好看的图标了。
|
||||
|
||||
# Steam++工具箱
|
||||
## 已知的未修复问题
|
||||
> 目前已知坛友反馈的严重BUG问题
|
||||
* steam++启动后运行steam在运行steam的部分游戏会使游戏掉帧,gpu利用率很低,这个问题在作者的电脑上确实无法复现,所以暂时只能请各位在遇到此问题时手动关闭steam++,带来不便请谅解,抱歉。
|
||||
|
||||
## 工具介绍
|
||||
`Steam++`是一个包含多种Steam工具功能的工具箱,开源发布于[Github](https://github.com/rmbadmin/SteamTools),如果您对发布的二进制文件不放心,可以自行下载源码编译运行。
|
||||
此工具的大部分功能都是需要您下载安装Steam才能使用。
|
||||
工具预计将整合进大部分常用的Steam相关工具,并且尽力做到比原工具更好用,在各种整合添加功能的同时,也会注意体积尽量的控制到最小。
|
||||
查毒链接[https://www.virustotal.com/gui/file/3889babb8b0dcf79b16045679a5cb57a70cc6d60447078fb65b8a8979da2f14d/detection](https://www.virustotal.com/gui/file/3889babb8b0dcf79b16045679a5cb57a70cc6d60447078fb65b8a8979da2f14d/detection)
|
||||
虽然没有什么杀毒软件报毒,但是使用过程中可能遇到windows defender误报,您可以选择添加信任。
|
||||
软件截图
|
||||
[hide]
|
||||
[attachimg]1224039[/attachimg]
|
||||
[attachimg]1224038[/attachimg]
|
||||
[attachimg]1224040[/attachimg]
|
||||
[/hide]
|
||||
|
||||
## 核心功能
|
||||
|
||||
|
||||
### 1. 反代Steam的社区网页使其能正常访问
|
||||
|
||||
功能类似羽翼城大佬的steamcommunity_302,使用[Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)开源项目进行本地反代,相比302工具具有更快的启动速度,以及支持简单的脚本注入。该功能也可以配合羽翼城大佬的[UsbEAm Hosts Editor](https://www.dogfight360.com/blog/475/)里的网页相关-steamcommunity_302 社区/api/商店加载速度选项的hosts提升加载速度。
|
||||
[attachimg]1224032[/attachimg]
|
||||
|
||||
### 2. 快速切换当前PC已经记住登陆的Steam账号
|
||||
|
||||
该功能是读取Steam路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌。
|
||||
[attachimg]1224033[/attachimg]
|
||||
|
||||
### 3. Steam游戏的成就统计管理功能
|
||||
|
||||
功能参考[SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)进行二次开发,修复了成就语言有中文却依然是英文成就信息的BUG,修改了游戏列表的加载和操作易用性。
|
||||
[attachimg]1224034[/attachimg]
|
||||
|
||||
### 4. Steam本地两步身份验证器
|
||||
|
||||
功能参考[WinAuth](https://github.com/winauth/winauth)开发,可以使您不用启动移动版Steam App也能查看您的令牌,功能类似的软件有[WinAuth](https://github.com/winauth/winauth)、[SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)。
|
||||
[attachimg]1224035[/attachimg]
|
||||
|
||||
### 5. 一些游戏工具
|
||||
|
||||
目前已有强制游戏无边框窗口化,CSGO修复VAC屏蔽。
|
||||
这一块是随缘做一些我经常用或者闲着没事捣鼓的功能。
|
||||
|
||||
将任何游戏强制无边框窗口化
|
||||
[attachimg]1224036[/attachimg]
|
||||
使任何窗口化游戏变成动态桌面壁纸(终于可以用《山》当壁纸了)
|
||||
[attachimg]1224037[/attachimg]
|
||||
|
||||
------
|
||||
|
||||
|
||||
## 预计后续添加的功能
|
||||
|
||||
|
||||
### Steam自动挂卡
|
||||
|
||||
尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内不用登录Steam即可直接获取徽章卡片信息并开始挂卡。
|
||||
|
||||
### Steam皮肤设计器
|
||||
|
||||
挖坑画大饼,可视化编辑Steam皮肤,而且如果软件能上架Steam的话打算支持创意工坊分享设计的Steam皮肤,短期内肯定做不完。
|
||||
|
||||
### 插件形式加载运行ASF
|
||||
|
||||
以插件形式支持ASF在工具内运行并增强ASF在Windows Desktop环境下的使用。
|
||||
|
||||
### Steam自定义封面管理
|
||||
|
||||
增强Steam自定义封面的管理以及从[SteamGridDB](https://www.steamgriddb.com/)快速匹配下载应用封面。
|
||||
|
||||
------
|
||||
|
||||
|
||||
## 运行环境
|
||||
|
||||
> 程序使用C# WPF在 .NET Framework4.7.2环境下开发,如果无法运行请下载安装[.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)。
|
||||
|
||||
|
||||
## 下载
|
||||
|
||||
> [Github](https://github.com/rmbadmin/SteamTools/releases)
|
||||
> [蓝奏云](https://wws.lanzous.com/ijIlwjg2bjc)
|
||||
> [百度云](https://pan.baidu.com/s/19XCB3-X7isygG6UFpXcCtg)
|
||||
> 查看百度云提取码
|
||||
> [hide]
|
||||
> 提取码:zbs6
|
||||
> [/hide]
|
||||
> exe体积:4.81MB
|
||||
> md5:AEECBD9B268C0BB8D619555CE125C9A5
|
||||