mirror of
https://github.com/SlothDpal/Relaunch-Process.git
synced 2026-02-22 17:27:38 +03:00
@@ -47,6 +47,9 @@
|
||||
<setting name="closeFreezeProcess" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="upgradeSettings" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
</RelaunchProcess.Properties.Settings>
|
||||
</userSettings>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup>
|
||||
|
||||
@@ -12,20 +12,33 @@ namespace Discord.Webhook
|
||||
public class DiscordWebhook
|
||||
{
|
||||
public string Url { get; set; }
|
||||
public int queueRetryCount = 3;
|
||||
public int sendTimeoutSeconds = 5;
|
||||
|
||||
private UInt64 queueNum = 0;
|
||||
private readonly ConcurrentQueue<(UInt64 num, DiscordMessage message, FileInfo[] files)> _queue = new ConcurrentQueue<(UInt64 num, DiscordMessage, FileInfo[])>();
|
||||
private UInt64 totalMessages = 0;
|
||||
private ConcurrentQueue<(UInt64 num, DiscordMessage message, FileInfo[] files)> _queue = new ConcurrentQueue<(UInt64 num, DiscordMessage, FileInfo[])>();
|
||||
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
|
||||
private bool _isProcessing;
|
||||
private CancellationTokenSource _cts = new CancellationTokenSource();
|
||||
private int queueErrorCounter = 0;
|
||||
private int queueSuppressedCounter = 0;
|
||||
private HttpRequestException lastHpptEx = null;
|
||||
|
||||
public async Task SendAsync(DiscordMessage message, params FileInfo[] files)
|
||||
public UInt64 TotalMessages => totalMessages;
|
||||
public int QueueSize => _queue.Count;
|
||||
public void CancelProcessing() => _cts.Cancel();
|
||||
public int ErrorCount => queueErrorCounter;
|
||||
public bool IsProcessing => _isProcessing;
|
||||
public HttpRequestException LastHpptEx => lastHpptEx;
|
||||
|
||||
public async Task<bool> SendAsync(DiscordMessage message, params FileInfo[] files)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Url))
|
||||
throw new ArgumentNullException("Invalid Webhook URL.");
|
||||
|
||||
string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
|
||||
|
||||
using (var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(30) })
|
||||
using (var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(sendTimeoutSeconds) })
|
||||
using (var content = new MultipartFormDataContent(boundary))
|
||||
{
|
||||
// Добавляем JSON payload
|
||||
@@ -54,48 +67,96 @@ namespace Discord.Webhook
|
||||
|
||||
try
|
||||
{
|
||||
var response = await client.PostAsync(Url, content);
|
||||
var response = await client.PostAsync(Url, content, _cts.Token);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
Debug.WriteLine($"Discord webhook request failed: {ex.Message}");
|
||||
Debug.WriteLine($"SendAsync: Discord webhook request failed: {ex.Message}");
|
||||
lastHpptEx = ex;
|
||||
return false;
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
Debug.WriteLine($"SendAsync: Discord webhook request cancelled: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task ProcessQueueAsync()
|
||||
{
|
||||
while (_queue.TryDequeue(out var item))
|
||||
queueErrorCounter = 0;
|
||||
|
||||
while (_queue.TryPeek(out var item))
|
||||
{
|
||||
if (_cts.Token.IsCancellationRequested)
|
||||
{
|
||||
Debug.WriteLine("ProcessQueueAsync: Discord queue processing cancelled.");
|
||||
break;
|
||||
}
|
||||
await _semaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
Debug.WriteLine($"Processing message {item.num}. Queue size: {_queue.Count}");
|
||||
await SendAsync(item.message, item.files);
|
||||
Debug.WriteLine($"Message {item.num} sent.");
|
||||
Debug.WriteLine($"ProcessQueueAsync: Processing message {item.num}. Queue size: {_queue.Count}");
|
||||
if (await SendAsync(item.message, item.files))
|
||||
{
|
||||
_queue.TryDequeue(out var deqItem);
|
||||
queueErrorCounter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
queueErrorCounter++;
|
||||
if (queueErrorCounter == queueRetryCount)
|
||||
{
|
||||
_queue.TryDequeue(out var deqItem);
|
||||
queueErrorCounter = 0;
|
||||
queueSuppressedCounter++;
|
||||
Debug.WriteLine($"ProcessQueueAsync: Message dropped. Total messages dropped:{queueSuppressedCounter}. Queue size: {_queue.Count}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
Task.Delay(500).Wait();
|
||||
try
|
||||
{
|
||||
await Task.Delay(1000, _cts.Token); // Discord rate limit: 1 message per second
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
Debug.WriteLine($"ProcessQueueAsync: Discord queue processing cancelled during delay. Was {_queue.Count} messages in queue. {totalMessages} messages in session. ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( _cts.IsCancellationRequested)
|
||||
{
|
||||
Debug.WriteLine($"ProcessQueueAsync: Discord queue processing cancelled. Was {_queue.Count} messages in queue.");
|
||||
Debug.WriteLine("Clearing queue.");
|
||||
var _newqueue = new ConcurrentQueue<(UInt64 num, DiscordMessage, FileInfo[])>();
|
||||
Interlocked.Exchange(ref _queue, _newqueue);
|
||||
}
|
||||
Debug.WriteLine($"ProcessQueueAsync: Discord queue processing finished.");
|
||||
_isProcessing = false;
|
||||
}
|
||||
|
||||
public void Send(DiscordMessage message, params FileInfo[] files)
|
||||
{
|
||||
_queue.Enqueue((queueNum++, message, files));
|
||||
Debug.WriteLine($"Message {queueNum-1} added. Queue size: {_queue.Count}");
|
||||
_queue.Enqueue((totalMessages++, message, files));
|
||||
Debug.WriteLine($"Message {totalMessages-1} added. Queue size: {_queue.Count}");
|
||||
if (_isProcessing)
|
||||
{
|
||||
Debug.WriteLine("Already processing queue.");
|
||||
return;
|
||||
}
|
||||
Debug.WriteLine("Run ProcessQueueAsync");
|
||||
_cts.Dispose();
|
||||
_cts = new CancellationTokenSource();
|
||||
_isProcessing = true;
|
||||
Task.Run(ProcessQueueAsync);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,19 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Process_Auto_Relaunch;
|
||||
using RelaunchProcess.Properties;
|
||||
|
||||
namespace RelaunchProcess
|
||||
{
|
||||
public partial class WebhookSettings : Form
|
||||
{
|
||||
public WebhookSettings()
|
||||
private Form1 parent;
|
||||
|
||||
public WebhookSettings(Form1 _parent)
|
||||
{
|
||||
InitializeComponent();
|
||||
parent = _parent;
|
||||
RestoreSettings();
|
||||
}
|
||||
|
||||
@@ -64,6 +68,10 @@ namespace RelaunchProcess
|
||||
{
|
||||
chbxDiscordEnabled.Checked = false;
|
||||
}
|
||||
if (!chbxDiscordEnabled.Checked)
|
||||
{
|
||||
parent.dwhHook.CancelProcessing();
|
||||
}
|
||||
SaveSettings();
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
|
||||
27
Form1.cs
27
Form1.cs
@@ -15,7 +15,7 @@ using RelaunchProcess;
|
||||
using System.Timers;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using System.Configuration;
|
||||
|
||||
namespace Process_Auto_Relaunch
|
||||
{
|
||||
@@ -32,7 +32,7 @@ namespace Process_Auto_Relaunch
|
||||
}
|
||||
private delegate void UpdateLogDelegate(string text, NotifyLevel level = NotifyLevel.logUpdateStatus);
|
||||
private readonly UpdateLogDelegate updateLogDelegate;
|
||||
private DiscordWebhook dwhHook;
|
||||
public DiscordWebhook dwhHook;
|
||||
private DiscordMessage dwhMessage;
|
||||
private Process WatchedProcess;
|
||||
private double cpuLastTime = 0;
|
||||
@@ -47,6 +47,24 @@ namespace Process_Auto_Relaunch
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
if (Settings.Default.upgradeSettings)
|
||||
{
|
||||
Debug.WriteLine("Обновление настроек.");
|
||||
try
|
||||
{
|
||||
Settings.Default.Upgrade();
|
||||
}
|
||||
catch (ConfigurationErrorsException ex)
|
||||
{
|
||||
Debug.WriteLine($"Ошибка обновления настроек: {ex.Message}");
|
||||
Settings.Default.Reset();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Settings.Default.upgradeSettings = false;
|
||||
Settings.Default.Save();
|
||||
}
|
||||
}
|
||||
this.updateLogDelegate = this.UpdateStatus;
|
||||
this.updateLogDelegate += this.SendDiscordMessage;
|
||||
this.updateLogDelegate += this.HistoryLog;
|
||||
@@ -249,8 +267,9 @@ namespace Process_Auto_Relaunch
|
||||
/// <param name="e"></param>
|
||||
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
Settings.Default.Save();
|
||||
dwhHook.CancelProcessing();
|
||||
Status("Наблюдение отменено - приложение закрыто.", NotifyLevel.logAlways);
|
||||
Settings.Default.Save();
|
||||
}
|
||||
|
||||
private bool ProcessByNameIsRuning(string name)
|
||||
@@ -476,7 +495,7 @@ namespace Process_Auto_Relaunch
|
||||
private void webhookDiscordToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
WebhookSettings discordSettings;
|
||||
discordSettings = new WebhookSettings();
|
||||
discordSettings = new WebhookSettings(this);
|
||||
discordSettings.ShowDialog(this);
|
||||
discordSettings.Dispose();
|
||||
}
|
||||
|
||||
@@ -82,14 +82,11 @@
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="CSharpDiscordWebhook, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>.\CSharpDiscordWebhook.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
||||
@@ -29,7 +29,7 @@ using System.Runtime.InteropServices;
|
||||
// Номер сборки
|
||||
// Редакция
|
||||
//
|
||||
[assembly: AssemblyVersion("1.6.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.6.0.0")]
|
||||
[assembly: AssemblyVersion("1.6.1.2")]
|
||||
[assembly: AssemblyFileVersion("1.6.1.2")]
|
||||
|
||||
[assembly: AssemblyInformationalVersion("1.6.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("1.6.1.2")]
|
||||
16
Properties/Settings.Designer.cs
generated
16
Properties/Settings.Designer.cs
generated
@@ -1,4 +1,4 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Этот код создан программой.
|
||||
// Исполняемая версия:4.0.30319.42000
|
||||
@@ -12,7 +12,7 @@ namespace RelaunchProcess.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -179,5 +179,17 @@ namespace RelaunchProcess.Properties {
|
||||
this["closeFreezeProcess"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool upgradeSettings {
|
||||
get {
|
||||
return ((bool)(this["upgradeSettings"]));
|
||||
}
|
||||
set {
|
||||
this["upgradeSettings"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,5 +41,8 @@
|
||||
<Setting Name="closeFreezeProcess" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="upgradeSettings" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
Reference in New Issue
Block a user