mirror of
https://github.com/netchx/netch.git
synced 2026-05-07 22:44:03 +08:00
实现WebUtil
Beta 更新检查 订阅更新异常提示
This commit is contained in:
@@ -1,19 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models.GitHubRelease;
|
||||
using Netch.Utils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class UpdateChecker
|
||||
{
|
||||
private const string DefaultUserAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36";
|
||||
|
||||
private const int DefaultGetTimeout = 30000;
|
||||
|
||||
public const string Owner = @"NetchX";
|
||||
public const string Repo = @"Netch";
|
||||
|
||||
@@ -28,14 +24,14 @@ namespace Netch.Controllers
|
||||
public event EventHandler NewVersionFoundFailed;
|
||||
public event EventHandler NewVersionNotFound;
|
||||
|
||||
public async void Check(bool notifyNoFound, bool isPreRelease)
|
||||
public void Check(bool notifyNoFound, bool isPreRelease)
|
||||
{
|
||||
try
|
||||
{
|
||||
var updater = new GitHubRelease(Owner, Repo);
|
||||
var url = updater.AllReleaseUrl;
|
||||
|
||||
var json = await GetAsync(url, true);
|
||||
var json = WebUtil.DownloadString(WebUtil.CreateRequest(url));
|
||||
|
||||
var releases = JsonConvert.DeserializeObject<List<Release>>(json);
|
||||
var latestRelease = VersionUtil.GetLatestRelease(releases, isPreRelease);
|
||||
@@ -53,29 +49,9 @@ namespace Netch.Controllers
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.ToString());
|
||||
Logging.Error(e.ToString());
|
||||
if (notifyNoFound) NewVersionFoundFailed?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<string> GetAsync(string url, bool useProxy, string userAgent = @"", double timeout = DefaultGetTimeout)
|
||||
{
|
||||
var httpClientHandler = new HttpClientHandler
|
||||
{
|
||||
UseProxy = useProxy
|
||||
};
|
||||
var httpClient = new HttpClient(httpClientHandler)
|
||||
{
|
||||
Timeout = TimeSpan.FromMilliseconds(timeout)
|
||||
};
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
request.Headers.Add(@"User-Agent", string.IsNullOrWhiteSpace(userAgent) ? DefaultUserAgent : userAgent);
|
||||
|
||||
var response = await httpClient.SendAsync(request);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
var resultStr = await response.Content.ReadAsStringAsync();
|
||||
return resultStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,12 +77,7 @@ namespace Netch.Forms
|
||||
if (_isFirstCloseWindow)
|
||||
{
|
||||
// 显示提示语
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
i18N.Translate(
|
||||
"Netch is now minimized to the notification bar, double click this icon to restore."),
|
||||
ToolTipIcon.Info);
|
||||
|
||||
NotifyTip(i18N.Translate("Netch is now minimized to the notification bar, double click this icon to restore."));
|
||||
_isFirstCloseWindow = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
@@ -10,7 +12,6 @@ using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using Trojan = Netch.Forms.Server.Trojan;
|
||||
using VMess = Netch.Forms.Server.VMess;
|
||||
using WebClient = Netch.Override.WebClient;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
@@ -97,31 +98,20 @@ namespace Netch.Forms
|
||||
|
||||
private void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var bak_State = State;
|
||||
var bak_StateText = StatusLabel.Text;
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1)
|
||||
Global.Settings.UseProxyToUpdateSubscription = false;
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
// 当前 ServerComboBox 中至少有一项
|
||||
if (ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = false;
|
||||
ControlButton.Text = "...";
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Global.Settings.SubscribeLink.Count > 0)
|
||||
{
|
||||
StatusText(i18N.Translate("Starting update subscription"));
|
||||
DeleteServerPictureBox.Enabled = false;
|
||||
|
||||
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = false;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
@@ -131,96 +121,72 @@ namespace Netch.Forms
|
||||
Remark = "ProxyUpdate",
|
||||
Type = 5
|
||||
};
|
||||
_mainController = new MainController();
|
||||
_mainController.Start(ServerComboBox.SelectedItem as Models.Server, mode);
|
||||
State = State.Starting;
|
||||
if (_mainController.Start(ServerComboBox.SelectedItem as Models.Server, mode))
|
||||
StatusText(i18N.Translate("Starting update subscription"));
|
||||
}
|
||||
else
|
||||
StatusText(i18N.Translate("Starting update subscription"));
|
||||
|
||||
foreach (var item in Global.Settings.SubscribeLink)
|
||||
Task.WaitAll(Global.Settings.SubscribeLink.Select(item => Task.Factory.StartNew(() =>
|
||||
{
|
||||
using var client = new WebClient();
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.UserAgent))
|
||||
{
|
||||
client.Headers.Add("User-Agent", item.UserAgent);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36");
|
||||
}
|
||||
var request = WebUtil.CreateRequest(item.Link);
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
{
|
||||
client.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(item.UserAgent)) request.UserAgent = item.UserAgent;
|
||||
if (Global.Settings.UseProxyToUpdateSubscription) request.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
|
||||
var response = client.DownloadString(item.Link);
|
||||
var str = WebUtil.DownloadString(request);
|
||||
|
||||
try
|
||||
{
|
||||
response = ShareLink.URLSafeBase64Decode(response);
|
||||
str = ShareLink.URLSafeBase64Decode(str);
|
||||
}
|
||||
catch (Exception)
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
Global.Settings.Server = Global.Settings.Server.Where(server => server.Group != item.Remark).ToList();
|
||||
var result = ShareLink.Parse(response);
|
||||
var result = ShareLink.Parse(str);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
foreach (var x in result)
|
||||
{
|
||||
x.Group = item.Remark;
|
||||
}
|
||||
foreach (var x in result) x.Group = item.Remark;
|
||||
|
||||
Global.Settings.Server.AddRange(result);
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
string.Format(i18N.Translate("Update {1} server(s) from {0}"), item.Remark, result.Count),
|
||||
ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
string.Format(i18N.Translate("Update servers error from {0}"), item.Remark),
|
||||
ToolTipIcon.Error);
|
||||
NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, result.Count));
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
catch (WebException e)
|
||||
{
|
||||
NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false);
|
||||
}
|
||||
}
|
||||
})).ToArray());
|
||||
|
||||
InitServer();
|
||||
DeleteServerPictureBox.Enabled = true;
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
{
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true;
|
||||
ControlButton.Text = i18N.Translate("Start");
|
||||
_mainController.Stop();
|
||||
NatTypeStatusLabel.Text = "";
|
||||
}
|
||||
|
||||
Configuration.Save();
|
||||
StatusText(i18N.Translate("Subscription updated"));
|
||||
NotifyTip(i18N.Translate("Subscription updated"));
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
{
|
||||
_mainController.Stop();
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
State = State.Waiting;
|
||||
DeleteModePictureBox.Enabled = true;
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true;
|
||||
State = bak_State;
|
||||
StatusLabel.Text = bak_StateText;
|
||||
}).ContinueWith(task => { BeginInvoke(new Action(() => { UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = true; })); });
|
||||
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = true;
|
||||
});
|
||||
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
i18N.Translate("Updating in the background"),
|
||||
ToolTipIcon.Info);
|
||||
NotifyTip(i18N.Translate("Updating in the background"));
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("No subscription link"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +194,98 @@ namespace Netch.Forms
|
||||
|
||||
#region 选项
|
||||
|
||||
private void OpenDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Utils.Utils.Open(".\\");
|
||||
}
|
||||
|
||||
private void CleanDNSCacheToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
DNS.Cache.Clear();
|
||||
NotifyTip(i18N.Translate("DNS cache cleanup succeeded"));
|
||||
});
|
||||
}
|
||||
|
||||
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
SaveConfigs();
|
||||
Task.Run(() =>
|
||||
{
|
||||
InitMode();
|
||||
|
||||
NotifyTip(i18N.Translate("Modes have been reload"));
|
||||
Enabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void updateACLWithProxyToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
UpdateACL(true, sender);
|
||||
}
|
||||
|
||||
private void updateACLToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
UpdateACL(false, sender);
|
||||
}
|
||||
|
||||
private void UpdateACL(bool useProxy, object sender)
|
||||
{
|
||||
if (useProxy && ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
((ToolStripMenuItem) sender).Enabled = false;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
if (useProxy)
|
||||
{
|
||||
var mode = new Models.Mode
|
||||
{
|
||||
Remark = "ProxyUpdate",
|
||||
Type = 5
|
||||
};
|
||||
State = State.Starting;
|
||||
if (_mainController.Start(ServerComboBox.SelectedItem as Models.Server, mode))
|
||||
StatusText(i18N.Translate("Updating in the background"));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var req = WebUtil.CreateRequest(Global.Settings.ACL);
|
||||
if (useProxy)
|
||||
req.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
|
||||
await WebUtil.DownloadFileAsync(req, Path.Combine(Global.NetchDir, "bin\\default.acl"));
|
||||
NotifyTip(i18N.Translate("ACL updated successfully"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
NotifyTip(i18N.Translate("ACL update failed") + "\n" + e.Message, info: false);
|
||||
Logging.Error("更新 ACL 失败!" + e);
|
||||
if (!(e is WebException))
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
((ToolStripMenuItem) sender).Enabled = true;
|
||||
if (useProxy)
|
||||
{
|
||||
_mainController.Stop();
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
State = State.Waiting;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
@@ -244,52 +302,15 @@ namespace Netch.Forms
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBoxX.Show(e.ToString(),LogLevel.ERROR);
|
||||
MessageBoxX.Show(e.ToString(), LogLevel.ERROR);
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
|
||||
Enabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
SaveConfigs();
|
||||
Task.Run(() =>
|
||||
{
|
||||
InitMode();
|
||||
|
||||
MessageBoxX.Show(i18N.Translate("Modes have been reload"), owner: this);
|
||||
Enabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void CleanDNSCacheToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var bak_State = State;
|
||||
var bak_StateText = StatusLabel.Text;
|
||||
|
||||
try
|
||||
{
|
||||
Enabled = false;
|
||||
DNS.Cache.Clear();
|
||||
|
||||
MessageBoxX.Show(i18N.Translate("DNS cache cleanup succeeded"), owner: this);
|
||||
StatusText(i18N.Translate("DNS cache cleanup succeeded"));
|
||||
Enabled = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
State = bak_State;
|
||||
StatusLabel.Text = bak_StateText;
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Utils.Utils.Open(@".\");
|
||||
}
|
||||
|
||||
private void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Task.Run(() =>
|
||||
@@ -300,15 +321,11 @@ namespace Netch.Forms
|
||||
{
|
||||
Configuration.deltapall();
|
||||
Configuration.addtap();
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name, i18N.Translate("Reinstall TUN/TAP driver successfully"),
|
||||
ToolTipIcon.Info);
|
||||
NotifyTip(i18N.Translate("Reinstall TUN/TAP driver successfully"));
|
||||
}
|
||||
catch
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name, i18N.Translate("Reinstall TUN/TAP driver failed"),
|
||||
ToolTipIcon.Error);
|
||||
NotifyTip(i18N.Translate("Reinstall TUN/TAP driver failed"), info: false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -318,56 +335,6 @@ namespace Netch.Forms
|
||||
});
|
||||
}
|
||||
|
||||
private void updateACLWithProxyToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
updateACLWithProxyToolStripMenuItem.Enabled = false;
|
||||
|
||||
// 当前 ServerComboBox 中至少有一项
|
||||
if (ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = false;
|
||||
ControlButton.Text = "...";
|
||||
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var mode = new Models.Mode
|
||||
{
|
||||
Remark = "ProxyUpdate",
|
||||
Type = 5
|
||||
};
|
||||
_mainController = new MainController();
|
||||
_mainController.Start(ServerComboBox.SelectedItem as Models.Server, mode);
|
||||
|
||||
using var client = new WebClient();
|
||||
|
||||
client.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
|
||||
StatusText(i18N.Translate("Updating in the background"));
|
||||
try
|
||||
{
|
||||
client.DownloadFile(Global.Settings.ACL, "bin\\default.acl");
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name, i18N.Translate("ACL updated successfully"),
|
||||
ToolTipIcon.Info);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error("使用代理更新 ACL 失败!" + e);
|
||||
MessageBoxX.Show(i18N.Translate("ACL update failed") + "\n" + e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
State = State.Waiting;
|
||||
_mainController.Stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -378,12 +345,12 @@ namespace Netch.Forms
|
||||
|
||||
private void RelyToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
System.Diagnostics.Process.Start("https://mega.nz/file/9OQ1EazJ#0pjJ3xt57AVLr29vYEEv15GSACtXVQOGlEOPpi_2Ico");
|
||||
Utils.Utils.Open("https://mega.nz/file/9OQ1EazJ#0pjJ3xt57AVLr29vYEEv15GSACtXVQOGlEOPpi_2Ico");
|
||||
}
|
||||
|
||||
private void VersionLabel_Click(object sender, EventArgs e)
|
||||
{
|
||||
System.Diagnostics.Process.Start($"https://github.com/{UpdateChecker.Owner}/{UpdateChecker.Repo}/releases");
|
||||
Utils.Utils.Open($"https://github.com/{UpdateChecker.Owner}/{UpdateChecker.Repo}/releases");
|
||||
}
|
||||
|
||||
private void AboutToolStripButton_Click(object sender, EventArgs e)
|
||||
@@ -392,39 +359,6 @@ namespace Netch.Forms
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void updateACLToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var bak_State = State;
|
||||
var bak_StateText = StatusLabel.Text;
|
||||
|
||||
StatusText(i18N.Translate("Starting update ACL"));
|
||||
using var client = new WebClient();
|
||||
|
||||
client.DownloadFileTaskAsync(Global.Settings.ACL, "bin\\default.acl");
|
||||
client.DownloadFileCompleted += ((sender, args) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (args.Error == null)
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name, i18N.Translate("ACL updated successfully"),
|
||||
ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Error("ACL 更新失败!" + args.Error);
|
||||
MessageBoxX.Show(i18N.Translate("ACL update failed") + "\n" + args.Error);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
State = bak_State;
|
||||
StatusLabel.Text = bak_StateText;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Controllers;
|
||||
using Netch.Utils;
|
||||
|
||||
@@ -11,22 +11,18 @@ namespace Netch.Forms
|
||||
/// <summary lang="zh">
|
||||
/// 此类用于禁用设计器
|
||||
/// </summary>
|
||||
[DesignerCategory("")] public partial class Dummy { }
|
||||
[DesignerCategory("")]
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
private void CheckUpdate()
|
||||
{
|
||||
var updater = new UpdateChecker();
|
||||
updater.NewVersionFound += (o, args) =>
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
$"{i18N.Translate(@"New version available",": ")}{updater.LatestVersionNumber}",
|
||||
ToolTipIcon.Info);
|
||||
};
|
||||
updater.Check(false, false);
|
||||
updater.NewVersionFound += (o, args) => { NotifyTip($"{i18N.Translate(@"New version available", ": ")}{updater.LatestVersionNumber}"); };
|
||||
updater.Check(false, Global.Settings.CheckBetaUpdate);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,11 @@ namespace Netch.Forms
|
||||
// 加载快速配置
|
||||
InitProfile();
|
||||
|
||||
// 打开软件时启动加速,产生开始按钮点击事件
|
||||
if (Global.Settings.StartWhenOpened)
|
||||
{
|
||||
ControlButton.PerformClick();
|
||||
}
|
||||
|
||||
// 自动检测延迟
|
||||
Task.Run(() =>
|
||||
@@ -92,17 +97,14 @@ namespace Netch.Forms
|
||||
}
|
||||
});
|
||||
|
||||
// 打开软件时启动加速,产生开始按钮点击事件
|
||||
if (Global.Settings.StartWhenOpened)
|
||||
Task.Run(() =>
|
||||
{
|
||||
ControlButton.PerformClick();
|
||||
}
|
||||
|
||||
// 检查更新
|
||||
if (Global.Settings.CheckUpdateWhenOpened)
|
||||
{
|
||||
CheckUpdate();
|
||||
}
|
||||
// 检查更新
|
||||
if (Global.Settings.CheckUpdateWhenOpened)
|
||||
{
|
||||
CheckUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -122,11 +124,7 @@ namespace Netch.Forms
|
||||
if (_isFirstCloseWindow)
|
||||
{
|
||||
// 显示提示语
|
||||
NotifyIcon.ShowBalloonTip(5,
|
||||
UpdateChecker.Name,
|
||||
i18N.Translate("Netch is now minimized to the notification bar, double click this icon to restore."),
|
||||
ToolTipIcon.Info);
|
||||
|
||||
NotifyTip(i18N.Translate("Netch is now minimized to the notification bar, double click this icon to restore."));
|
||||
_isFirstCloseWindow = false;
|
||||
}
|
||||
|
||||
@@ -451,6 +449,14 @@ namespace Netch.Forms
|
||||
Activate();
|
||||
}
|
||||
|
||||
private void NotifyTip(string text, int timeout = 5, bool info = true)
|
||||
{
|
||||
NotifyIcon.ShowBalloonTip(timeout,
|
||||
UpdateChecker.Name,
|
||||
text,
|
||||
info ? ToolTipIcon.Info : ToolTipIcon.Error);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
54
Netch/Forms/SettingForm.Designer.cs
generated
54
Netch/Forms/SettingForm.Designer.cs
generated
@@ -54,6 +54,7 @@
|
||||
this.BehaviorGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.LanguageLabel = new System.Windows.Forms.Label();
|
||||
this.LanguageComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.ModifySystemDNSCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.BootShadowsocksFromDLLCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.AclAddrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.AclLabel = new System.Windows.Forms.Label();
|
||||
@@ -68,11 +69,11 @@
|
||||
this.MinimizeWhenStartedCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ProfileCountLabel = new System.Windows.Forms.Label();
|
||||
this.ProfileCountTextBox = new System.Windows.Forms.TextBox();
|
||||
this.CheckBetaUpdateCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.CheckUpdateWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.StartWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.StopWhenExitedCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ExitWhenClosedCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ModifySystemDNSCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.PortGroupBox.SuspendLayout();
|
||||
this.TUNTAPGroupBox.SuspendLayout();
|
||||
this.BehaviorGroupBox.SuspendLayout();
|
||||
@@ -316,6 +317,7 @@
|
||||
this.BehaviorGroupBox.Controls.Add(this.MinimizeWhenStartedCheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.ProfileCountLabel);
|
||||
this.BehaviorGroupBox.Controls.Add(this.ProfileCountTextBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.CheckBetaUpdateCheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.CheckUpdateWhenOpenedCheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.StartWhenOpenedCheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.StopWhenExitedCheckBox);
|
||||
@@ -345,17 +347,27 @@
|
||||
this.LanguageComboBox.Size = new System.Drawing.Size(121, 25);
|
||||
this.LanguageComboBox.TabIndex = 22;
|
||||
//
|
||||
// ModifySystemDNSCheckBox
|
||||
//
|
||||
this.ModifySystemDNSCheckBox.AutoSize = true;
|
||||
this.ModifySystemDNSCheckBox.Location = new System.Drawing.Point(12, 129);
|
||||
this.ModifySystemDNSCheckBox.Name = "ModifySystemDNSCheckBox";
|
||||
this.ModifySystemDNSCheckBox.Size = new System.Drawing.Size(143, 21);
|
||||
this.ModifySystemDNSCheckBox.TabIndex = 21;
|
||||
this.ModifySystemDNSCheckBox.Text = "Modify System DNS";
|
||||
this.ModifySystemDNSCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// BootShadowsocksFromDLLCheckBox
|
||||
//
|
||||
this.BootShadowsocksFromDLLCheckBox.AutoSize = true;
|
||||
this.BootShadowsocksFromDLLCheckBox.Location = new System.Drawing.Point(12, 102);
|
||||
this.BootShadowsocksFromDLLCheckBox.Name = "BootShadowsocksFromDLLCheckBox";
|
||||
this.BootShadowsocksFromDLLCheckBox.Size = new System.Drawing.Size(321, 21);
|
||||
this.BootShadowsocksFromDLLCheckBox.Size = new System.Drawing.Size(168, 21);
|
||||
this.BootShadowsocksFromDLLCheckBox.TabIndex = 21;
|
||||
this.BootShadowsocksFromDLLCheckBox.Text = "Start Shadowsocks from DLL (No support for ACL)";
|
||||
this.BootShadowsocksFromDLLCheckBox.Text = "SS DLL(No ACL support)";
|
||||
this.BootShadowsocksFromDLLCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// AclAddr
|
||||
// AclAddrTextBox
|
||||
//
|
||||
this.AclAddrTextBox.Location = new System.Drawing.Point(120, 273);
|
||||
this.AclAddrTextBox.Name = "AclAddrTextBox";
|
||||
@@ -372,7 +384,7 @@
|
||||
this.AclLabel.TabIndex = 20;
|
||||
this.AclLabel.Text = "Custom ACL";
|
||||
//
|
||||
// DetectionInterval_Label
|
||||
// DetectionIntervalLabel
|
||||
//
|
||||
this.DetectionIntervalLabel.AutoSize = true;
|
||||
this.DetectionIntervalLabel.Location = new System.Drawing.Point(228, 215);
|
||||
@@ -381,7 +393,7 @@
|
||||
this.DetectionIntervalLabel.TabIndex = 18;
|
||||
this.DetectionIntervalLabel.Text = "Detection interval(sec)";
|
||||
//
|
||||
// DetectionInterval_TextBox
|
||||
// DetectionIntervalTextBox
|
||||
//
|
||||
this.DetectionIntervalTextBox.Location = new System.Drawing.Point(366, 212);
|
||||
this.DetectionIntervalTextBox.Name = "DetectionIntervalTextBox";
|
||||
@@ -389,7 +401,7 @@
|
||||
this.DetectionIntervalTextBox.TabIndex = 17;
|
||||
this.DetectionIntervalTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// EnableStartedTcping_CheckBox
|
||||
// TcpingAtStartedCheckBox
|
||||
//
|
||||
this.TcpingAtStartedCheckBox.AutoSize = true;
|
||||
this.TcpingAtStartedCheckBox.Location = new System.Drawing.Point(15, 214);
|
||||
@@ -426,7 +438,7 @@
|
||||
this.STUNServerLabel.TabIndex = 10;
|
||||
this.STUNServerLabel.Text = "STUN Server";
|
||||
//
|
||||
// RunAtStartup
|
||||
// RunAtStartupCheckBox
|
||||
//
|
||||
this.RunAtStartupCheckBox.AutoSize = true;
|
||||
this.RunAtStartupCheckBox.Location = new System.Drawing.Point(12, 75);
|
||||
@@ -454,7 +466,7 @@
|
||||
this.MinimizeWhenStartedCheckBox.Text = "Minimize when started";
|
||||
this.MinimizeWhenStartedCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ProfileCount_Label
|
||||
// ProfileCountLabel
|
||||
//
|
||||
this.ProfileCountLabel.AutoSize = true;
|
||||
this.ProfileCountLabel.Location = new System.Drawing.Point(12, 188);
|
||||
@@ -463,7 +475,7 @@
|
||||
this.ProfileCountLabel.TabIndex = 8;
|
||||
this.ProfileCountLabel.Text = "ProfileCount";
|
||||
//
|
||||
// ProfileCount_TextBox
|
||||
// ProfileCountTextBox
|
||||
//
|
||||
this.ProfileCountTextBox.Location = new System.Drawing.Point(120, 185);
|
||||
this.ProfileCountTextBox.Name = "ProfileCountTextBox";
|
||||
@@ -471,6 +483,17 @@
|
||||
this.ProfileCountTextBox.TabIndex = 9;
|
||||
this.ProfileCountTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// CheckBetaUpdateCheckBox
|
||||
//
|
||||
this.CheckBetaUpdateCheckBox.AutoSize = true;
|
||||
this.CheckBetaUpdateCheckBox.Location = new System.Drawing.Point(206, 102);
|
||||
this.CheckBetaUpdateCheckBox.Name = "CheckBetaUpdateCheckBox";
|
||||
this.CheckBetaUpdateCheckBox.Size = new System.Drawing.Size(137, 21);
|
||||
this.CheckBetaUpdateCheckBox.TabIndex = 8;
|
||||
this.CheckBetaUpdateCheckBox.Text = "Check Beta update";
|
||||
this.CheckBetaUpdateCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.CheckBetaUpdateCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// CheckUpdateWhenOpenedCheckBox
|
||||
//
|
||||
this.CheckUpdateWhenOpenedCheckBox.AutoSize = true;
|
||||
@@ -515,16 +538,6 @@
|
||||
this.ExitWhenClosedCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.ExitWhenClosedCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ModifySystemDNSCheckBox
|
||||
//
|
||||
this.ModifySystemDNSCheckBox.AutoSize = true;
|
||||
this.ModifySystemDNSCheckBox.Location = new System.Drawing.Point(12, 129);
|
||||
this.ModifySystemDNSCheckBox.Name = "ModifySystemDNSCheckBox";
|
||||
this.ModifySystemDNSCheckBox.Size = new System.Drawing.Size(143, 21);
|
||||
this.ModifySystemDNSCheckBox.TabIndex = 21;
|
||||
this.ModifySystemDNSCheckBox.Text = "Modify System DNS";
|
||||
this.ModifySystemDNSCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// SettingForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
@@ -601,5 +614,6 @@
|
||||
private System.Windows.Forms.Label LanguageLabel;
|
||||
private System.Windows.Forms.ComboBox LanguageComboBox;
|
||||
private System.Windows.Forms.CheckBox ModifySystemDNSCheckBox;
|
||||
private System.Windows.Forms.CheckBox CheckBetaUpdateCheckBox;
|
||||
}
|
||||
}
|
||||
@@ -106,6 +106,7 @@ namespace Netch.Forms
|
||||
CheckUpdateWhenOpenedCheckBox.Checked = Global.Settings.CheckUpdateWhenOpened;
|
||||
BootShadowsocksFromDLLCheckBox.Checked = Global.Settings.BootShadowsocksFromDLL;
|
||||
ModifySystemDNSCheckBox.Checked = Global.Settings.ModifySystemDNS;
|
||||
CheckBetaUpdateCheckBox.Checked = Global.Settings.CheckBetaUpdate;
|
||||
|
||||
ProfileCountTextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
TcpingAtStartedCheckBox.Checked = Global.Settings.StartedTcping;
|
||||
@@ -133,6 +134,7 @@ namespace Netch.Forms
|
||||
ControlButton.Text = i18N.Translate(ControlButton.Text);
|
||||
BootShadowsocksFromDLLCheckBox.Text = i18N.Translate(BootShadowsocksFromDLLCheckBox.Text);
|
||||
ModifySystemDNSCheckBox.Text = i18N.Translate(ModifySystemDNSCheckBox.Text);
|
||||
CheckBetaUpdateCheckBox.Text = i18N.Translate(CheckBetaUpdateCheckBox.Text);
|
||||
BehaviorGroupBox.Text = i18N.Translate(BehaviorGroupBox.Text);
|
||||
ExitWhenClosedCheckBox.Text = i18N.Translate(ExitWhenClosedCheckBox.Text);
|
||||
StopWhenExitedCheckBox.Text = i18N.Translate(StopWhenExitedCheckBox.Text);
|
||||
@@ -173,6 +175,7 @@ namespace Netch.Forms
|
||||
Global.Settings.StopWhenExited = StopWhenExitedCheckBox.Checked;
|
||||
Global.Settings.StartWhenOpened = StartWhenOpenedCheckBox.Checked;
|
||||
Global.Settings.CheckUpdateWhenOpened = CheckUpdateWhenOpenedCheckBox.Checked;
|
||||
Global.Settings.CheckBetaUpdate = CheckBetaUpdateCheckBox.Checked;
|
||||
Global.Settings.MinimizeWhenStarted = MinimizeWhenStartedCheckBox.Checked;
|
||||
Global.Settings.RunAtStartup = RunAtStartupCheckBox.Checked;
|
||||
Global.Settings.BootShadowsocksFromDLL = BootShadowsocksFromDLLCheckBox.Checked;
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Netch.Models.GitHubRelease
|
||||
{
|
||||
releases = releases.Where(release => !release.prerelease);
|
||||
}
|
||||
|
||||
releases = releases.Where(release => IsVersionString(release.tag_name));
|
||||
var ordered = releases.OrderByDescending(release => release.tag_name, new VersionComparer());
|
||||
return ordered.ElementAt(0);
|
||||
@@ -19,6 +20,8 @@ namespace Netch.Models.GitHubRelease
|
||||
|
||||
private static bool IsVersionString(string str)
|
||||
{
|
||||
if (Global.Settings.CheckBetaUpdate)
|
||||
str = str.Split('-')[0];
|
||||
return Version.TryParse(str, out _);
|
||||
}
|
||||
|
||||
@@ -27,10 +30,28 @@ namespace Netch.Models.GitHubRelease
|
||||
/// <returns> <0:version2 is greater</returns>
|
||||
public static int CompareVersion(string v1, string v2)
|
||||
{
|
||||
var version1 = new Version(v1);
|
||||
var version2 = new Version(v2);
|
||||
var version1 = ToVersion(v1);
|
||||
var version2 = ToVersion(v2);
|
||||
var res = version1.CompareTo(version2);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static Version ToVersion(string versionStr)
|
||||
{
|
||||
var v = versionStr.Split('-');
|
||||
var version = Version.Parse(v[0]);
|
||||
if (v.Length == 1)
|
||||
return version;
|
||||
var beta = v[1];
|
||||
|
||||
var result = string.Empty;
|
||||
foreach (var c in beta)
|
||||
{
|
||||
if (int.TryParse(c.ToString(), out var n))
|
||||
result += n;
|
||||
}
|
||||
|
||||
return new Version(version.Major, version.Minor, version.Build, int.Parse(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,12 +87,22 @@ namespace Netch.Models
|
||||
/// 是否打开软件时检查更新
|
||||
/// </summary>
|
||||
public bool CheckUpdateWhenOpened = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否检查 Beta 更新
|
||||
/// </summary>
|
||||
public bool CheckBetaUpdate = false;
|
||||
|
||||
/// <summary>
|
||||
/// 修改系统 DNS
|
||||
/// </summary>
|
||||
public bool ModifySystemDNS = false;
|
||||
|
||||
/// <summary>
|
||||
/// 网页请求超时 毫秒
|
||||
/// </summary>
|
||||
public int RequestTimeout = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// 使用何种模式文件名
|
||||
/// 0 为自定义文件名,1 为使用和备注一致的文件名,2 为使用时间数据作为文件名
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Netch.Override
|
||||
{
|
||||
public class WebClient : System.Net.WebClient
|
||||
{
|
||||
protected override WebRequest GetWebRequest(Uri address)
|
||||
{
|
||||
var request = base.GetWebRequest(address);
|
||||
request.Timeout = 10000;
|
||||
((HttpWebRequest)request).ReadWriteTimeout = 10000;
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
"If this is your first time using this software,\n please check https://netch.org to install supports first,\n or the program may report errors.": "如果你是第一次使用本软件,\n请务必前往https://netch.org安装程序所需依赖,\n否则程序将无法正常运行!",
|
||||
"Netch is already running": "Netch 已经在运行中",
|
||||
"Missing File or runtime components": "缺少文件或运行库",
|
||||
|
||||
"Start": "启动",
|
||||
"Stop": "停止",
|
||||
@@ -156,7 +157,8 @@
|
||||
"Global Bypass IPs": "全局直连 IP",
|
||||
"Port value illegal. Try again.": "端口值非法。请重试。",
|
||||
"Check update when opened": "打开软件时检查更新",
|
||||
"Start Shadowsocks from DLL (No support for ACL)": "SS DLL(推荐使用,不支持 ACL)",
|
||||
"Check Beta update": "检查 Beta 更新",
|
||||
"SS DLL(No ACL support)": "SS DLL(不支持 ACL)",
|
||||
"Modify System DNS": "修改系统 DNS",
|
||||
"ProfileCount": "快捷配置数量",
|
||||
"ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试。",
|
||||
|
||||
76
Netch/Utils/WebUtil.cs
Normal file
76
Netch/Utils/WebUtil.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public class WebUtil
|
||||
{
|
||||
private const string DefaultUserAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36";
|
||||
|
||||
private static int DefaultGetTimeout => Global.Settings.RequestTimeout;
|
||||
|
||||
public static HttpWebRequest CreateRequest(string url, int? timeout = null, string userAgent = null)
|
||||
{
|
||||
var req = (HttpWebRequest) WebRequest.Create(url);
|
||||
req.UserAgent = string.IsNullOrEmpty(userAgent) ? DefaultUserAgent : userAgent;
|
||||
req.Accept = "*/*";
|
||||
req.KeepAlive = true;
|
||||
req.Timeout = timeout ?? DefaultGetTimeout;
|
||||
req.ReadWriteTimeout = timeout ?? DefaultGetTimeout;
|
||||
req.Headers.Add("Accept-Charset", "utf-8");
|
||||
return req;
|
||||
}
|
||||
|
||||
/// <param name="req"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="WebException"></exception>
|
||||
public static async Task<string> DownloadStringAsync(HttpWebRequest req)
|
||||
{
|
||||
string content;
|
||||
var response = (HttpWebResponse) await req.GetResponseAsync();
|
||||
using (var responseStream = response.GetResponseStream())
|
||||
{
|
||||
using (var sr = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")))
|
||||
{
|
||||
content = await sr.ReadToEndAsync();
|
||||
}
|
||||
}
|
||||
|
||||
response.Close();
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <param name="req"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="WebException"></exception>
|
||||
public static string DownloadString(HttpWebRequest req)
|
||||
{
|
||||
string content;
|
||||
var response = (HttpWebResponse) req.GetResponse();
|
||||
using (var responseStream = response.GetResponseStream())
|
||||
{
|
||||
using (var sr = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")))
|
||||
{
|
||||
content = sr.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
response.Close();
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <param name="req"></param>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <exception cref="WebException"></exception>
|
||||
public static async Task DownloadFileAsync(HttpWebRequest req, string fileFullPath)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(fileFullPath) ?? throw new ArgumentException();
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
File.WriteAllText(fileFullPath, await DownloadStringAsync(req));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user