get subscription userinfo

This commit is contained in:
2dust
2022-10-06 15:42:35 +08:00
parent cc0288ed5d
commit a5b208e729
11 changed files with 206 additions and 174 deletions

View File

@@ -51,18 +51,18 @@ namespace clashN.Base
}
return null;
}
public async Task<string> GetAsync(HttpClient client, string url, CancellationToken token)
public async Task<(string, HttpResponseHeaders)> GetAsync(HttpClient client, string url, CancellationToken token)
{
if (Utils.IsNullOrEmpty(url))
{
return null;
return (null, null);
}
HttpResponseMessage response = await client.GetAsync(url, token);
if (!response.IsSuccessStatusCode)
{
throw new Exception(string.Format("The request returned with HTTP status code {0}", response.StatusCode));
}
return await response.Content.ReadAsStringAsync();
return (await response.Content.ReadAsStringAsync(), response.Headers);
}

View File

@@ -637,7 +637,16 @@ namespace clashN.Handler
}
}
public static void ClearAllServerStatistics(ref Config config)
{
foreach (var item in config.profileItems)
{
item.uploadRemote = 0;
item.downloadRemote = 0;
}
ToJsonFile(config);
}
#endregion
}

View File

@@ -71,7 +71,7 @@ namespace clashN.Handler
/// DownloadString
/// </summary>
/// <param name="url"></param>
public async Task<string> DownloadStringAsync(string url, bool blProxy, string userAgent)
public async Task<(string, HttpResponseHeaders)> DownloadStringAsync(string url, bool blProxy, string userAgent)
{
try
{
@@ -109,7 +109,7 @@ namespace clashN.Handler
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
return (null, null);
}
public async Task<string> UrlRedirectAsync(string url, bool blProxy)

View File

@@ -7,34 +7,34 @@ namespace clashN.Handler
class StatisticsHandler
{
private Config config_;
private ServerStatistics serverStatistics_;
//private ServerStatistics serverStatistics_;
private bool exitFlag_;
private ClientWebSocket webSocket = null;
string url = string.Empty;
Action<ulong, ulong, List<ProfileStatItem>> updateFunc_;
Action<ulong, ulong> updateFunc_;
private bool Enable
{
get; set;
}
private List<ProfileStatItem> Statistic
{
get
{
return serverStatistics_.profileStat;
}
}
//private List<ProfileStatItem> Statistic
//{
// get
// {
// return serverStatistics_.profileStat;
// }
//}
public StatisticsHandler(Config config, Action<ulong, ulong, List<ProfileStatItem>> update)
public StatisticsHandler(Config config, Action<ulong, ulong> update)
{
config_ = config;
Enable = config.enableStatistics;
updateFunc_ = update;
exitFlag_ = false;
LoadFromFile();
//LoadFromFile();
Task.Run(() => Run());
}
@@ -106,18 +106,14 @@ namespace clashN.Handler
var result = Encoding.UTF8.GetString(buffer, 0, res.Count);
if (!Utils.IsNullOrEmpty(result))
{
string itemId = config_.indexId;
ProfileStatItem serverStatItem = GetServerStatItem(itemId);
var serverStatItem = config_.GetProfileItem(config_.indexId);
ParseOutput(result, out ulong up, out ulong down);
if (up + down > 0)
{
serverStatItem.todayUp += up;
serverStatItem.todayDown += down;
serverStatItem.totalUp += up;
serverStatItem.totalDown += down;
serverStatItem.uploadRemote += up;
serverStatItem.downloadRemote += down;
}
updateFunc_(up, down, new List<ProfileStatItem> { serverStatItem });
updateFunc_(up, down);
}
res = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
@@ -133,103 +129,103 @@ namespace clashN.Handler
}
}
public void LoadFromFile()
{
try
{
string result = Utils.LoadResource(Utils.GetConfigPath(Global.StatisticLogOverall));
if (!Utils.IsNullOrEmpty(result))
{
serverStatistics_ = Utils.FromJson<ServerStatistics>(result);
}
//public void LoadFromFile()
//{
// try
// {
// string result = Utils.LoadResource(Utils.GetConfigPath(Global.StatisticLogOverall));
// if (!Utils.IsNullOrEmpty(result))
// {
// serverStatistics_ = Utils.FromJson<ServerStatistics>(result);
// }
if (serverStatistics_ == null)
{
serverStatistics_ = new ServerStatistics();
}
if (serverStatistics_.profileStat == null)
{
serverStatistics_.profileStat = new List<ProfileStatItem>();
}
// if (serverStatistics_ == null)
// {
// serverStatistics_ = new ServerStatistics();
// }
// if (serverStatistics_.profileStat == null)
// {
// serverStatistics_.profileStat = new List<ProfileStatItem>();
// }
long ticks = DateTime.Now.Date.Ticks;
foreach (ProfileStatItem item in serverStatistics_.profileStat)
{
if (item.dateNow != ticks)
{
item.todayUp = 0;
item.todayDown = 0;
item.dateNow = ticks;
}
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
}
}
// long ticks = DateTime.Now.Date.Ticks;
// foreach (ProfileStatItem item in serverStatistics_.profileStat)
// {
// if (item.dateNow != ticks)
// {
// item.todayUp = 0;
// item.todayDown = 0;
// item.dateNow = ticks;
// }
// }
// }
// catch (Exception ex)
// {
// Utils.SaveLog(ex.Message, ex);
// }
//}
public void SaveToFile()
{
try
{
Utils.ToJsonFile(serverStatistics_, Utils.GetConfigPath(Global.StatisticLogOverall));
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
}
}
//public void SaveToFile()
//{
// try
// {
// Utils.ToJsonFile(serverStatistics_, Utils.GetConfigPath(Global.StatisticLogOverall));
// }
// catch (Exception ex)
// {
// Utils.SaveLog(ex.Message, ex);
// }
//}
public void ClearAllServerStatistics()
{
if (serverStatistics_ != null)
{
foreach (var item in serverStatistics_.profileStat)
{
item.todayUp = 0;
item.todayDown = 0;
item.totalUp = 0;
item.totalDown = 0;
// update ui display to zero
updateFunc_(0, 0, new List<ProfileStatItem> { item });
}
//public void ClearAllServerStatistics()
//{
// if (serverStatistics_ != null)
// {
// foreach (var item in serverStatistics_.profileStat)
// {
// item.todayUp = 0;
// item.todayDown = 0;
// item.totalUp = 0;
// item.totalDown = 0;
// // update ui display to zero
// updateFunc_(0, 0);
// }
// update statistic json file
SaveToFile();
}
}
// // update statistic json file
// //SaveToFile();
// }
//}
public List<ProfileStatItem> GetStatistic()
{
return Statistic;
}
//public List<ProfileStatItem> GetStatistic()
//{
// return Statistic;
//}
private ProfileStatItem GetServerStatItem(string itemId)
{
long ticks = DateTime.Now.Date.Ticks;
int cur = Statistic.FindIndex(item => item.indexId == itemId);
if (cur < 0)
{
Statistic.Add(new ProfileStatItem
{
indexId = itemId,
totalUp = 0,
totalDown = 0,
todayUp = 0,
todayDown = 0,
dateNow = ticks
});
cur = Statistic.Count - 1;
}
if (Statistic[cur].dateNow != ticks)
{
Statistic[cur].todayUp = 0;
Statistic[cur].todayDown = 0;
Statistic[cur].dateNow = ticks;
}
return Statistic[cur];
}
//private ProfileStatItem GetServerStatItem(string itemId)
//{
// long ticks = DateTime.Now.Date.Ticks;
// int cur = Statistic.FindIndex(item => item.indexId == itemId);
// if (cur < 0)
// {
// Statistic.Add(new ProfileStatItem
// {
// indexId = itemId,
// totalUp = 0,
// totalDown = 0,
// todayUp = 0,
// todayDown = 0,
// dateNow = ticks
// });
// cur = Statistic.Count - 1;
// }
// if (Statistic[cur].dateNow != ticks)
// {
// Statistic[cur].todayUp = 0;
// Statistic[cur].todayDown = 0;
// Statistic[cur].dateNow = ticks;
// }
// return Statistic[cur];
//}
private void ParseOutput(string source, out ulong up, out ulong down)
{

View File

@@ -3,6 +3,7 @@ using clashN.Mode;
using clashN.Resx;
using System.Diagnostics;
using System.IO;
using System.Net.Http.Headers;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
@@ -211,27 +212,56 @@ namespace clashN.Handler
_updateFunc(false, $"{hashCode}{args.GetException().Message}");
};
var result = await downloadHandle.DownloadStringAsync(url, blProxy, userAgent);
if (blProxy && Utils.IsNullOrEmpty(result))
if (blProxy && Utils.IsNullOrEmpty(result.Item1))
{
result = await downloadHandle.DownloadStringAsync(url, false, userAgent);
}
if (Utils.IsNullOrEmpty(result))
if (Utils.IsNullOrEmpty(result.Item1))
{
_updateFunc(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
}
else
{
_updateFunc(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
if (result.Length < 99)
if (result.Item1.Length < 99)
{
_updateFunc(false, $"{hashCode}{result}");
}
int ret = ConfigHandler.AddBatchProfiles(ref config, result, indexId, groupId);
int ret = ConfigHandler.AddBatchProfiles(ref config, result.Item1, indexId, groupId);
if (ret == 0)
{
item.updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds();
//get remote info
try
{
if (result.Item2 != null && result.Item2 is HttpResponseHeaders)
{
var userinfo = ((HttpResponseHeaders)result.Item2)
.Where(t => t.Key == "subscription-userinfo")
.Select(t => t.Value)
.FirstOrDefault()?
.FirstOrDefault();
Dictionary<string, string>? dicInfo = userinfo?.Split(';')
.Select(value => value.Split('='))
.ToDictionary(pair => pair[0].Trim(), pair => pair[1].Trim());
if (dicInfo != null)
{
item.uploadRemote = ParseRemoteInfo(dicInfo, "upload");
item.downloadRemote = ParseRemoteInfo(dicInfo, "download");
item.totalRemote = ParseRemoteInfo(dicInfo, "total");
item.expireRemote = dicInfo.ContainsKey("expire") ? Convert.ToInt64(dicInfo?["expire"]) : 0;
}
}
}
catch (Exception ex)
{
_updateFunc(false, ex.Message);
}
_updateFunc(false, $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}");
}
else
@@ -251,7 +281,10 @@ namespace clashN.Handler
_updateFunc(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
});
}
private ulong ParseRemoteInfo(Dictionary<string, string> dicInfo, string key)
{
return dicInfo.ContainsKey(key) ? Convert.ToUInt64(dicInfo?[key]) : 0;
}
public void UpdateGeoFile(string geoName, Config config, Action<bool, string> update)
{

View File

@@ -150,7 +150,7 @@ namespace clashN.Mode
{
get { return !address.IsNullOrEmpty(); }
}
public string HasUpdateTime
public string StrUpdateTime
{
get
{
@@ -159,9 +159,30 @@ namespace clashN.Mode
return String.Empty;
}
var dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
return dateTime.AddSeconds(updateTime).ToLocalTime().ToString("MM/dd HH:mm");
return dateTime.AddSeconds(updateTime).ToLocalTime().ToString("MM-dd HH:mm");
}
}
public string TrafficUsed
{
get { return Utils.HumanFy(uploadRemote + downloadRemote); }
}
public string TrafficTotal
{
get { return totalRemote <= 0 ? "∞" : Utils.HumanFy(totalRemote); }
}
public string StrExpireTime
{
get
{
if (expireRemote <= 0)
{
return String.Empty;
}
var dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
return dateTime.AddSeconds(expireRemote).ToLocalTime().ToString("yyyy-MM-dd");
}
}
#endregion
@@ -216,7 +237,10 @@ namespace clashN.Mode
public bool enableConvert { get; set; }
public long updateTime { get; set; }
public ulong uploadRemote { get; set; }
public ulong downloadRemote { get; set; }
public ulong totalRemote { get; set; }
public long expireRemote { get; set; }
}
[Serializable]

View File

@@ -3,22 +3,5 @@
public class ProfileItemModel : ProfileItem
{
public bool isActive { get; set; }
public string totalUp
{
get; set;
}
public string totalDown
{
get; set;
}
public string todayUp
{
get; set;
}
public string todayDown
{
get; set;
}
}
}

View File

@@ -200,7 +200,7 @@ namespace clashN.ViewModels
StorageUI();
ConfigHandler.SaveConfig(ref _config);
statistics?.SaveToFile();
//statistics?.SaveToFile();
statistics?.Close();
}
catch { }
@@ -271,7 +271,7 @@ namespace clashN.ViewModels
await LoadCore();
}
}
private void UpdateStatisticsHandler(ulong up, ulong down, List<ProfileStatItem> statistics)
private void UpdateStatisticsHandler(ulong up, ulong down)
{
try
{
@@ -291,15 +291,6 @@ namespace clashN.ViewModels
Utils.SaveLog(ex.Message, ex);
}
}
public void ClearAllServerStatistics()
{
statistics?.ClearAllServerStatistics();
}
public List<ProfileStatItem>? GetAllServerStatistic()
{
return statistics?.GetStatistic();
}
#endregion
#region Core
@@ -319,7 +310,7 @@ namespace clashN.ViewModels
Global.reloadCore = false;
ConfigHandler.SaveConfig(ref _config, false);
statistics?.SaveToFile();
//statistics?.SaveToFile();
ChangePACButtonStatus(_config.sysProxyType);
SetRuleMode(_config.ruleMode);
@@ -332,7 +323,7 @@ namespace clashN.ViewModels
public void CloseCore()
{
ConfigHandler.SaveConfig(ref _config, false);
statistics?.SaveToFile();
//statistics?.SaveToFile();
ChangePACButtonStatus(ESysProxyType.ForcedClear);
@@ -450,7 +441,7 @@ namespace clashN.ViewModels
if (_config.uiItem.mainWidth > 0 && _config.uiItem.mainHeight > 0)
{
if(_config.uiItem.mainWidth > SystemInformation.WorkingArea.Width)
if (_config.uiItem.mainWidth > SystemInformation.WorkingArea.Width)
{
_config.uiItem.mainWidth = SystemInformation.WorkingArea.Width * 2 / 3;
}

View File

@@ -128,7 +128,8 @@ namespace clashN.ViewModels
ClearStatisticCmd = ReactiveCommand.Create(() =>
{
Locator.Current.GetService<MainWindowViewModel>()?.ClearAllServerStatistics();
ConfigHandler.ClearAllServerStatistics(ref _config);
RefreshProfiles();
});
ProfileReloadCmd = ReactiveCommand.Create(() =>
{
@@ -320,22 +321,10 @@ namespace clashN.ViewModels
ConfigHandler.SetDefaultProfile(_config, _config.profileItems);
var lstModel = new List<ProfileItemModel>();
var statistic = Locator.Current.GetService<MainWindowViewModel>()?.GetAllServerStatistic();
foreach (var item in _config.profileItems)
{
var model = Utils.FromJson<ProfileItemModel>(Utils.ToJson(item));
model.isActive = _config.IsActiveNode(item);
if (statistic != null)
{
var statOne = statistic.Where(t => t.indexId == item.indexId).FirstOrDefault();
if (statOne != null)
{
model.todayUp = Utils.HumanFy(statOne.todayUp);
model.todayDown = Utils.HumanFy(statOne.todayDown);
model.totalUp = Utils.HumanFy(statOne.totalUp);
model.totalDown = Utils.HumanFy(statOne.totalDown);
}
}
lstModel.Add(model);
}

View File

@@ -142,7 +142,7 @@
IsHitTestVisible="False"
Style="{StaticResource ListItemCheckBox}" />
<TextBlock Style="{StaticResource ListItemSubTitle}" Text="{Binding HasUpdateTime}" />
<TextBlock Style="{StaticResource ListItemSubTitle}" Text="{Binding StrUpdateTime}" />
</StackPanel>
@@ -152,20 +152,25 @@
Grid.Row="4"
Margin="8,0,8,8"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal">
<materialDesign:PackIcon Padding="4,0,4,0" Kind="ArrowUpThin" />
<materialDesign:PackIcon Kind="ChartDonut" />
<TextBlock
Padding="4,0,4,0"
Style="{StaticResource ListItemSubTitle}"
Text="{Binding totalUp}" />
<materialDesign:PackIcon
Margin="8,0,0,0"
Padding="4,0,4,0"
Kind="ArrowDownThin" />
Text="{Binding TrafficUsed}" />
<TextBlock
Padding="4,0,4,0"
Style="{StaticResource ListItemSubTitle}"
Text="{Binding totalDown}" />
Text="/" />
<TextBlock
Padding="4,0,4,0"
Style="{StaticResource ListItemSubTitle}"
Text="{Binding TrafficTotal}" />
<TextBlock
Padding="4,0,4,0"
Style="{StaticResource ListItemSubTitle}"
Text="{Binding StrExpireTime}" />
</StackPanel>
</Grid>

View File

@@ -36,6 +36,7 @@
<ComboBox
x:Name="cmbSwatches"
Width="100"
Margin="8"
DisplayMemberPath="Name"
Style="{StaticResource DefComboBox}" />
<Separator />
@@ -46,6 +47,7 @@
<ComboBox
x:Name="cmbCurrentLanguage"
Width="100"
Margin="8"
materialDesign:HintAssist.Hint="Language"
Style="{StaticResource DefComboBox}" />