修离线缓存
This commit is contained in:
parent
888ddce4ef
commit
6f5c21aa8f
@ -11,7 +11,7 @@ namespace AnotherReplayReader
|
|||||||
public About()
|
public About()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_idBox.Text = Auth.ID;
|
_idBox.Text = Auth.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
|
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
|
||||||
|
22
Auth.cs
22
Auth.cs
@ -9,11 +9,11 @@ namespace AnotherReplayReader
|
|||||||
{
|
{
|
||||||
internal static class Auth
|
internal static class Auth
|
||||||
{
|
{
|
||||||
public static string? ID { get; }
|
public static string? Id { get; }
|
||||||
|
|
||||||
static Auth()
|
static Auth()
|
||||||
{
|
{
|
||||||
ID = null;
|
Id = null;
|
||||||
|
|
||||||
string? windowsID;
|
string? windowsID;
|
||||||
try
|
try
|
||||||
@ -56,17 +56,17 @@ namespace AnotherReplayReader
|
|||||||
|
|
||||||
using var sha = SHA256.Create();
|
using var sha = SHA256.Create();
|
||||||
var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(windowsID + randomKey));
|
var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(windowsID + randomKey));
|
||||||
ID = string.Concat(hash.Skip(3).Take(10).Select(x => $"{x:X2}"));
|
Id = string.Concat(hash.Skip(3).Take(10).Select(x => $"{x:X2}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetKey()
|
public static string GetKey()
|
||||||
{
|
{
|
||||||
if (ID == null)
|
if (Id == null)
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var text = $"{ID}{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
|
var text = $"{Id}{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
|
||||||
var bytes = Encoding.UTF8.GetBytes(text);
|
var bytes = Encoding.UTF8.GetBytes(text);
|
||||||
var pre = Encoding.UTF8.GetBytes("playertable!");
|
var pre = Encoding.UTF8.GetBytes("playertable!");
|
||||||
var salt = new byte[9];
|
var salt = new byte[9];
|
||||||
@ -82,5 +82,17 @@ namespace AnotherReplayReader
|
|||||||
|
|
||||||
return Convert.ToBase64String(salt.Concat(bytes).Select((x, i) => (byte)(x ^ pre[i % pre.Length])).ToArray());
|
return Convert.ToBase64String(salt.Concat(bytes).Select((x, i) => (byte)(x ^ pre[i % pre.Length])).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[]? IdAsKey()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Id))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(Id);
|
||||||
|
var destination = Enumerable.Repeat<byte>(0xEA, 24).ToArray();
|
||||||
|
Array.Copy(bytes, destination, Math.Min(bytes.Length, destination.Length));
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
Cache.cs
4
Cache.cs
@ -14,9 +14,11 @@ namespace AnotherReplayReader
|
|||||||
|
|
||||||
private readonly ConcurrentDictionary<string, string> _storage = new();
|
private readonly ConcurrentDictionary<string, string> _storage = new();
|
||||||
|
|
||||||
|
public Task Initialization { get; }
|
||||||
|
|
||||||
public Cache()
|
public Cache()
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
Initialization = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -86,17 +86,19 @@ namespace AnotherReplayReader
|
|||||||
_list = converted;
|
_list = converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list is null)
|
if (list is null || Auth.IdAsKey() is not { } encryptKey)
|
||||||
{
|
{
|
||||||
_cache.Set<string?>(StoredKey, null);
|
_cache.Set<string?>(StoredKey, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var aes = Aes.Create();
|
|
||||||
using var encryptor = aes.CreateEncryptor(Encoding.UTF8.GetBytes(Auth.ID), aes.IV);
|
|
||||||
using var memory = new MemoryStream();
|
using var memory = new MemoryStream();
|
||||||
using var decryptorStream = new CryptoStream(memory, encryptor, CryptoStreamMode.Write);
|
using var aes = Aes.Create();
|
||||||
|
using (var encryptor = aes.CreateEncryptor(encryptKey, aes.IV))
|
||||||
|
using (var decryptorStream = new CryptoStream(memory, encryptor, CryptoStreamMode.Write))
|
||||||
|
{
|
||||||
await SerializeAsync(decryptorStream, list, _jsonOptions).ConfigureAwait(false);
|
await SerializeAsync(decryptorStream, list, _jsonOptions).ConfigureAwait(false);
|
||||||
|
}
|
||||||
memory.Flush();
|
memory.Flush();
|
||||||
_cache.SetValues((StoredKey, Convert.ToBase64String(memory.ToArray())), (IvKey, Convert.ToBase64String(aes.IV)));
|
_cache.SetValues((StoredKey, Convert.ToBase64String(memory.ToArray())), (IvKey, Convert.ToBase64String(aes.IV)));
|
||||||
}
|
}
|
||||||
@ -155,15 +157,16 @@ namespace AnotherReplayReader
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
await _cache.Initialization;
|
||||||
var stored = _cache.GetOrDefault(StoredKey, string.Empty);
|
var stored = _cache.GetOrDefault(StoredKey, string.Empty);
|
||||||
var iv = Convert.FromBase64String(_cache.GetOrDefault(IvKey, string.Empty));
|
var iv = Convert.FromBase64String(_cache.GetOrDefault(IvKey, string.Empty));
|
||||||
if (string.IsNullOrWhiteSpace(stored))
|
if (string.IsNullOrWhiteSpace(stored) || Auth.IdAsKey() is not { } key)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var aes = Aes.Create();
|
using var aes = Aes.Create();
|
||||||
using var decryptor = aes.CreateDecryptor(Encoding.UTF8.GetBytes(Auth.ID), iv);
|
using var decryptor = aes.CreateDecryptor(key, iv);
|
||||||
using var memory = new MemoryStream(Convert.FromBase64String(stored));
|
using var memory = new MemoryStream(Convert.FromBase64String(stored));
|
||||||
using var decryptorStream = new CryptoStream(memory, decryptor, CryptoStreamMode.Read);
|
using var decryptorStream = new CryptoStream(memory, decryptor, CryptoStreamMode.Read);
|
||||||
var cachedTable = await DeserializeAsync<List<IpAndPlayer>>(decryptorStream, _jsonOptions).ConfigureAwait(false);
|
var cachedTable = await DeserializeAsync<List<IpAndPlayer>>(decryptorStream, _jsonOptions).ConfigureAwait(false);
|
||||||
|
@ -13,7 +13,11 @@
|
|||||||
<TextBox x:Name="_idField" Height="16" Margin="294,27,92,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" TextChanged="OnIpFieldChanged" />
|
<TextBox x:Name="_idField" Height="16" Margin="294,27,92,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" TextChanged="OnIpFieldChanged" />
|
||||||
<TextBlock x:Name="textBlock1" HorizontalAlignment="Left" Margin="205,28,0,0" TextWrapping="Wrap" Text="玩家名称 / 说明" VerticalAlignment="Top"/>
|
<TextBlock x:Name="textBlock1" HorizontalAlignment="Left" Margin="205,28,0,0" TextWrapping="Wrap" Text="玩家名称 / 说明" VerticalAlignment="Top"/>
|
||||||
<Button x:Name="_setIPButton" Content="上传" Margin="705,26,12,0" VerticalAlignment="Top" Click="OnClick"/>
|
<Button x:Name="_setIPButton" Content="上传" Margin="705,26,12,0" VerticalAlignment="Top" Click="OnClick"/>
|
||||||
<DataGrid x:Name="_dataGrid" Margin="20,60,12,19" MouseDoubleClick="DataGrid_MouseDoubleClick" IsReadOnly="True">
|
<DataGrid x:Name="_dataGrid"
|
||||||
|
Margin="20,60,12,19"
|
||||||
|
MouseDoubleClick="DataGrid_MouseDoubleClick"
|
||||||
|
IsReadOnly="True"
|
||||||
|
AutoGenerateColumns="False">
|
||||||
<DataGrid.Columns>
|
<DataGrid.Columns>
|
||||||
<DataGridTextColumn Header="IP" Binding="{Binding Path=IpString}"/>
|
<DataGridTextColumn Header="IP" Binding="{Binding Path=IpString}"/>
|
||||||
<DataGridTextColumn Header="玩家名称 / 说明" Binding="{Binding Path=Id}"/>
|
<DataGridTextColumn Header="玩家名称 / 说明" Binding="{Binding Path=Id}"/>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using AnotherReplayReader.Utils;
|
using AnotherReplayReader.Utils;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -20,16 +22,21 @@ namespace AnotherReplayReader
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_identity = identity;
|
_identity = identity;
|
||||||
Refresh();
|
Refresh(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Refresh()
|
private async void Refresh(bool showCached)
|
||||||
{
|
{
|
||||||
_setIPButton.IsEnabled = false;
|
_setIPButton.IsEnabled = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_dataGrid.Items.Clear();
|
var loading = new IpAndPlayer[] { new() { Ip = 0, Id = "正在加载..." } };
|
||||||
_dataGrid.Items.Add(new IpAndPlayer { Ip = 0, Id = "正在加载..." });
|
_dataGrid.ItemsSource = loading;
|
||||||
|
if (showCached)
|
||||||
|
{
|
||||||
|
await Display();
|
||||||
|
_dataGrid.ItemsSource = loading.Concat(_dataGrid.ItemsSource.Cast<IpAndPlayer>());
|
||||||
|
}
|
||||||
await _identity.Fetch();
|
await _identity.Fetch();
|
||||||
await Display();
|
await Display();
|
||||||
}
|
}
|
||||||
@ -45,10 +52,10 @@ namespace AnotherReplayReader
|
|||||||
|
|
||||||
private async Task Display(string filter = "", string nameFilter = "")
|
private async Task Display(string filter = "", string nameFilter = "")
|
||||||
{
|
{
|
||||||
var newList = await Task.Run(() =>
|
var result = await Task.Run(() =>
|
||||||
{
|
{
|
||||||
var pinyin = nameFilter.ToPinyin();
|
var pinyin = nameFilter.ToPinyin();
|
||||||
return _identity
|
var query = _identity
|
||||||
.AsSortedList()
|
.AsSortedList()
|
||||||
.Where(x =>
|
.Where(x =>
|
||||||
{
|
{
|
||||||
@ -61,13 +68,10 @@ namespace AnotherReplayReader
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return x.Id.ContainsIgnoreCase(nameFilter);
|
return x.Id.ContainsIgnoreCase(nameFilter);
|
||||||
})
|
|
||||||
.ToArray();
|
|
||||||
});
|
});
|
||||||
|
return new ObservableCollection<IpAndPlayer>(query);
|
||||||
_dataGrid.Items.Clear();
|
});
|
||||||
_dataGrid.ItemsSource = newList;
|
_dataGrid.ItemsSource = result;
|
||||||
_dataGrid.Items.Refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnClick(object sender, RoutedEventArgs e)
|
private async void OnClick(object sender, RoutedEventArgs e)
|
||||||
@ -97,7 +101,7 @@ namespace AnotherReplayReader
|
|||||||
MessageBox.Show(this, "设置 IP 表失败");
|
MessageBox.Show(this, "设置 IP 表失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
Refresh();
|
Refresh(false);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user