Skip to content

Commit 6def85a

Browse files
committed
🚧 ValveKeyValue
1 parent 4dcff4f commit 6def85a

File tree

8 files changed

+302
-86
lines changed

8 files changed

+302
-86
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using BD.SteamClient.Services;
2+
using BD.SteamClient.Services.Implementation;
3+
using BD.SteamClient.Services.Mvvm;
4+
using Microsoft.Extensions.Logging.Abstractions;
5+
6+
namespace BD.SteamClient.UnitTest;
7+
8+
public sealed class SteamServiceTest
9+
{
10+
IServiceProvider service;
11+
12+
ISteamService Client => service.GetRequiredService<ISteamService>();
13+
14+
[SetUp]
15+
public void Setup()
16+
{
17+
var services = new ServiceCollection();
18+
services.AddLogging(l => l.AddProvider(NullLoggerProvider.Instance));
19+
services.AddSingleton<ISteamService, TestSteamServiceImpl>();
20+
service = services.BuildServiceProvider();
21+
}
22+
23+
[Test]
24+
public void TestGetRememberUserList()
25+
{
26+
var list = Client.GetRememberUserList();
27+
list.ForEach(x =>
28+
{
29+
TestContext.WriteLine($"{x.SteamId64} {x.SteamID}");
30+
});
31+
Assert.True(list.Any_Nullable());
32+
}
33+
34+
sealed class TestSteamServiceImpl : SteamServiceImpl
35+
{
36+
public TestSteamServiceImpl(ILoggerFactory loggerFactory) : base(loggerFactory)
37+
{
38+
39+
}
40+
41+
public override ISteamConnectService Conn => throw new NotImplementedException();
42+
43+
protected override string AppResources_SaveEditedAppInfo_SaveFailed => throw new NotImplementedException();
44+
45+
protected override string? SteamSettings_StratParameter => throw new NotImplementedException();
46+
47+
protected override bool SteamSettings_IsRunSteamAdministrator => throw new NotImplementedException();
48+
49+
protected override Dictionary<uint, string?> GameLibrarySettings_HideGameList => throw new NotImplementedException();
50+
}
51+
}

‎src/BD.SteamClient/BD.SteamClient.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626
<Compile Include="..\ImplicitUsings.MessagePack.cs">
2727
<LinkBase>Properties</LinkBase>
2828
</Compile>
29-
<Compile Include="..\..\ref\Gameloop.Vdf\Gameloop.Vdf\**\*.cs">
29+
<!--<Compile Include="..\..\ref\Gameloop.Vdf\Gameloop.Vdf\**\*.cs">
3030
<LinkBase>ThirdParty\Gameloop.Vdf</LinkBase>
3131
</Compile>
3232
<Compile Remove="..\..\ref\Gameloop.Vdf\Gameloop.Vdf\bin\**" />
3333
<Compile Remove="..\..\ref\Gameloop.Vdf\Gameloop.Vdf\obj\**" />
34-
<Compile Remove="..\..\ref\Gameloop.Vdf\Gameloop.Vdf\Properties\**" />
34+
<Compile Remove="..\..\ref\Gameloop.Vdf\Gameloop.Vdf\Properties\**" />-->
3535
<Compile Include="..\..\ref\Steam4NET\Steam4NET\**\*.cs">
3636
<LinkBase>ThirdParty\Steam4NET</LinkBase>
3737
</Compile>
@@ -65,6 +65,7 @@
6565
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' OR $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos' OR $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst' OR $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == ''">
6666
<!-- Desktop Only -->
6767
<PackageReference Include="SteamKit2" />
68+
<PackageReference Include="ValveKeyValue" />
6869
<!--<ProjectReference Include="..\..\ref\Gameloop.Vdf\Gameloop.Vdf\Gameloop.Vdf.csproj" />-->
6970
<!--<ProjectReference Include="..\..\ref\Steam4NET\Steam4NET\Steam4NET.csproj" />-->
7071
<!--<ProjectReference Include="..\..\ref\SteamAchievementManager\SAM.API\SAM.API.csproj" />-->
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
using Newtonsoft.Json;
2+
using JsonSerializer = Newtonsoft.Json.JsonSerializer;
3+
4+
// ReSharper disable once CheckNamespace
5+
namespace System;
6+
7+
static class HttpClientExtensions
8+
{
9+
static async Task<T?> SendAsync<T>(
10+
this HttpClient client,
11+
ILogger logger,
12+
JsonSerializer? jsonSerializer,
13+
bool isCheckHttpUrl,
14+
string? requestUri,
15+
Func<HttpRequestMessage> requestFactory,
16+
string? accept,
17+
//bool enableForward,
18+
CancellationToken cancellationToken,
19+
Action<HttpResponseMessage>? handlerResponse = null,
20+
Action<HttpResponseMessage>? handlerResponseByIsNotSuccessStatusCode = null) where T : notnull
21+
{
22+
HttpRequestMessage? request = null;
23+
bool requestIsSend = false;
24+
HttpResponseMessage? response = null;
25+
bool notDisposeResponse = false;
26+
try
27+
{
28+
request = requestFactory();
29+
requestUri ??= request.RequestUri?.ToString();
30+
31+
if (!isCheckHttpUrl && !String2.IsHttpUrl(requestUri)) return default;
32+
33+
//if (enableForward && IsAllowUrl(requestUri))
34+
//{
35+
// try
36+
// {
37+
// requestIsSend = true;
38+
// response = await Csc.Forward(request,
39+
// HttpCompletionOption.ResponseHeadersRead,
40+
// cancellationToken);
41+
// }
42+
// catch (Exception e)
43+
// {
44+
// logger.LogWarning(e, "CloudService Forward Fail, requestUri: {0}", requestUri);
45+
// response = null;
46+
// }
47+
//}
48+
49+
if (response == null)
50+
{
51+
if (requestIsSend)
52+
{
53+
request.Dispose();
54+
request = requestFactory();
55+
}
56+
response = await client.SendAsync(request,
57+
HttpCompletionOption.ResponseHeadersRead,
58+
cancellationToken).ConfigureAwait(false);
59+
}
60+
61+
handlerResponse?.Invoke(response);
62+
63+
if (response.IsSuccessStatusCode)
64+
{
65+
if (response.Content != null)
66+
{
67+
var rspContentClrType = typeof(T);
68+
if (rspContentClrType == typeof(string))
69+
{
70+
return (T)(object)await response.Content.ReadAsStringAsync();
71+
}
72+
else if (rspContentClrType == typeof(byte[]))
73+
{
74+
return (T)(object)await response.Content.ReadAsByteArrayAsync();
75+
}
76+
else if (rspContentClrType == typeof(Stream))
77+
{
78+
notDisposeResponse = true;
79+
return (T)(object)await response.Content.ReadAsStreamAsync();
80+
}
81+
var mime = response.Content.Headers.ContentType?.MediaType ?? accept;
82+
switch (mime)
83+
{
84+
case MediaTypeNames.JSON:
85+
case MediaTypeNames.XML:
86+
case MediaTypeNames.XML_APP:
87+
{
88+
using var stream = await response.Content
89+
.ReadAsStreamAsync().ConfigureAwait(false);
90+
using var reader = new StreamReader(stream, Encoding.UTF8);
91+
switch (mime)
92+
{
93+
case MediaTypeNames.JSON:
94+
{
95+
if (jsonSerializer == null)
96+
throw new NotSupportedException(null, new ArgumentNullException(nameof(jsonSerializer)));
97+
using var json = new JsonTextReader(reader);
98+
return jsonSerializer.Deserialize<T>(json);
99+
}
100+
case MediaTypeNames.XML:
101+
case MediaTypeNames.XML_APP:
102+
{
103+
var xmlSerializer = new XmlSerializer(typeof(T));
104+
return (T?)xmlSerializer.Deserialize(reader);
105+
}
106+
}
107+
}
108+
break;
109+
}
110+
}
111+
}
112+
else
113+
{
114+
handlerResponseByIsNotSuccessStatusCode?.Invoke(response);
115+
}
116+
}
117+
catch (Exception e)
118+
{
119+
var knownType = e.GetKnownType();
120+
if (knownType == ExceptionKnownType.Unknown)
121+
{
122+
logger.LogError(e, "SendAsync fail, requestUri: {0}", requestUri);
123+
}
124+
}
125+
finally
126+
{
127+
request?.Dispose();
128+
if (!notDisposeResponse)
129+
{
130+
response?.Dispose();
131+
}
132+
}
133+
return default;
134+
}
135+
136+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
137+
public static Task<T?> SendAsync<T>(
138+
this HttpClient client,
139+
ILogger logger,
140+
JsonSerializer? jsonSerializer,
141+
string? requestUri,
142+
Func<HttpRequestMessage> requestFactory,
143+
string? accept,
144+
//bool enableForward,
145+
CancellationToken cancellationToken,
146+
Action<HttpResponseMessage>? handlerResponse = null,
147+
Action<HttpResponseMessage>? handlerResponseByIsNotSuccessStatusCode = null) where T : notnull
148+
{
149+
return client.SendAsync<T>(
150+
logger,
151+
jsonSerializer,
152+
isCheckHttpUrl: false,
153+
requestUri,
154+
requestFactory,
155+
accept,
156+
//enableForward,
157+
cancellationToken,
158+
handlerResponse,
159+
handlerResponseByIsNotSuccessStatusCode);
160+
}
161+
162+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
163+
public static Task<T?> GetAsync<T>(
164+
this HttpClient client,
165+
ILogger logger,
166+
string requestUri,
167+
string accept = MediaTypeNames.JSON,
168+
CancellationToken cancellationToken = default,
169+
string? cookie = null,
170+
string? userAgent = null,
171+
JsonSerializer? jsonSerializer = null) where T : notnull
172+
{
173+
if (!String2.IsHttpUrl(requestUri))
174+
return Task.FromResult(default(T?));
175+
return client.SendAsync<T>(logger, jsonSerializer, isCheckHttpUrl: true, requestUri, () =>
176+
{
177+
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
178+
if (cookie != null)
179+
{
180+
request.Headers.Add("Cookie", cookie);
181+
}
182+
request.Headers.Accept.ParseAdd(accept);
183+
if (userAgent != null)
184+
request.Headers.UserAgent.ParseAdd(userAgent);
185+
return request;
186+
}, accept/*, true*/, cancellationToken);
187+
}
188+
}

‎src/BD.SteamClient/Helpers/VdfHelper.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#if (WINDOWS || MACCATALYST || MACOS || LINUX) && !(IOS || ANDROID)
2-
using Gameloop.Vdf;
3-
using Gameloop.Vdf.Linq;
2+
using System.IO;
3+
using ValveKeyValue;
44

55
namespace BD.SteamClient.Helpers;
66

@@ -16,17 +16,20 @@ public static class VdfHelper
1616
/// </summary>
1717
/// <param name="filePath"></param>
1818
/// <returns></returns>
19-
public static VProperty Read(string filePath)
19+
public static KVObject Read(string filePath)
2020
{
21-
var text = File.ReadAllText(filePath, Encoding.UTF8);
22-
return VdfConvert.Deserialize(text);
21+
var kv = KVSerializer.Create(KVSerializationFormat.KeyValues1Text);
22+
var data = kv.Deserialize(IOPath.OpenRead(filePath));
23+
return data;
2324
}
2425

25-
public static void Write(string filePath, VProperty content)
26+
public static void Write(string filePath, KVObject content)
2627
{
2728
try
2829
{
29-
File.WriteAllText(filePath, VdfConvert.Serialize(content), Encoding.UTF8);
30+
using var stream = File.OpenWrite(filePath);
31+
var kv = KVSerializer.Create(KVSerializationFormat.KeyValues1Text);
32+
kv.Serialize(stream, content);
3033
}
3134
catch (Exception e)
3235
{

‎src/BD.SteamClient/Models/AuthorizedDevice.cs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ public class AuthorizedDevice : ReactiveObject
66

77
public AuthorizedDevice() { }
88

9-
public AuthorizedDevice(string vdfString) : this()
10-
{
11-
OriginVdfString = vdfString;
12-
}
13-
149
public bool Disable { get; set; }
1510

1611
public string ProfileUrl => string.Format(STEAM_PROFILES_URL, SteamId64_Int);
@@ -76,12 +71,4 @@ public Task<string?>? AvatarStream
7671
get => _AvatarStream;
7772
set => this.RaiseAndSetIfChanged(ref _AvatarStream, value);
7873
}
79-
80-
public string? OriginVdfString { get; set; }
81-
82-
public string CurrentVdfString =>
83-
"\t\t\"" + SteamId3_Int + "\"\n\t\t{\n" +
84-
"\t\t\t\"timeused\"\t\t\"" + Timeused + "\"\n" +
85-
"\t\t\t\"description\"\t\t\"" + Description + "\"\n" +
86-
"\t\t\t\"tokenid\"\t\t\"" + Tokenid + "\"\n\t\t}";
8774
}

0 commit comments

Comments
 (0)