diff --git a/_irc_provider_8cs_source.html b/_irc_provider_8cs_source.html index 3870fd546c..d742cd6ef6 100644 --- a/_irc_provider_8cs_source.html +++ b/_irc_provider_8cs_source.html @@ -257,506 +257,504 @@ $(document).ready(function() { init_codefold(0); });
227 {
228 ArgumentNullException.ThrowIfNull(revisionInformation);
229 ArgumentNullException.ThrowIfNull(engineVersion);
-
230 ArgumentNullException.ThrowIfNull(gitHubOwner);
-
231 ArgumentNullException.ThrowIfNull(gitHubRepo);
-
232
-
233 var commitInsert = revisionInformation.CommitSha![..7];
-
234 string remoteCommitInsert;
-
235 if (revisionInformation.CommitSha == revisionInformation.OriginCommitSha)
-
236 {
-
237 commitInsert = String.Format(CultureInfo.InvariantCulture, localCommitPushed ? "^{0}" : "{0}", commitInsert);
-
238 remoteCommitInsert = String.Empty;
-
239 }
-
240 else
-
241 remoteCommitInsert = String.Format(CultureInfo.InvariantCulture, ". Remote commit: ^{0}", revisionInformation.OriginCommitSha![..7]);
-
242
-
243 var testmergeInsert = (revisionInformation.ActiveTestMerges?.Count ?? 0) == 0
-
244 ? String.Empty
-
245 : String.Format(
-
246 CultureInfo.InvariantCulture,
-
247 " (Test Merges: {0})",
-
248 String.Join(
-
249 ", ",
-
250 revisionInformation
-
251 .ActiveTestMerges!
-
252 .Select(x => x.TestMerge)
-
253 .Select(x =>
-
254 {
-
255 var result = String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.TargetCommitSha![..7]);
-
256 if (x.Comment != null)
-
257 result += String.Format(CultureInfo.InvariantCulture, " ({0})", x.Comment);
-
258 return result;
-
259 })));
-
260
-
261 var prefix = GetEngineCompilerPrefix(engineVersion.Engine!.Value);
-
262 await SendMessage(
-
263 null,
-
264 new MessageContent
-
265 {
-
266 Text = String.Format(
-
267 CultureInfo.InvariantCulture,
-
268 $"{prefix}: Deploying revision: {0}{1}{2} BYOND Version: {3}{4}",
-
269 commitInsert,
-
270 testmergeInsert,
-
271 remoteCommitInsert,
-
272 engineVersion.ToString(),
-
273 estimatedCompletionTime.HasValue
-
274 ? $" ETA: {estimatedCompletionTime - DateTimeOffset.UtcNow}"
-
275 : String.Empty),
-
276 },
-
277 channelId,
-
278 cancellationToken);
-
279
-
280 return async (errorMessage, dreamMakerOutput) =>
-
281 {
-
282 await SendMessage(
-
283 null,
-
284 new MessageContent
-
285 {
-
286 Text = $"{prefix}: Deployment {(errorMessage == null ? "complete" : "failed")}!",
-
287 },
-
288 channelId,
-
289 cancellationToken);
-
290
-
291 return active => ValueTask.CompletedTask;
-
292 };
-
293 }
+
230
+
231 var commitInsert = revisionInformation.CommitSha![..7];
+
232 string remoteCommitInsert;
+
233 if (revisionInformation.CommitSha == revisionInformation.OriginCommitSha)
+
234 {
+
235 commitInsert = String.Format(CultureInfo.InvariantCulture, localCommitPushed ? "^{0}" : "{0}", commitInsert);
+
236 remoteCommitInsert = String.Empty;
+
237 }
+
238 else
+
239 remoteCommitInsert = String.Format(CultureInfo.InvariantCulture, ". Remote commit: ^{0}", revisionInformation.OriginCommitSha![..7]);
+
240
+
241 var testmergeInsert = (revisionInformation.ActiveTestMerges?.Count ?? 0) == 0
+
242 ? String.Empty
+
243 : String.Format(
+
244 CultureInfo.InvariantCulture,
+
245 " (Test Merges: {0})",
+
246 String.Join(
+
247 ", ",
+
248 revisionInformation
+
249 .ActiveTestMerges!
+
250 .Select(x => x.TestMerge)
+
251 .Select(x =>
+
252 {
+
253 var result = String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.TargetCommitSha![..7]);
+
254 if (x.Comment != null)
+
255 result += String.Format(CultureInfo.InvariantCulture, " ({0})", x.Comment);
+
256 return result;
+
257 })));
+
258
+
259 var prefix = GetEngineCompilerPrefix(engineVersion.Engine!.Value);
+
260 await SendMessage(
+
261 null,
+
262 new MessageContent
+
263 {
+
264 Text = String.Format(
+
265 CultureInfo.InvariantCulture,
+
266 $"{prefix}: Deploying revision: {0}{1}{2} BYOND Version: {3}{4}",
+
267 commitInsert,
+
268 testmergeInsert,
+
269 remoteCommitInsert,
+
270 engineVersion.ToString(),
+
271 estimatedCompletionTime.HasValue
+
272 ? $" ETA: {estimatedCompletionTime - DateTimeOffset.UtcNow}"
+
273 : String.Empty),
+
274 },
+
275 channelId,
+
276 cancellationToken);
+
277
+
278 return async (errorMessage, dreamMakerOutput) =>
+
279 {
+
280 await SendMessage(
+
281 null,
+
282 new MessageContent
+
283 {
+
284 Text = $"{prefix}: Deployment {(errorMessage == null ? "complete" : "failed")}!",
+
285 },
+
286 channelId,
+
287 cancellationToken);
+
288
+
289 return active => ValueTask.CompletedTask;
+
290 };
+
291 }
-
294
-
296 protected override async ValueTask<Dictionary<Models.ChatChannel, IEnumerable<ChannelRepresentation>>> MapChannelsImpl(
-
297 IEnumerable<Models.ChatChannel> channels,
-
298 CancellationToken cancellationToken)
-
299 => await Task.Factory.StartNew(
-
300 () =>
-
301 {
-
302 if (channels.Any(x => x.IrcChannel == null))
-
303 throw new InvalidOperationException("ChatChannel missing IrcChannel!");
-
304 lock (client)
-
305 {
-
306 var channelsWithKeys = new Dictionary<string, string>();
-
307 var hs = new HashSet<string>(); // for unique inserts
-
308 foreach (var channel in channels)
-
309 {
-
310 var name = channel.GetIrcChannelName();
-
311 var key = channel.GetIrcChannelKey();
-
312 if (hs.Add(name) && key != null)
-
313 channelsWithKeys.Add(name, key);
-
314 }
-
315
-
316 var toPart = new List<string>();
-
317 foreach (var activeChannel in client.JoinedChannels)
-
318 if (!hs.Remove(activeChannel))
-
319 toPart.Add(activeChannel);
-
320
-
321 foreach (var channelToLeave in toPart)
-
322 client.RfcPart(channelToLeave, "Pretty nice abscond!");
-
323 foreach (var channelToJoin in hs)
-
324 if (channelsWithKeys.TryGetValue(channelToJoin, out var key))
-
325 client.RfcJoin(channelToJoin, key);
-
326 else
-
327 client.RfcJoin(channelToJoin);
-
328
-
329 return new Dictionary<Models.ChatChannel, IEnumerable<ChannelRepresentation>>(
-
330 channels
-
331 .Select(dbChannel =>
-
332 {
-
333 var channelName = dbChannel.GetIrcChannelName();
-
334 ulong? id = null;
-
335 if (!channelIdMap.Any(y =>
-
336 {
-
337 if (y.Value != channelName)
-
338 return false;
-
339 id = y.Key;
-
340 return true;
-
341 }))
-
342 {
-
343 id = channelIdCounter++;
-
344 channelIdMap.Add(id.Value, channelName);
-
345 }
-
346
-
347 return new KeyValuePair<Models.ChatChannel, IEnumerable<ChannelRepresentation>>(
-
348 dbChannel,
-
349 new List<ChannelRepresentation>
-
350 {
-
351 new(address, channelName, id!.Value)
-
352 {
-
353 Tag = dbChannel.Tag,
-
354 IsAdminChannel = dbChannel.IsAdminChannel == true,
-
355 IsPrivateChannel = false,
-
356 EmbedsSupported = false,
-
357 },
-
358 });
-
359 }));
-
360 }
-
361 },
-
362 cancellationToken,
-
363 DefaultIOManager.BlockingTaskCreationOptions,
-
364 TaskScheduler.Current);
-
365
-
-
367 protected override async ValueTask Connect(CancellationToken cancellationToken)
-
368 {
-
369 cancellationToken.ThrowIfCancellationRequested();
-
370 try
-
371 {
-
372 await Task.Factory.StartNew(
-
373 () =>
-
374 {
-
375 client = InstantiateClient();
-
376 client.Connect(address, port);
-
377 },
-
378 cancellationToken,
-
379 DefaultIOManager.BlockingTaskCreationOptions,
-
380 TaskScheduler.Current)
-
381 .WaitAsync(cancellationToken);
+
292
+
294 protected override async ValueTask<Dictionary<Models.ChatChannel, IEnumerable<ChannelRepresentation>>> MapChannelsImpl(
+
295 IEnumerable<Models.ChatChannel> channels,
+
296 CancellationToken cancellationToken)
+
297 => await Task.Factory.StartNew(
+
298 () =>
+
299 {
+
300 if (channels.Any(x => x.IrcChannel == null))
+
301 throw new InvalidOperationException("ChatChannel missing IrcChannel!");
+
302 lock (client)
+
303 {
+
304 var channelsWithKeys = new Dictionary<string, string>();
+
305 var hs = new HashSet<string>(); // for unique inserts
+
306 foreach (var channel in channels)
+
307 {
+
308 var name = channel.GetIrcChannelName();
+
309 var key = channel.GetIrcChannelKey();
+
310 if (hs.Add(name) && key != null)
+
311 channelsWithKeys.Add(name, key);
+
312 }
+
313
+
314 var toPart = new List<string>();
+
315 foreach (var activeChannel in client.JoinedChannels)
+
316 if (!hs.Remove(activeChannel))
+
317 toPart.Add(activeChannel);
+
318
+
319 foreach (var channelToLeave in toPart)
+
320 client.RfcPart(channelToLeave, "Pretty nice abscond!");
+
321 foreach (var channelToJoin in hs)
+
322 if (channelsWithKeys.TryGetValue(channelToJoin, out var key))
+
323 client.RfcJoin(channelToJoin, key);
+
324 else
+
325 client.RfcJoin(channelToJoin);
+
326
+
327 return new Dictionary<Models.ChatChannel, IEnumerable<ChannelRepresentation>>(
+
328 channels
+
329 .Select(dbChannel =>
+
330 {
+
331 var channelName = dbChannel.GetIrcChannelName();
+
332 ulong? id = null;
+
333 if (!channelIdMap.Any(y =>
+
334 {
+
335 if (y.Value != channelName)
+
336 return false;
+
337 id = y.Key;
+
338 return true;
+
339 }))
+
340 {
+
341 id = channelIdCounter++;
+
342 channelIdMap.Add(id.Value, channelName);
+
343 }
+
344
+
345 return new KeyValuePair<Models.ChatChannel, IEnumerable<ChannelRepresentation>>(
+
346 dbChannel,
+
347 new List<ChannelRepresentation>
+
348 {
+
349 new(address, channelName, id!.Value)
+
350 {
+
351 Tag = dbChannel.Tag,
+
352 IsAdminChannel = dbChannel.IsAdminChannel == true,
+
353 IsPrivateChannel = false,
+
354 EmbedsSupported = false,
+
355 },
+
356 });
+
357 }));
+
358 }
+
359 },
+
360 cancellationToken,
+
361 DefaultIOManager.BlockingTaskCreationOptions,
+
362 TaskScheduler.Current);
+
363
+
+
365 protected override async ValueTask Connect(CancellationToken cancellationToken)
+
366 {
+
367 cancellationToken.ThrowIfCancellationRequested();
+
368 try
+
369 {
+
370 await Task.Factory.StartNew(
+
371 () =>
+
372 {
+
373 client = InstantiateClient();
+
374 client.Connect(address, port);
+
375 },
+
376 cancellationToken,
+ +
378 TaskScheduler.Current)
+
379 .WaitAsync(cancellationToken);
+
380
+
381 cancellationToken.ThrowIfCancellationRequested();
382
-
383 cancellationToken.ThrowIfCancellationRequested();
-
384
-
385 listenTask = Task.Factory.StartNew(
-
386 () =>
-
387 {
-
388 Logger.LogTrace("Starting blocking listen...");
-
389 try
-
390 {
-
391 client.Listen();
-
392 }
-
393 catch (Exception ex)
-
394 {
-
395 Logger.LogWarning(ex, "IRC Main Listen Exception!");
-
396 }
-
397
-
398 Logger.LogTrace("Exiting listening task...");
-
399 },
-
400 cancellationToken,
- -
402 TaskScheduler.Current);
-
403
-
404 Logger.LogTrace("Authenticating ({passwordType})...", passwordType);
-
405 switch (passwordType)
-
406 {
-
407 case IrcPasswordType.Server:
-
408 client.RfcPass(password);
-
409 await Login(client, nickname, cancellationToken);
-
410 break;
-
411 case IrcPasswordType.NickServ:
-
412 await Login(client, nickname, cancellationToken);
-
413 cancellationToken.ThrowIfCancellationRequested();
-
414 client.SendMessage(SendType.Message, "NickServ", String.Format(CultureInfo.InvariantCulture, "IDENTIFY {0}", password));
-
415 break;
-
416 case IrcPasswordType.Sasl:
-
417 await SaslAuthenticate(cancellationToken);
-
418 break;
-
419 case IrcPasswordType.Oper:
-
420 await Login(client, nickname, cancellationToken);
-
421 cancellationToken.ThrowIfCancellationRequested();
-
422 client.RfcOper(nickname, password, Priority.Critical);
-
423 break;
-
424 case null:
-
425 await Login(client, nickname, cancellationToken);
-
426 break;
-
427 default:
-
428 throw new InvalidOperationException($"Invalid IrcPasswordType: {passwordType.Value}");
-
429 }
+
383 listenTask = Task.Factory.StartNew(
+
384 () =>
+
385 {
+
386 Logger.LogTrace("Starting blocking listen...");
+
387 try
+
388 {
+
389 client.Listen();
+
390 }
+
391 catch (Exception ex)
+
392 {
+
393 Logger.LogWarning(ex, "IRC Main Listen Exception!");
+
394 }
+
395
+
396 Logger.LogTrace("Exiting listening task...");
+
397 },
+
398 cancellationToken,
+ +
400 TaskScheduler.Current);
+
401
+
402 Logger.LogTrace("Authenticating ({passwordType})...", passwordType);
+
403 switch (passwordType)
+
404 {
+
405 case IrcPasswordType.Server:
+
406 client.RfcPass(password);
+
407 await Login(client, nickname, cancellationToken);
+
408 break;
+
409 case IrcPasswordType.NickServ:
+
410 await Login(client, nickname, cancellationToken);
+
411 cancellationToken.ThrowIfCancellationRequested();
+
412 client.SendMessage(SendType.Message, "NickServ", String.Format(CultureInfo.InvariantCulture, "IDENTIFY {0}", password));
+
413 break;
+
414 case IrcPasswordType.Sasl:
+
415 await SaslAuthenticate(cancellationToken);
+
416 break;
+
417 case IrcPasswordType.Oper:
+
418 await Login(client, nickname, cancellationToken);
+
419 cancellationToken.ThrowIfCancellationRequested();
+
420 client.RfcOper(nickname, password, Priority.Critical);
+
421 break;
+
422 case null:
+
423 await Login(client, nickname, cancellationToken);
+
424 break;
+
425 default:
+
426 throw new InvalidOperationException($"Invalid IrcPasswordType: {passwordType.Value}");
+
427 }
+
428
+
429 cancellationToken.ThrowIfCancellationRequested();
430
-
431 cancellationToken.ThrowIfCancellationRequested();
-
432
-
433 Logger.LogTrace("Connection established!");
-
434 }
-
435 catch (Exception e) when (e is not OperationCanceledException)
-
436 {
-
437 throw new JobException(ErrorCode.ChatCannotConnectProvider, e);
-
438 }
-
439 }
+
431 Logger.LogTrace("Connection established!");
+
432 }
+
433 catch (Exception e) when (e is not OperationCanceledException)
+
434 {
+
435 throw new JobException(ErrorCode.ChatCannotConnectProvider, e);
+
436 }
+
437 }
-
440
-
-
442 protected override async ValueTask DisconnectImpl(CancellationToken cancellationToken)
-
443 {
-
444 try
-
445 {
-
446 await Task.Factory.StartNew(
-
447 () =>
-
448 {
-
449 try
-
450 {
-
451 client.RfcQuit("Mr. Stark, I don't feel so good...", Priority.Critical); // priocritical otherwise it wont go through
-
452 }
-
453 catch (Exception e)
-
454 {
-
455 Logger.LogWarning(e, "Error quitting IRC!");
-
456 }
-
457 },
-
458 cancellationToken,
- -
460 TaskScheduler.Current);
-
461 await HardDisconnect(cancellationToken);
-
462 }
-
463 catch (OperationCanceledException)
-
464 {
-
465 throw;
-
466 }
-
467 catch (Exception e)
-
468 {
-
469 Logger.LogWarning(e, "Error disconnecting from IRC!");
-
470 }
-
471 }
+
438
+
+
440 protected override async ValueTask DisconnectImpl(CancellationToken cancellationToken)
+
441 {
+
442 try
+
443 {
+
444 await Task.Factory.StartNew(
+
445 () =>
+
446 {
+
447 try
+
448 {
+
449 client.RfcQuit("Mr. Stark, I don't feel so good...", Priority.Critical); // priocritical otherwise it wont go through
+
450 }
+
451 catch (Exception e)
+
452 {
+
453 Logger.LogWarning(e, "Error quitting IRC!");
+
454 }
+
455 },
+
456 cancellationToken,
+ +
458 TaskScheduler.Current);
+
459 await HardDisconnect(cancellationToken);
+
460 }
+
461 catch (OperationCanceledException)
+
462 {
+
463 throw;
+
464 }
+
465 catch (Exception e)
+
466 {
+
467 Logger.LogWarning(e, "Error disconnecting from IRC!");
+
468 }
+
469 }
-
472
-
-
481 async ValueTask Login(IrcFeatures client, string nickname, CancellationToken cancellationToken)
-
482 {
-
483 var promise = new TaskCompletionSource<object>();
-
484
-
485 void Callback(object? sender, EventArgs e)
-
486 {
-
487 Logger.LogTrace("IRC Registered.");
-
488 promise.TrySetResult(e);
-
489 }
+
470
+
+
479 async ValueTask Login(IrcFeatures client, string nickname, CancellationToken cancellationToken)
+
480 {
+
481 var promise = new TaskCompletionSource<object>();
+
482
+
483 void Callback(object? sender, EventArgs e)
+
484 {
+
485 Logger.LogTrace("IRC Registered.");
+
486 promise.TrySetResult(e);
+
487 }
+
488
+
489 client.OnRegistered += Callback;
490
-
491 client.OnRegistered += Callback;
+
491 client.Login(nickname, nickname, 0, nickname);
492
-
493 client.Login(nickname, nickname, 0, nickname);
-
494
-
495 using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
-
496 cts.CancelAfter(TimeSpan.FromSeconds(30));
-
497
-
498 try
-
499 {
-
500 await promise.Task.WaitAsync(cts.Token);
-
501 client.OnRegistered -= Callback;
-
502 }
-
503 catch (OperationCanceledException)
-
504 {
-
505 if (client.IsConnected)
-
506 client.Disconnect();
-
507 throw new JobException("Timed out waiting for IRC Registration");
-
508 }
-
509 }
+
493 using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
+
494 cts.CancelAfter(TimeSpan.FromSeconds(30));
+
495
+
496 try
+
497 {
+
498 await promise.Task.WaitAsync(cts.Token);
+
499 client.OnRegistered -= Callback;
+
500 }
+
501 catch (OperationCanceledException)
+
502 {
+
503 if (client.IsConnected)
+
504 client.Disconnect();
+
505 throw new JobException("Timed out waiting for IRC Registration");
+
506 }
+
507 }
-
510
-
-
516 void HandleMessage(IrcEventArgs e, bool isPrivate)
-
517 {
-
518 if (e.Data.Nick.Equals(client.Nickname, StringComparison.OrdinalIgnoreCase))
-
519 return;
-
520
-
521 var username = e.Data.Nick;
-
522 var channelName = isPrivate ? username : e.Data.Channel;
-
523
-
524 ulong MapAndGetChannelId(Dictionary<ulong, string?> dicToCheck)
-
525 {
-
526 ulong? resultId = null;
-
527 if (!dicToCheck.Any(x =>
-
528 {
-
529 if (x.Value != channelName)
-
530 return false;
-
531 resultId = x.Key;
-
532 return true;
-
533 }))
-
534 {
-
535 resultId = channelIdCounter++;
-
536 dicToCheck.Add(resultId.Value, channelName);
-
537 if (dicToCheck == queryChannelIdMap)
-
538 channelIdMap.Add(resultId.Value, null);
-
539 }
-
540
-
541 return resultId!.Value;
-
542 }
-
543
-
544 ulong userId, channelId;
-
545 lock (client)
-
546 {
-
547 userId = MapAndGetChannelId(new Dictionary<ulong, string?>(queryChannelIdMap
-
548 .Cast<KeyValuePair<ulong, string?>>())); // NRT my beloathed
-
549 channelId = isPrivate ? userId : MapAndGetChannelId(channelIdMap);
-
550 }
-
551
-
552 var channelFriendlyName = isPrivate ? String.Format(CultureInfo.InvariantCulture, "PM: {0}", channelName) : channelName;
-
553 var message = new Message(
-
554 new ChatUser(
-
555 new ChannelRepresentation(address, channelFriendlyName, channelId)
-
556 {
-
557 IsPrivateChannel = isPrivate,
-
558 EmbedsSupported = false,
-
559
-
560 // isAdmin and Tag populated by manager
-
561 },
-
562 username,
-
563 username,
-
564 userId),
-
565 e.Data.Message);
-
566
-
567 EnqueueMessage(message);
-
568 }
+
508
+
+
514 void HandleMessage(IrcEventArgs e, bool isPrivate)
+
515 {
+
516 if (e.Data.Nick.Equals(client.Nickname, StringComparison.OrdinalIgnoreCase))
+
517 return;
+
518
+
519 var username = e.Data.Nick;
+
520 var channelName = isPrivate ? username : e.Data.Channel;
+
521
+
522 ulong MapAndGetChannelId(Dictionary<ulong, string?> dicToCheck)
+
523 {
+
524 ulong? resultId = null;
+
525 if (!dicToCheck.Any(x =>
+
526 {
+
527 if (x.Value != channelName)
+
528 return false;
+
529 resultId = x.Key;
+
530 return true;
+
531 }))
+
532 {
+
533 resultId = channelIdCounter++;
+
534 dicToCheck.Add(resultId.Value, channelName);
+
535 if (dicToCheck == queryChannelIdMap)
+
536 channelIdMap.Add(resultId.Value, null);
+
537 }
+
538
+
539 return resultId!.Value;
+
540 }
+
541
+
542 ulong userId, channelId;
+
543 lock (client)
+
544 {
+
545 userId = MapAndGetChannelId(new Dictionary<ulong, string?>(queryChannelIdMap
+
546 .Cast<KeyValuePair<ulong, string?>>())); // NRT my beloathed
+
547 channelId = isPrivate ? userId : MapAndGetChannelId(channelIdMap);
+
548 }
+
549
+
550 var channelFriendlyName = isPrivate ? String.Format(CultureInfo.InvariantCulture, "PM: {0}", channelName) : channelName;
+
551 var message = new Message(
+
552 new ChatUser(
+
553 new ChannelRepresentation(address, channelFriendlyName, channelId)
+
554 {
+
555 IsPrivateChannel = isPrivate,
+
556 EmbedsSupported = false,
+
557
+
558 // isAdmin and Tag populated by manager
+
559 },
+
560 username,
+
561 username,
+
562 userId),
+
563 e.Data.Message);
+
564
+
565 EnqueueMessage(message);
+
566 }
-
569
-
575 void Client_OnQueryMessage(object sender, IrcEventArgs e) => HandleMessage(e, true);
-
576
-
582 void Client_OnChannelMessage(object sender, IrcEventArgs e) => HandleMessage(e, false);
-
583
-
589 Task NonBlockingListen(CancellationToken cancellationToken) => Task.Factory.StartNew(
-
590 () =>
-
591 {
-
592 try
-
593 {
-
594 client.Listen(false);
-
595 }
-
596 catch (Exception ex)
-
597 {
-
598 Logger.LogWarning(ex, "IRC Non-Blocking Listen Exception!");
-
599 }
-
600 },
-
601 cancellationToken,
-
602 TaskCreationOptions.None,
-
603 TaskScheduler.Current)
-
604 .WaitAsync(cancellationToken);
-
605
-
-
611 async ValueTask SaslAuthenticate(CancellationToken cancellationToken)
-
612 {
-
613 client.WriteLine("CAP REQ :sasl", Priority.Critical); // needs to be put in the buffer before anything else
-
614 cancellationToken.ThrowIfCancellationRequested();
-
615
-
616 Logger.LogTrace("Logging in...");
-
617 client.Login(nickname, nickname, 0, nickname);
-
618 cancellationToken.ThrowIfCancellationRequested();
-
619
-
620 // wait for the SASL ack or timeout
-
621 var receivedAck = false;
-
622 var receivedPlus = false;
-
623
-
624 void AuthenticationDelegate(object sender, ReadLineEventArgs e)
-
625 {
-
626 if (e.Line.Contains("ACK :sasl", StringComparison.Ordinal))
-
627 receivedAck = true;
-
628 else if (e.Line.Contains("AUTHENTICATE +", StringComparison.Ordinal))
-
629 receivedPlus = true;
-
630 }
-
631
-
632 Logger.LogTrace("Performing handshake...");
-
633 client.OnReadLine += AuthenticationDelegate;
-
634 try
-
635 {
-
636 using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
-
637 timeoutCts.CancelAfter(TimeSpan.FromSeconds(25));
-
638 var timeoutToken = timeoutCts.Token;
-
639
-
640 var listenTimeSpan = TimeSpan.FromMilliseconds(10);
-
641 for (; !receivedAck;
-
642 await AsyncDelayer.Delay(listenTimeSpan, timeoutToken))
-
643 await NonBlockingListen(cancellationToken);
-
644
-
645 client.WriteLine("AUTHENTICATE PLAIN", Priority.Critical);
-
646 timeoutToken.ThrowIfCancellationRequested();
-
647
-
648 for (; !receivedPlus;
-
649 await AsyncDelayer.Delay(listenTimeSpan, timeoutToken))
-
650 await NonBlockingListen(cancellationToken);
-
651 }
-
652 finally
-
653 {
-
654 client.OnReadLine -= AuthenticationDelegate;
-
655 }
+
567
+
573 void Client_OnQueryMessage(object sender, IrcEventArgs e) => HandleMessage(e, true);
+
574
+
580 void Client_OnChannelMessage(object sender, IrcEventArgs e) => HandleMessage(e, false);
+
581
+
587 Task NonBlockingListen(CancellationToken cancellationToken) => Task.Factory.StartNew(
+
588 () =>
+
589 {
+
590 try
+
591 {
+
592 client.Listen(false);
+
593 }
+
594 catch (Exception ex)
+
595 {
+
596 Logger.LogWarning(ex, "IRC Non-Blocking Listen Exception!");
+
597 }
+
598 },
+
599 cancellationToken,
+
600 TaskCreationOptions.None,
+
601 TaskScheduler.Current)
+
602 .WaitAsync(cancellationToken);
+
603
+
+
609 async ValueTask SaslAuthenticate(CancellationToken cancellationToken)
+
610 {
+
611 client.WriteLine("CAP REQ :sasl", Priority.Critical); // needs to be put in the buffer before anything else
+
612 cancellationToken.ThrowIfCancellationRequested();
+
613
+
614 Logger.LogTrace("Logging in...");
+
615 client.Login(nickname, nickname, 0, nickname);
+
616 cancellationToken.ThrowIfCancellationRequested();
+
617
+
618 // wait for the SASL ack or timeout
+
619 var receivedAck = false;
+
620 var receivedPlus = false;
+
621
+
622 void AuthenticationDelegate(object sender, ReadLineEventArgs e)
+
623 {
+
624 if (e.Line.Contains("ACK :sasl", StringComparison.Ordinal))
+
625 receivedAck = true;
+
626 else if (e.Line.Contains("AUTHENTICATE +", StringComparison.Ordinal))
+
627 receivedPlus = true;
+
628 }
+
629
+
630 Logger.LogTrace("Performing handshake...");
+
631 client.OnReadLine += AuthenticationDelegate;
+
632 try
+
633 {
+
634 using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
+
635 timeoutCts.CancelAfter(TimeSpan.FromSeconds(25));
+
636 var timeoutToken = timeoutCts.Token;
+
637
+
638 var listenTimeSpan = TimeSpan.FromMilliseconds(10);
+
639 for (; !receivedAck;
+
640 await AsyncDelayer.Delay(listenTimeSpan, timeoutToken))
+
641 await NonBlockingListen(cancellationToken);
+
642
+
643 client.WriteLine("AUTHENTICATE PLAIN", Priority.Critical);
+
644 timeoutToken.ThrowIfCancellationRequested();
+
645
+
646 for (; !receivedPlus;
+
647 await AsyncDelayer.Delay(listenTimeSpan, timeoutToken))
+
648 await NonBlockingListen(cancellationToken);
+
649 }
+
650 finally
+
651 {
+
652 client.OnReadLine -= AuthenticationDelegate;
+
653 }
+
654
+
655 cancellationToken.ThrowIfCancellationRequested();
656
-
657 cancellationToken.ThrowIfCancellationRequested();
-
658
-
659 // Stolen! https://github.com/znc/znc/blob/1e697580155d5a38f8b5a377f3b1d94aaa979539/modules/sasl.cpp#L196
-
660 Logger.LogTrace("Sending credentials...");
-
661 var authString = String.Format(
-
662 CultureInfo.InvariantCulture,
-
663 "{0}{1}{0}{1}{2}",
-
664 nickname,
-
665 '\0',
-
666 password);
-
667 var b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
-
668 var authLine = $"AUTHENTICATE {b64}";
-
669 client.WriteLine(authLine, Priority.Critical);
-
670 cancellationToken.ThrowIfCancellationRequested();
-
671
-
672 Logger.LogTrace("Finishing authentication...");
-
673 client.WriteLine("CAP END", Priority.Critical);
-
674 }
+
657 // Stolen! https://github.com/znc/znc/blob/1e697580155d5a38f8b5a377f3b1d94aaa979539/modules/sasl.cpp#L196
+
658 Logger.LogTrace("Sending credentials...");
+
659 var authString = String.Format(
+
660 CultureInfo.InvariantCulture,
+
661 "{0}{1}{0}{1}{2}",
+
662 nickname,
+
663 '\0',
+
664 password);
+
665 var b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
+
666 var authLine = $"AUTHENTICATE {b64}";
+
667 client.WriteLine(authLine, Priority.Critical);
+
668 cancellationToken.ThrowIfCancellationRequested();
+
669
+
670 Logger.LogTrace("Finishing authentication...");
+
671 client.WriteLine("CAP END", Priority.Critical);
+
672 }
-
675
-
-
681 async ValueTask HardDisconnect(CancellationToken cancellationToken)
-
682 {
-
683 if (!Connected)
-
684 {
-
685 Logger.LogTrace("Not hard disconnecting, already offline");
-
686 return;
-
687 }
+
673
+
+
679 async ValueTask HardDisconnect(CancellationToken cancellationToken)
+
680 {
+
681 if (!Connected)
+
682 {
+
683 Logger.LogTrace("Not hard disconnecting, already offline");
+
684 return;
+
685 }
+
686
+
687 Logger.LogTrace("Hard disconnect");
688
-
689 Logger.LogTrace("Hard disconnect");
-
690
-
691 // This call blocks permanently randomly sometimes
-
692 // Frankly I don't give a shit
-
693 var disconnectTask = Task.Factory.StartNew(
-
694 () =>
-
695 {
-
696 try
-
697 {
-
698 client.Disconnect();
-
699 }
-
700 catch (Exception e)
-
701 {
-
702 Logger.LogWarning(e, "Error disconnecting IRC!");
-
703 }
-
704 },
-
705 cancellationToken,
- -
707 TaskScheduler.Current);
-
708
-
709 await Task.WhenAny(
-
710 Task.WhenAll(
-
711 disconnectTask,
-
712 listenTask ?? Task.CompletedTask),
-
713 AsyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken).AsTask());
-
714 }
+
689 // This call blocks permanently randomly sometimes
+
690 // Frankly I don't give a shit
+
691 var disconnectTask = Task.Factory.StartNew(
+
692 () =>
+
693 {
+
694 try
+
695 {
+
696 client.Disconnect();
+
697 }
+
698 catch (Exception e)
+
699 {
+
700 Logger.LogWarning(e, "Error disconnecting IRC!");
+
701 }
+
702 },
+
703 cancellationToken,
+ +
705 TaskScheduler.Current);
+
706
+
707 await Task.WhenAny(
+
708 Task.WhenAll(
+
709 disconnectTask,
+
710 listenTask ?? Task.CompletedTask),
+
711 AsyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken).AsTask());
+
712 }
-
715
-
-
721 IrcFeatures InstantiateClient()
-
722 {
-
723 var newClient = new IrcFeatures
-
724 {
-
725 SupportNonRfc = true,
-
726 CtcpUserInfo = "You are going to play. And I am going to watch. And everything will be just fine...",
-
727 AutoRejoin = true,
-
728 AutoRejoinOnKick = true,
-
729 AutoRelogin = false,
-
730 AutoRetry = false,
-
731 AutoReconnect = false,
-
732 ActiveChannelSyncing = true,
-
733 AutoNickHandling = true,
-
734 CtcpVersion = assemblyInfo.VersionString,
-
735 UseSsl = ssl,
-
736 EnableUTF8Recode = true,
-
737 };
-
738 if (ssl)
-
739 newClient.ValidateServerCertificate = true; // dunno if it defaults to that or what
-
740
-
741 newClient.OnChannelMessage += Client_OnChannelMessage;
-
742 newClient.OnQueryMessage += Client_OnQueryMessage;
-
743
-
744 if (loggingConfiguration.ProviderNetworkDebug)
-
745 {
-
746 newClient.OnReadLine += (sender, e) => Logger.LogTrace("READ: {line}", e.Line);
-
747 newClient.OnWriteLine += (sender, e) => Logger.LogTrace("WRITE: {line}", e.Line);
-
748 }
-
749
-
750 newClient.OnError += (sender, e) =>
-
751 {
-
752 Logger.LogError("IRC ERROR: {error}", e.ErrorMessage);
-
753 newClient.Disconnect();
-
754 };
-
755
-
756 return newClient;
-
757 }
+
713
+
+
719 IrcFeatures InstantiateClient()
+
720 {
+
721 var newClient = new IrcFeatures
+
722 {
+
723 SupportNonRfc = true,
+
724 CtcpUserInfo = "You are going to play. And I am going to watch. And everything will be just fine...",
+
725 AutoRejoin = true,
+
726 AutoRejoinOnKick = true,
+
727 AutoRelogin = false,
+
728 AutoRetry = false,
+
729 AutoReconnect = false,
+
730 ActiveChannelSyncing = true,
+
731 AutoNickHandling = true,
+
732 CtcpVersion = assemblyInfo.VersionString,
+
733 UseSsl = ssl,
+
734 EnableUTF8Recode = true,
+
735 };
+
736 if (ssl)
+
737 newClient.ValidateServerCertificate = true; // dunno if it defaults to that or what
+
738
+
739 newClient.OnChannelMessage += Client_OnChannelMessage;
+
740 newClient.OnQueryMessage += Client_OnQueryMessage;
+
741
+
742 if (loggingConfiguration.ProviderNetworkDebug)
+
743 {
+
744 newClient.OnReadLine += (sender, e) => Logger.LogTrace("READ: {line}", e.Line);
+
745 newClient.OnWriteLine += (sender, e) => Logger.LogTrace("WRITE: {line}", e.Line);
+
746 }
+
747
+
748 newClient.OnError += (sender, e) =>
+
749 {
+
750 Logger.LogError("IRC ERROR: {error}", e.ErrorMessage);
+
751 newClient.Disconnect();
+
752 };
+
753
+
754 return newClient;
+
755 }
-
758 }
+
756 }
-
759}
+
757}
Information about an engine installation.
@@ -765,27 +763,27 @@ $(document).ready(function() { init_codefold(0); });
Represents a tgs_chat_user datum.
Definition ChatUser.cs:12
-
IrcFeatures InstantiateClient()
Creates a new instance of the IRC client. Reusing the same client after a disconnection seems to caus...
+
IrcFeatures InstantiateClient()
Creates a new instance of the IRC client. Reusing the same client after a disconnection seems to caus...
readonly IAssemblyInformationProvider assemblyInfo
The IAssemblyInformationProvider obtained from constructor, used for the CTCP version string.
readonly ushort port
Port of the server to connect to.
readonly string password
Password which will used for authentication.
override async ValueTask< Dictionary< Models.ChatChannel, IEnumerable< ChannelRepresentation > > > MapChannelsImpl(IEnumerable< Models.ChatChannel > channels, CancellationToken cancellationToken)
override async ValueTask< Func< string?, string, ValueTask< Func< bool, ValueTask > > > > SendUpdateMessage(Models.RevisionInformation revisionInformation, EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string? gitHubOwner, string? gitHubRepo, ulong channelId, bool localCommitPushed, CancellationToken cancellationToken)
Send the message for a deployment.A ValueTask<TResult> resulting in a Func<T1, T2,...
override string BotMention
The string that indicates the IProvider was mentioned.
-
override async ValueTask DisconnectImpl(CancellationToken cancellationToken)
+
override async ValueTask DisconnectImpl(CancellationToken cancellationToken)
IrcProvider(IJobManager jobManager, IAsyncDelayer asyncDelayer, ILogger< IrcProvider > logger, IAssemblyInformationProvider assemblyInformationProvider, Models.ChatBot chatBot, FileLoggingConfiguration loggingConfiguration)
Initializes a new instance of the IrcProvider class.
-
async ValueTask HardDisconnect(CancellationToken cancellationToken)
Attempt to disconnect from IRC immediately.
+
async ValueTask HardDisconnect(CancellationToken cancellationToken)
Attempt to disconnect from IRC immediately.
const int PreambleMessageLength
Length of the preamble when writing a message to the server. Must be summed with the channel name to ...
-
async ValueTask SaslAuthenticate(CancellationToken cancellationToken)
Run SASL authentication on client.
+
async ValueTask SaslAuthenticate(CancellationToken cancellationToken)
Run SASL authentication on client.
readonly string address
Address of the server to connect to.
void Client_OnQueryMessage(object sender, IrcEventArgs e)
When a query message is received in IRC.
-
override async ValueTask Connect(CancellationToken cancellationToken)
+
override async ValueTask Connect(CancellationToken cancellationToken)
readonly? IrcPasswordType passwordType
The IrcPasswordType of password.
-
async ValueTask Login(IrcFeatures client, string nickname, CancellationToken cancellationToken)
Register the client on the network.
+
async ValueTask Login(IrcFeatures client, string nickname, CancellationToken cancellationToken)
Register the client on the network.
-
void HandleMessage(IrcEventArgs e, bool isPrivate)
Handle an IRC message.
+
void HandleMessage(IrcEventArgs e, bool isPrivate)
Handle an IRC message.
readonly Dictionary< ulong, string > queryChannelIdMap
Map of ChannelRepresentation.RealIds to query users.
override bool Connected
If the IProvider is currently connected.
diff --git a/changelog.yml b/changelog.yml index 5a828e94a3..471090fc25 100644 --- a/changelog.yml +++ b/changelog.yml @@ -215,6 +215,10 @@ Components: - 'nix: bump up sha256 of fixed deviation' Author: Lorwp PullRequest: 2109 + - Descriptions: + - Fixed IRC provider not being able to send update messages for non-GitHub repositories. + Author: Cyberboss + PullRequest: 2136 Unreleased: true - Version: 6.13.0 ComponentVersions: diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_irc_provider.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_irc_provider.html index ab605cab8f..8406b53a1d 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_irc_provider.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_irc_provider.html @@ -506,7 +506,7 @@ Additional Inherited Members
152 }
ChatConnectionStringBuilder for ChatProvider.Irc.
-
IrcFeatures InstantiateClient()
Creates a new instance of the IRC client. Reusing the same client after a disconnection seems to caus...
+
IrcFeatures InstantiateClient()
Creates a new instance of the IRC client. Reusing the same client after a disconnection seems to caus...
readonly IAssemblyInformationProvider assemblyInfo
The IAssemblyInformationProvider obtained from constructor, used for the CTCP version string.
readonly ushort port
Port of the server to connect to.
readonly string password
Password which will used for authentication.
@@ -521,7 +521,7 @@ Additional Inherited Members
readonly Dictionary< ulong, string?> channelIdMap
Map of ChannelRepresentation.RealIds to channel names.
readonly IJobManager jobManager
The IJobManager for the Provider.
Definition Provider.cs:40
-

References Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.address, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.assemblyInfo, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.channelIdCounter, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.channelIdMap, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.client, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.InstantiateClient(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.loggingConfiguration, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.nickname, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.password, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.passwordType, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.port, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.queryChannelIdMap, and Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.ssl.

+

References Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.address, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.assemblyInfo, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.channelIdCounter, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.channelIdMap, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.client, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.InstantiateClient(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.loggingConfiguration, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.nickname, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.password, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.passwordType, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.port, Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.queryChannelIdMap, and Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.ssl.

Here is the call graph for this function:
@@ -652,82 +652,82 @@ Here is the call graph for this function:

-

Definition at line 367 of file IrcProvider.cs.

-
368 {
-
369 cancellationToken.ThrowIfCancellationRequested();
-
370 try
-
371 {
-
372 await Task.Factory.StartNew(
-
373 () =>
-
374 {
- -
376 client.Connect(address, port);
-
377 },
-
378 cancellationToken,
- -
380 TaskScheduler.Current)
-
381 .WaitAsync(cancellationToken);
+

Definition at line 365 of file IrcProvider.cs.

+
366 {
+
367 cancellationToken.ThrowIfCancellationRequested();
+
368 try
+
369 {
+
370 await Task.Factory.StartNew(
+
371 () =>
+
372 {
+ +
374 client.Connect(address, port);
+
375 },
+
376 cancellationToken,
+ +
378 TaskScheduler.Current)
+
379 .WaitAsync(cancellationToken);
+
380
+
381 cancellationToken.ThrowIfCancellationRequested();
382
-
383 cancellationToken.ThrowIfCancellationRequested();
-
384
-
385 listenTask = Task.Factory.StartNew(
-
386 () =>
-
387 {
-
388 Logger.LogTrace("Starting blocking listen...");
-
389 try
-
390 {
-
391 client.Listen();
-
392 }
-
393 catch (Exception ex)
-
394 {
-
395 Logger.LogWarning(ex, "IRC Main Listen Exception!");
-
396 }
-
397
-
398 Logger.LogTrace("Exiting listening task...");
-
399 },
-
400 cancellationToken,
- -
402 TaskScheduler.Current);
-
403
-
404 Logger.LogTrace("Authenticating ({passwordType})...", passwordType);
-
405 switch (passwordType)
-
406 {
-
407 case IrcPasswordType.Server:
-
408 client.RfcPass(password);
-
409 await Login(client, nickname, cancellationToken);
-
410 break;
-
411 case IrcPasswordType.NickServ:
-
412 await Login(client, nickname, cancellationToken);
-
413 cancellationToken.ThrowIfCancellationRequested();
-
414 client.SendMessage(SendType.Message, "NickServ", String.Format(CultureInfo.InvariantCulture, "IDENTIFY {0}", password));
-
415 break;
-
416 case IrcPasswordType.Sasl:
-
417 await SaslAuthenticate(cancellationToken);
-
418 break;
-
419 case IrcPasswordType.Oper:
-
420 await Login(client, nickname, cancellationToken);
-
421 cancellationToken.ThrowIfCancellationRequested();
-
422 client.RfcOper(nickname, password, Priority.Critical);
-
423 break;
-
424 case null:
-
425 await Login(client, nickname, cancellationToken);
-
426 break;
-
427 default:
-
428 throw new InvalidOperationException($"Invalid IrcPasswordType: {passwordType.Value}");
-
429 }
+
383 listenTask = Task.Factory.StartNew(
+
384 () =>
+
385 {
+
386 Logger.LogTrace("Starting blocking listen...");
+
387 try
+
388 {
+
389 client.Listen();
+
390 }
+
391 catch (Exception ex)
+
392 {
+
393 Logger.LogWarning(ex, "IRC Main Listen Exception!");
+
394 }
+
395
+
396 Logger.LogTrace("Exiting listening task...");
+
397 },
+
398 cancellationToken,
+ +
400 TaskScheduler.Current);
+
401
+
402 Logger.LogTrace("Authenticating ({passwordType})...", passwordType);
+
403 switch (passwordType)
+
404 {
+
405 case IrcPasswordType.Server:
+
406 client.RfcPass(password);
+
407 await Login(client, nickname, cancellationToken);
+
408 break;
+
409 case IrcPasswordType.NickServ:
+
410 await Login(client, nickname, cancellationToken);
+
411 cancellationToken.ThrowIfCancellationRequested();
+
412 client.SendMessage(SendType.Message, "NickServ", String.Format(CultureInfo.InvariantCulture, "IDENTIFY {0}", password));
+
413 break;
+
414 case IrcPasswordType.Sasl:
+
415 await SaslAuthenticate(cancellationToken);
+
416 break;
+
417 case IrcPasswordType.Oper:
+
418 await Login(client, nickname, cancellationToken);
+
419 cancellationToken.ThrowIfCancellationRequested();
+
420 client.RfcOper(nickname, password, Priority.Critical);
+
421 break;
+
422 case null:
+
423 await Login(client, nickname, cancellationToken);
+
424 break;
+
425 default:
+
426 throw new InvalidOperationException($"Invalid IrcPasswordType: {passwordType.Value}");
+
427 }
+
428
+
429 cancellationToken.ThrowIfCancellationRequested();
430
-
431 cancellationToken.ThrowIfCancellationRequested();
-
432
-
433 Logger.LogTrace("Connection established!");
-
434 }
-
435 catch (Exception e) when (e is not OperationCanceledException)
-
436 {
-
437 throw new JobException(ErrorCode.ChatCannotConnectProvider, e);
-
438 }
-
439 }
+
431 Logger.LogTrace("Connection established!");
+
432 }
+
433 catch (Exception e) when (e is not OperationCanceledException)
+
434 {
+
435 throw new JobException(ErrorCode.ChatCannotConnectProvider, e);
+
436 }
+
437 }
-
async ValueTask SaslAuthenticate(CancellationToken cancellationToken)
Run SASL authentication on client.
-
async ValueTask Login(IrcFeatures client, string nickname, CancellationToken cancellationToken)
Register the client on the network.
+
async ValueTask SaslAuthenticate(CancellationToken cancellationToken)
Run SASL authentication on client.
+
async ValueTask Login(IrcFeatures client, string nickname, CancellationToken cancellationToken)
Register the client on the network.
Task? listenTask
The ValueTask used for IrcConnection.Listen(bool).
ILogger< Provider > Logger
The ILogger for the Provider.
Definition Provider.cs:35
IIOManager that resolves paths to Environment.CurrentDirectory.
@@ -766,37 +766,37 @@ Here is the call graph for this function:

-

Definition at line 442 of file IrcProvider.cs.

-
443 {
-
444 try
-
445 {
-
446 await Task.Factory.StartNew(
-
447 () =>
-
448 {
-
449 try
-
450 {
-
451 client.RfcQuit("Mr. Stark, I don't feel so good...", Priority.Critical); // priocritical otherwise it wont go through
-
452 }
-
453 catch (Exception e)
-
454 {
-
455 Logger.LogWarning(e, "Error quitting IRC!");
-
456 }
-
457 },
-
458 cancellationToken,
- -
460 TaskScheduler.Current);
-
461 await HardDisconnect(cancellationToken);
-
462 }
-
463 catch (OperationCanceledException)
-
464 {
-
465 throw;
-
466 }
-
467 catch (Exception e)
-
468 {
-
469 Logger.LogWarning(e, "Error disconnecting from IRC!");
-
470 }
-
471 }
-
async ValueTask HardDisconnect(CancellationToken cancellationToken)
Attempt to disconnect from IRC immediately.
+

Definition at line 440 of file IrcProvider.cs.

+
441 {
+
442 try
+
443 {
+
444 await Task.Factory.StartNew(
+
445 () =>
+
446 {
+
447 try
+
448 {
+
449 client.RfcQuit("Mr. Stark, I don't feel so good...", Priority.Critical); // priocritical otherwise it wont go through
+
450 }
+
451 catch (Exception e)
+
452 {
+
453 Logger.LogWarning(e, "Error quitting IRC!");
+
454 }
+
455 },
+
456 cancellationToken,
+ +
458 TaskScheduler.Current);
+
459 await HardDisconnect(cancellationToken);
+
460 }
+
461 catch (OperationCanceledException)
+
462 {
+
463 throw;
+
464 }
+
465 catch (Exception e)
+
466 {
+
467 Logger.LogWarning(e, "Error disconnecting from IRC!");
+
468 }
+
469 }
+
async ValueTask HardDisconnect(CancellationToken cancellationToken)
Attempt to disconnect from IRC immediately.

References Tgstation.Server.Host.IO.DefaultIOManager.BlockingTaskCreationOptions.

@@ -837,7 +837,7 @@ Here is the call graph for this function:
160 await HardDisconnect(CancellationToken.None);
161 }
-

References Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.HardDisconnect().

+

References Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.HardDisconnect().

Here is the call graph for this function:
@@ -896,59 +896,59 @@ Here is the call graph for this function:
-

Definition at line 516 of file IrcProvider.cs.

-
517 {
-
518 if (e.Data.Nick.Equals(client.Nickname, StringComparison.OrdinalIgnoreCase))
-
519 return;
-
520
-
521 var username = e.Data.Nick;
-
522 var channelName = isPrivate ? username : e.Data.Channel;
-
523
-
524 ulong MapAndGetChannelId(Dictionary<ulong, string?> dicToCheck)
-
525 {
-
526 ulong? resultId = null;
-
527 if (!dicToCheck.Any(x =>
-
528 {
-
529 if (x.Value != channelName)
-
530 return false;
-
531 resultId = x.Key;
-
532 return true;
-
533 }))
-
534 {
-
535 resultId = channelIdCounter++;
-
536 dicToCheck.Add(resultId.Value, channelName);
-
537 if (dicToCheck == queryChannelIdMap)
-
538 channelIdMap.Add(resultId.Value, null);
-
539 }
-
540
-
541 return resultId!.Value;
-
542 }
-
543
-
544 ulong userId, channelId;
-
545 lock (client)
-
546 {
-
547 userId = MapAndGetChannelId(new Dictionary<ulong, string?>(queryChannelIdMap
-
548 .Cast<KeyValuePair<ulong, string?>>())); // NRT my beloathed
-
549 channelId = isPrivate ? userId : MapAndGetChannelId(channelIdMap);
-
550 }
-
551
-
552 var channelFriendlyName = isPrivate ? String.Format(CultureInfo.InvariantCulture, "PM: {0}", channelName) : channelName;
-
553 var message = new Message(
-
554 new ChatUser(
-
555 new ChannelRepresentation(address, channelFriendlyName, channelId)
-
556 {
-
557 IsPrivateChannel = isPrivate,
-
558 EmbedsSupported = false,
-
559
-
560 // isAdmin and Tag populated by manager
-
561 },
-
562 username,
-
563 username,
-
564 userId),
-
565 e.Data.Message);
-
566
-
567 EnqueueMessage(message);
-
568 }
+

Definition at line 514 of file IrcProvider.cs.

+
515 {
+
516 if (e.Data.Nick.Equals(client.Nickname, StringComparison.OrdinalIgnoreCase))
+
517 return;
+
518
+
519 var username = e.Data.Nick;
+
520 var channelName = isPrivate ? username : e.Data.Channel;
+
521
+
522 ulong MapAndGetChannelId(Dictionary<ulong, string?> dicToCheck)
+
523 {
+
524 ulong? resultId = null;
+
525 if (!dicToCheck.Any(x =>
+
526 {
+
527 if (x.Value != channelName)
+
528 return false;
+
529 resultId = x.Key;
+
530 return true;
+
531 }))
+
532 {
+
533 resultId = channelIdCounter++;
+
534 dicToCheck.Add(resultId.Value, channelName);
+
535 if (dicToCheck == queryChannelIdMap)
+
536 channelIdMap.Add(resultId.Value, null);
+
537 }
+
538
+
539 return resultId!.Value;
+
540 }
+
541
+
542 ulong userId, channelId;
+
543 lock (client)
+
544 {
+
545 userId = MapAndGetChannelId(new Dictionary<ulong, string?>(queryChannelIdMap
+
546 .Cast<KeyValuePair<ulong, string?>>())); // NRT my beloathed
+
547 channelId = isPrivate ? userId : MapAndGetChannelId(channelIdMap);
+
548 }
+
549
+
550 var channelFriendlyName = isPrivate ? String.Format(CultureInfo.InvariantCulture, "PM: {0}", channelName) : channelName;
+
551 var message = new Message(
+
552 new ChatUser(
+
553 new ChannelRepresentation(address, channelFriendlyName, channelId)
+
554 {
+
555 IsPrivateChannel = isPrivate,
+
556 EmbedsSupported = false,
+
557
+
558 // isAdmin and Tag populated by manager
+
559 },
+
560 username,
+
561 username,
+
562 userId),
+
563 e.Data.Message);
+
564
+
565 EnqueueMessage(message);
+
566 }
void EnqueueMessage(Message? message)
Queues a message for NextMessage(CancellationToken).
Definition Provider.cs:238
@@ -986,40 +986,40 @@ Here is the call graph for this function:
Returns
A ValueTask representing the running operation.
-

Definition at line 681 of file IrcProvider.cs.

-
682 {
-
683 if (!Connected)
-
684 {
-
685 Logger.LogTrace("Not hard disconnecting, already offline");
-
686 return;
-
687 }
+

Definition at line 679 of file IrcProvider.cs.

+
680 {
+
681 if (!Connected)
+
682 {
+
683 Logger.LogTrace("Not hard disconnecting, already offline");
+
684 return;
+
685 }
+
686
+
687 Logger.LogTrace("Hard disconnect");
688
-
689 Logger.LogTrace("Hard disconnect");
-
690
-
691 // This call blocks permanently randomly sometimes
-
692 // Frankly I don't give a shit
-
693 var disconnectTask = Task.Factory.StartNew(
-
694 () =>
-
695 {
-
696 try
-
697 {
-
698 client.Disconnect();
-
699 }
-
700 catch (Exception e)
-
701 {
-
702 Logger.LogWarning(e, "Error disconnecting IRC!");
-
703 }
-
704 },
-
705 cancellationToken,
- -
707 TaskScheduler.Current);
-
708
-
709 await Task.WhenAny(
-
710 Task.WhenAll(
-
711 disconnectTask,
-
712 listenTask ?? Task.CompletedTask),
-
713 AsyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken).AsTask());
-
714 }
+
689 // This call blocks permanently randomly sometimes
+
690 // Frankly I don't give a shit
+
691 var disconnectTask = Task.Factory.StartNew(
+
692 () =>
+
693 {
+
694 try
+
695 {
+
696 client.Disconnect();
+
697 }
+
698 catch (Exception e)
+
699 {
+
700 Logger.LogWarning(e, "Error disconnecting IRC!");
+
701 }
+
702 },
+
703 cancellationToken,
+ +
705 TaskScheduler.Current);
+
706
+
707 await Task.WhenAny(
+
708 Task.WhenAll(
+
709 disconnectTask,
+
710 listenTask ?? Task.CompletedTask),
+
711 AsyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken).AsTask());
+
712 }
override bool Connected
If the IProvider is currently connected.
async ValueTask Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan .A ValueTask representing the running operation.
@@ -1076,43 +1076,43 @@ Here is the caller graph for this function:

Creates a new instance of the IRC client. Reusing the same client after a disconnection seems to cause issues.

Returns
The IrcFeatures client to use.
-

Definition at line 721 of file IrcProvider.cs.

-
722 {
-
723 var newClient = new IrcFeatures
-
724 {
-
725 SupportNonRfc = true,
-
726 CtcpUserInfo = "You are going to play. And I am going to watch. And everything will be just fine...",
-
727 AutoRejoin = true,
-
728 AutoRejoinOnKick = true,
-
729 AutoRelogin = false,
-
730 AutoRetry = false,
-
731 AutoReconnect = false,
-
732 ActiveChannelSyncing = true,
-
733 AutoNickHandling = true,
-
734 CtcpVersion = assemblyInfo.VersionString,
-
735 UseSsl = ssl,
-
736 EnableUTF8Recode = true,
-
737 };
-
738 if (ssl)
-
739 newClient.ValidateServerCertificate = true; // dunno if it defaults to that or what
-
740
-
741 newClient.OnChannelMessage += Client_OnChannelMessage;
-
742 newClient.OnQueryMessage += Client_OnQueryMessage;
-
743
- -
745 {
-
746 newClient.OnReadLine += (sender, e) => Logger.LogTrace("READ: {line}", e.Line);
-
747 newClient.OnWriteLine += (sender, e) => Logger.LogTrace("WRITE: {line}", e.Line);
-
748 }
-
749
-
750 newClient.OnError += (sender, e) =>
-
751 {
-
752 Logger.LogError("IRC ERROR: {error}", e.ErrorMessage);
-
753 newClient.Disconnect();
-
754 };
-
755
-
756 return newClient;
-
757 }
+

Definition at line 719 of file IrcProvider.cs.

+
720 {
+
721 var newClient = new IrcFeatures
+
722 {
+
723 SupportNonRfc = true,
+
724 CtcpUserInfo = "You are going to play. And I am going to watch. And everything will be just fine...",
+
725 AutoRejoin = true,
+
726 AutoRejoinOnKick = true,
+
727 AutoRelogin = false,
+
728 AutoRetry = false,
+
729 AutoReconnect = false,
+
730 ActiveChannelSyncing = true,
+
731 AutoNickHandling = true,
+
732 CtcpVersion = assemblyInfo.VersionString,
+
733 UseSsl = ssl,
+
734 EnableUTF8Recode = true,
+
735 };
+
736 if (ssl)
+
737 newClient.ValidateServerCertificate = true; // dunno if it defaults to that or what
+
738
+
739 newClient.OnChannelMessage += Client_OnChannelMessage;
+
740 newClient.OnQueryMessage += Client_OnQueryMessage;
+
741
+ +
743 {
+
744 newClient.OnReadLine += (sender, e) => Logger.LogTrace("READ: {line}", e.Line);
+
745 newClient.OnWriteLine += (sender, e) => Logger.LogTrace("WRITE: {line}", e.Line);
+
746 }
+
747
+
748 newClient.OnError += (sender, e) =>
+
749 {
+
750 Logger.LogError("IRC ERROR: {error}", e.ErrorMessage);
+
751 newClient.Disconnect();
+
752 };
+
753
+
754 return newClient;
+
755 }
void Client_OnQueryMessage(object sender, IrcEventArgs e)
When a query message is received in IRC.
void Client_OnChannelMessage(object sender, IrcEventArgs e)
When a channel message is received in IRC.
bool ProviderNetworkDebug
If Chat Providers should log their network traffic. Normally disabled because it is too noisy.
@@ -1189,35 +1189,35 @@ Here is the caller graph for this function:
-

Definition at line 481 of file IrcProvider.cs.

-
482 {
-
483 var promise = new TaskCompletionSource<object>();
-
484
-
485 void Callback(object? sender, EventArgs e)
-
486 {
-
487 Logger.LogTrace("IRC Registered.");
-
488 promise.TrySetResult(e);
-
489 }
+

Definition at line 479 of file IrcProvider.cs.

+
480 {
+
481 var promise = new TaskCompletionSource<object>();
+
482
+
483 void Callback(object? sender, EventArgs e)
+
484 {
+
485 Logger.LogTrace("IRC Registered.");
+
486 promise.TrySetResult(e);
+
487 }
+
488
+
489 client.OnRegistered += Callback;
490
-
491 client.OnRegistered += Callback;
+
491 client.Login(nickname, nickname, 0, nickname);
492
-
493 client.Login(nickname, nickname, 0, nickname);
-
494
-
495 using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
-
496 cts.CancelAfter(TimeSpan.FromSeconds(30));
-
497
-
498 try
-
499 {
-
500 await promise.Task.WaitAsync(cts.Token);
-
501 client.OnRegistered -= Callback;
-
502 }
-
503 catch (OperationCanceledException)
-
504 {
-
505 if (client.IsConnected)
-
506 client.Disconnect();
-
507 throw new JobException("Timed out waiting for IRC Registration");
-
508 }
-
509 }
+
493 using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
+
494 cts.CancelAfter(TimeSpan.FromSeconds(30));
+
495
+
496 try
+
497 {
+
498 await promise.Task.WaitAsync(cts.Token);
+
499 client.OnRegistered -= Callback;
+
500 }
+
501 catch (OperationCanceledException)
+
502 {
+
503 if (client.IsConnected)
+
504 client.Disconnect();
+
505 throw new JobException("Timed out waiting for IRC Registration");
+
506 }
+
507 }
@@ -1329,70 +1329,70 @@ Here is the caller graph for this function:
Returns
A ValueTask representing the running operation.
-

Definition at line 611 of file IrcProvider.cs.

-
612 {
-
613 client.WriteLine("CAP REQ :sasl", Priority.Critical); // needs to be put in the buffer before anything else
-
614 cancellationToken.ThrowIfCancellationRequested();
-
615
-
616 Logger.LogTrace("Logging in...");
-
617 client.Login(nickname, nickname, 0, nickname);
-
618 cancellationToken.ThrowIfCancellationRequested();
-
619
-
620 // wait for the SASL ack or timeout
-
621 var receivedAck = false;
-
622 var receivedPlus = false;
-
623
-
624 void AuthenticationDelegate(object sender, ReadLineEventArgs e)
-
625 {
-
626 if (e.Line.Contains("ACK :sasl", StringComparison.Ordinal))
-
627 receivedAck = true;
-
628 else if (e.Line.Contains("AUTHENTICATE +", StringComparison.Ordinal))
-
629 receivedPlus = true;
-
630 }
-
631
-
632 Logger.LogTrace("Performing handshake...");
-
633 client.OnReadLine += AuthenticationDelegate;
-
634 try
-
635 {
-
636 using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
-
637 timeoutCts.CancelAfter(TimeSpan.FromSeconds(25));
-
638 var timeoutToken = timeoutCts.Token;
-
639
-
640 var listenTimeSpan = TimeSpan.FromMilliseconds(10);
-
641 for (; !receivedAck;
-
642 await AsyncDelayer.Delay(listenTimeSpan, timeoutToken))
-
643 await NonBlockingListen(cancellationToken);
-
644
-
645 client.WriteLine("AUTHENTICATE PLAIN", Priority.Critical);
-
646 timeoutToken.ThrowIfCancellationRequested();
-
647
-
648 for (; !receivedPlus;
-
649 await AsyncDelayer.Delay(listenTimeSpan, timeoutToken))
-
650 await NonBlockingListen(cancellationToken);
-
651 }
-
652 finally
-
653 {
-
654 client.OnReadLine -= AuthenticationDelegate;
-
655 }
+

Definition at line 609 of file IrcProvider.cs.

+
610 {
+
611 client.WriteLine("CAP REQ :sasl", Priority.Critical); // needs to be put in the buffer before anything else
+
612 cancellationToken.ThrowIfCancellationRequested();
+
613
+
614 Logger.LogTrace("Logging in...");
+
615 client.Login(nickname, nickname, 0, nickname);
+
616 cancellationToken.ThrowIfCancellationRequested();
+
617
+
618 // wait for the SASL ack or timeout
+
619 var receivedAck = false;
+
620 var receivedPlus = false;
+
621
+
622 void AuthenticationDelegate(object sender, ReadLineEventArgs e)
+
623 {
+
624 if (e.Line.Contains("ACK :sasl", StringComparison.Ordinal))
+
625 receivedAck = true;
+
626 else if (e.Line.Contains("AUTHENTICATE +", StringComparison.Ordinal))
+
627 receivedPlus = true;
+
628 }
+
629
+
630 Logger.LogTrace("Performing handshake...");
+
631 client.OnReadLine += AuthenticationDelegate;
+
632 try
+
633 {
+
634 using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
+
635 timeoutCts.CancelAfter(TimeSpan.FromSeconds(25));
+
636 var timeoutToken = timeoutCts.Token;
+
637
+
638 var listenTimeSpan = TimeSpan.FromMilliseconds(10);
+
639 for (; !receivedAck;
+
640 await AsyncDelayer.Delay(listenTimeSpan, timeoutToken))
+
641 await NonBlockingListen(cancellationToken);
+
642
+
643 client.WriteLine("AUTHENTICATE PLAIN", Priority.Critical);
+
644 timeoutToken.ThrowIfCancellationRequested();
+
645
+
646 for (; !receivedPlus;
+
647 await AsyncDelayer.Delay(listenTimeSpan, timeoutToken))
+
648 await NonBlockingListen(cancellationToken);
+
649 }
+
650 finally
+
651 {
+
652 client.OnReadLine -= AuthenticationDelegate;
+
653 }
+
654
+
655 cancellationToken.ThrowIfCancellationRequested();
656
-
657 cancellationToken.ThrowIfCancellationRequested();
-
658
-
659 // Stolen! https://github.com/znc/znc/blob/1e697580155d5a38f8b5a377f3b1d94aaa979539/modules/sasl.cpp#L196
-
660 Logger.LogTrace("Sending credentials...");
-
661 var authString = String.Format(
-
662 CultureInfo.InvariantCulture,
-
663 "{0}{1}{0}{1}{2}",
-
664 nickname,
-
665 '\0',
-
666 password);
-
667 var b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
-
668 var authLine = $"AUTHENTICATE {b64}";
-
669 client.WriteLine(authLine, Priority.Critical);
-
670 cancellationToken.ThrowIfCancellationRequested();
-
671
-
672 Logger.LogTrace("Finishing authentication...");
-
673 client.WriteLine("CAP END", Priority.Critical);
-
674 }
+
657 // Stolen! https://github.com/znc/znc/blob/1e697580155d5a38f8b5a377f3b1d94aaa979539/modules/sasl.cpp#L196
+
658 Logger.LogTrace("Sending credentials...");
+
659 var authString = String.Format(
+
660 CultureInfo.InvariantCulture,
+
661 "{0}{1}{0}{1}{2}",
+
662 nickname,
+
663 '\0',
+
664 password);
+
665 var b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
+
666 var authLine = $"AUTHENTICATE {b64}";
+
667 client.WriteLine(authLine, Priority.Critical);
+
668 cancellationToken.ThrowIfCancellationRequested();
+
669
+
670 Logger.LogTrace("Finishing authentication...");
+
671 client.WriteLine("CAP END", Priority.Critical);
+
672 }
Task NonBlockingListen(CancellationToken cancellationToken)
Perform a non-blocking IrcConnection.Listen(bool).

References Tgstation.Server.Host.Utils.AsyncDelayer.Delay().

@@ -1617,70 +1617,68 @@ Here is the caller graph for this function:
227 {
228 ArgumentNullException.ThrowIfNull(revisionInformation);
229 ArgumentNullException.ThrowIfNull(engineVersion);
-
230 ArgumentNullException.ThrowIfNull(gitHubOwner);
-
231 ArgumentNullException.ThrowIfNull(gitHubRepo);
-
232
-
233 var commitInsert = revisionInformation.CommitSha![..7];
-
234 string remoteCommitInsert;
-
235 if (revisionInformation.CommitSha == revisionInformation.OriginCommitSha)
-
236 {
-
237 commitInsert = String.Format(CultureInfo.InvariantCulture, localCommitPushed ? "^{0}" : "{0}", commitInsert);
-
238 remoteCommitInsert = String.Empty;
-
239 }
-
240 else
-
241 remoteCommitInsert = String.Format(CultureInfo.InvariantCulture, ". Remote commit: ^{0}", revisionInformation.OriginCommitSha![..7]);
-
242
-
243 var testmergeInsert = (revisionInformation.ActiveTestMerges?.Count ?? 0) == 0
-
244 ? String.Empty
-
245 : String.Format(
-
246 CultureInfo.InvariantCulture,
-
247 " (Test Merges: {0})",
-
248 String.Join(
-
249 ", ",
-
250 revisionInformation
-
251 .ActiveTestMerges!
-
252 .Select(x => x.TestMerge)
-
253 .Select(x =>
-
254 {
-
255 var result = String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.TargetCommitSha![..7]);
-
256 if (x.Comment != null)
-
257 result += String.Format(CultureInfo.InvariantCulture, " ({0})", x.Comment);
-
258 return result;
-
259 })));
-
260
-
261 var prefix = GetEngineCompilerPrefix(engineVersion.Engine!.Value);
-
262 await SendMessage(
-
263 null,
- -
265 {
-
266 Text = String.Format(
-
267 CultureInfo.InvariantCulture,
-
268 $"{prefix}: Deploying revision: {0}{1}{2} BYOND Version: {3}{4}",
-
269 commitInsert,
-
270 testmergeInsert,
-
271 remoteCommitInsert,
-
272 engineVersion.ToString(),
-
273 estimatedCompletionTime.HasValue
-
274 ? $" ETA: {estimatedCompletionTime - DateTimeOffset.UtcNow}"
-
275 : String.Empty),
-
276 },
-
277 channelId,
-
278 cancellationToken);
-
279
-
280 return async (errorMessage, dreamMakerOutput) =>
-
281 {
-
282 await SendMessage(
-
283 null,
- -
285 {
-
286 Text = $"{prefix}: Deployment {(errorMessage == null ? "complete" : "failed")}!",
-
287 },
-
288 channelId,
-
289 cancellationToken);
-
290
-
291 return active => ValueTask.CompletedTask;
-
292 };
-
293 }
+
230
+
231 var commitInsert = revisionInformation.CommitSha![..7];
+
232 string remoteCommitInsert;
+
233 if (revisionInformation.CommitSha == revisionInformation.OriginCommitSha)
+
234 {
+
235 commitInsert = String.Format(CultureInfo.InvariantCulture, localCommitPushed ? "^{0}" : "{0}", commitInsert);
+
236 remoteCommitInsert = String.Empty;
+
237 }
+
238 else
+
239 remoteCommitInsert = String.Format(CultureInfo.InvariantCulture, ". Remote commit: ^{0}", revisionInformation.OriginCommitSha![..7]);
+
240
+
241 var testmergeInsert = (revisionInformation.ActiveTestMerges?.Count ?? 0) == 0
+
242 ? String.Empty
+
243 : String.Format(
+
244 CultureInfo.InvariantCulture,
+
245 " (Test Merges: {0})",
+
246 String.Join(
+
247 ", ",
+
248 revisionInformation
+
249 .ActiveTestMerges!
+
250 .Select(x => x.TestMerge)
+
251 .Select(x =>
+
252 {
+
253 var result = String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.TargetCommitSha![..7]);
+
254 if (x.Comment != null)
+
255 result += String.Format(CultureInfo.InvariantCulture, " ({0})", x.Comment);
+
256 return result;
+
257 })));
+
258
+
259 var prefix = GetEngineCompilerPrefix(engineVersion.Engine!.Value);
+
260 await SendMessage(
+
261 null,
+ +
263 {
+
264 Text = String.Format(
+
265 CultureInfo.InvariantCulture,
+
266 $"{prefix}: Deploying revision: {0}{1}{2} BYOND Version: {3}{4}",
+
267 commitInsert,
+
268 testmergeInsert,
+
269 remoteCommitInsert,
+
270 engineVersion.ToString(),
+
271 estimatedCompletionTime.HasValue
+
272 ? $" ETA: {estimatedCompletionTime - DateTimeOffset.UtcNow}"
+
273 : String.Empty),
+
274 },
+
275 channelId,
+
276 cancellationToken);
+
277
+
278 return async (errorMessage, dreamMakerOutput) =>
+
279 {
+
280 await SendMessage(
+
281 null,
+ +
283 {
+
284 Text = $"{prefix}: Deployment {(errorMessage == null ? "complete" : "failed")}!",
+
285 },
+
286 channelId,
+
287 cancellationToken);
+
288
+
289 return active => ValueTask.CompletedTask;
+
290 };
+
291 }
diff --git a/class_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_default_i_o_manager.html b/class_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_default_i_o_manager.html index 3793215db9..582a77c450 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_default_i_o_manager.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_default_i_o_manager.html @@ -2262,7 +2262,7 @@ Here is the call graph for this function:

Definition at line 31 of file DefaultIOManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), Tgstation.Server.Host.Components.Repository.Repository.CheckoutObject(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.Connect(), Tgstation.Server.Host.Components.StaticFiles.Configuration.CreateDirectory(), Tgstation.Server.Host.System.WindowsProcessFeatures.CreateDump(), Tgstation.Server.Host.Components.Repository.LibGit2RepositoryFactory.CreateFromPath(), Tgstation.Server.Host.IO.DefaultIOManager.DeleteDirectory(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.DisconnectImpl(), Tgstation.Server.Host.Components.Repository.Repository.FetchOrigin(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.HardDisconnect(), Tgstation.Server.Host.Components.Repository.Repository.MergeOrigin(), Tgstation.Server.Host.System.Process.Process(), Tgstation.Server.Host.Components.StaticFiles.Configuration.Read(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.SendMessage(), Tgstation.Server.Host.Components.Repository.Repository.Synchronize(), Tgstation.Server.Host.Components.Repository.Repository.UpdateSubmodules(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.Write().

+

Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), Tgstation.Server.Host.Components.Repository.Repository.CheckoutObject(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.Connect(), Tgstation.Server.Host.Components.StaticFiles.Configuration.CreateDirectory(), Tgstation.Server.Host.System.WindowsProcessFeatures.CreateDump(), Tgstation.Server.Host.Components.Repository.LibGit2RepositoryFactory.CreateFromPath(), Tgstation.Server.Host.IO.DefaultIOManager.DeleteDirectory(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.DisconnectImpl(), Tgstation.Server.Host.Components.Repository.Repository.FetchOrigin(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.HardDisconnect(), Tgstation.Server.Host.Components.Repository.Repository.MergeOrigin(), Tgstation.Server.Host.System.Process.Process(), Tgstation.Server.Host.Components.StaticFiles.Configuration.Read(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.SendMessage(), Tgstation.Server.Host.Components.Repository.Repository.Synchronize(), Tgstation.Server.Host.Components.Repository.Repository.UpdateSubmodules(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.Write().

diff --git a/class_tgstation_1_1_server_1_1_host_1_1_utils_1_1_async_delayer.html b/class_tgstation_1_1_server_1_1_host_1_1_utils_1_1_async_delayer.html index aa6093824e..df8a8d66f9 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_utils_1_1_async_delayer.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_utils_1_1_async_delayer.html @@ -238,7 +238,7 @@ Private Attributes

References Tgstation.Server.Host.Utils.AsyncDelayer.logger.

-

Referenced by Tgstation.Server.Host.Components.Watchdog.AdvancedWatchdog.HandleNormalReboot(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.HardDisconnect(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.MonitorRestart(), Tgstation.Server.Host.Components.Chat.Providers.Provider.ReconnectionLoop(), and Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.SaslAuthenticate().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.AdvancedWatchdog.HandleNormalReboot(), Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.HardDisconnect(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.MonitorRestart(), Tgstation.Server.Host.Components.Chat.Providers.Provider.ReconnectionLoop(), and Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.SaslAuthenticate().

Here is the caller graph for this function: