@@ -13,12 +13,17 @@ public class DiscordWebhook
1313 {
1414 public string Url { get ; set ; }
1515
16- private UInt64 queueNum = 0 ;
16+ private UInt64 totalMessages = 0 ;
1717 private readonly ConcurrentQueue < ( UInt64 num , DiscordMessage message , FileInfo [ ] files ) > _queue = new ConcurrentQueue < ( UInt64 num , DiscordMessage , FileInfo [ ] ) > ( ) ;
1818 private readonly SemaphoreSlim _semaphore = new SemaphoreSlim ( 1 , 1 ) ;
1919 private bool _isProcessing ;
20+ private CancellationTokenSource _cts = new CancellationTokenSource ( ) ;
2021
21- public async Task SendAsync ( DiscordMessage message , params FileInfo [ ] files )
22+ public UInt64 GetTotalMessages ( ) => totalMessages ;
23+ public int GetQueueSize ( ) => _queue . Count ;
24+ public void CancelProcessing ( ) => _cts . Cancel ( ) ;
25+
26+ public async Task < bool > SendAsync ( DiscordMessage message , params FileInfo [ ] files )
2227 {
2328 if ( string . IsNullOrEmpty ( Url ) )
2429 throw new ArgumentNullException ( "Invalid Webhook URL." ) ;
@@ -54,46 +59,70 @@ public async Task SendAsync(DiscordMessage message, params FileInfo[] files)
5459
5560 try
5661 {
57- var response = await client . PostAsync ( Url , content ) ;
62+ var response = await client . PostAsync ( Url , content , _cts . Token ) ;
5863 response . EnsureSuccessStatusCode ( ) ;
5964 }
6065 catch ( HttpRequestException ex )
6166 {
6267 Debug . WriteLine ( $ "Discord webhook request failed: { ex . Message } ") ;
68+ return false ;
69+ }
70+ catch ( TaskCanceledException ex )
71+ {
72+ Debug . WriteLine ( $ "Discord webhook request cancelled: { ex . Message } ") ;
73+ return false ;
6374 }
6475 }
76+ return true ;
6577 }
6678
6779 private async Task ProcessQueueAsync ( )
6880 {
69- while ( _queue . TryDequeue ( out var item ) )
81+ while ( _queue . TryPeek ( out var item ) )
7082 {
83+ if ( _cts . Token . IsCancellationRequested )
84+ {
85+ Debug . WriteLine ( "Discord queue processing cancelled." ) ;
86+ break ;
87+ }
7188 await _semaphore . WaitAsync ( ) ;
7289 try
7390 {
7491 Debug . WriteLine ( $ "Processing message { item . num } . Queue size: { _queue . Count } ") ;
75- await SendAsync ( item . message , item . files ) ;
76- Debug . WriteLine ( $ "Message { item . num } sent.") ;
92+ if ( await SendAsync ( item . message , item . files ) )
93+ {
94+ _queue . TryDequeue ( out var deqItem ) ;
95+ }
7796 }
7897 finally
7998 {
8099 _semaphore . Release ( ) ;
81100 }
82- Task . Delay ( 500 ) . Wait ( ) ;
101+ try
102+ {
103+ await Task . Delay ( 1000 , _cts . Token ) ; // Discord rate limit: 1 message per second
104+ }
105+ catch ( TaskCanceledException )
106+ {
107+ Debug . WriteLine ( $ "Discord queue processing cancelled during delay. Was { _queue . Count } messages in queue. { totalMessages } messages in session. ") ;
108+ break ;
109+ }
83110 }
84111 _isProcessing = false ;
85112 }
86113
87114 public void Send ( DiscordMessage message , params FileInfo [ ] files )
88115 {
89- _queue . Enqueue ( ( queueNum ++ , message , files ) ) ;
90- Debug . WriteLine ( $ "Message { queueNum - 1 } added. Queue size: { _queue . Count } ") ;
116+ _queue . Enqueue ( ( totalMessages ++ , message , files ) ) ;
117+ Debug . WriteLine ( $ "Message { totalMessages - 1 } added. Queue size: { _queue . Count } ") ;
91118 if ( _isProcessing )
92119 {
93120 Debug . WriteLine ( "Already processing queue." ) ;
94121 return ;
95122 }
96123 Debug . WriteLine ( "Run ProcessQueueAsync" ) ;
124+ _cts . Dispose ( ) ;
125+ _cts = new CancellationTokenSource ( ) ;
97126 _isProcessing = true ;
98127 Task . Run ( ProcessQueueAsync ) ;
99128 }
0 commit comments