private EmbedBuilder CommunityGoalToEmbed(CommunityGoal cg) { string thumbnailURL = _options.CurrentValue.ThumbnailURL; string descriptionTrimmed = cg.Description.Length <= EmbedBuilder.MaxDescriptionLength ? cg.Description : $"{cg.Description.Remove(EmbedBuilder.MaxDescriptionLength - 3)}..."; EmbedBuilder builder = new EmbedBuilder() .WithAuthor("Elite Dangerous Community Goals", _client.CurrentUser.GetAvatarUrl() ?? _client.CurrentUser.GetDefaultAvatarUrl()) .WithTitle(cg.Name) .WithDescription($"```\n{cg.Objective}\n```\n{descriptionTrimmed}") .AddField("System", cg.SystemName, true) .AddField("Station", cg.StationName, true) .AddField("Tier Reached", $"*{cg.TierReached}* / {cg.TierMax}") .AddField("Contributing Pilots", cg.ContributingPilotsCount.ToString(), true) .AddField("Contributions Count", cg.ContributionsCount.ToString(), true) .AddField("Last Updated", $"{(DateTime.UtcNow - cg.LastUpdateTime.ToUniversalTime()).ToLongFriendlyString()} ago") .AddField("Is Completed?", cg.IsCompleted ? "\u2705" : "\u274C", true) .WithUrl(cg.InaraURL) .WithColor(cg.IsCompleted ? Color.Green : (Color)System.Drawing.Color.Cyan) .WithFooter("Powered by Inara | CG expiration time: ") .WithTimestamp(cg.ExpirationTime); if (!string.IsNullOrWhiteSpace(thumbnailURL)) { builder.WithThumbnailUrl(thumbnailURL); } if (!cg.IsCompleted) { builder.AddField("Time Left", (cg.ExpirationTime - DateTimeOffset.Now).ToLongFriendlyString()); } if (!string.IsNullOrWhiteSpace(cg.Reward)) { string rewardTrimmed = cg.Reward.Length <= EmbedFieldBuilder.MaxFieldValueLength ? cg.Reward : $"{cg.Reward.Remove(EmbedFieldBuilder.MaxFieldValueLength - 3)}..."; builder.AddField("Reward", rewardTrimmed); } return(builder); }
private void StartAutomaticNewsPosting() { if (_autoModeCTS != null) { return; } _autoModeCTS = new CancellationTokenSource(); Task autoTask = Task.Run(async() => { using IDisposable context = _log.UseSource("Elite CGs"); CancellationToken cancellationToken = _autoModeCTS.Token; // wait 5 seconds to let the client get connection state in check await Task.Delay(5 * 1000, cancellationToken).ConfigureAwait(false); _log.LogDebug("Starting automatic ED CG checker"); DateTime _lastRetrievalTime = DateTime.MinValue; try { while (!cancellationToken.IsCancellationRequested) { if (!this._enabled) { _log.LogWarning("Inara credentials missing. Elite Dangerous Community Goals feature will be disabled"); return; } TimeSpan nextUpdateIn = (_lastRetrievalTime + _options.CurrentValue.AutoNewsInterval) - DateTime.UtcNow; // if still waiting, await time, and repeat iteration if (nextUpdateIn > TimeSpan.Zero) { _log.LogTrace("Next update in: {TimeRemaining}", nextUpdateIn); // this will not reflect on updates to options monitor, but that's ok await Task.Delay(nextUpdateIn, cancellationToken).ConfigureAwait(false); continue; } CommunityGoalsOptions options = _options.CurrentValue; // get guild channel if (!(_client.GetChannel(options.AutoNewsChannelID) is SocketTextChannel guildChannel)) { throw new InvalidOperationException($"Channel {options.AutoNewsChannelID} is not a valid guild text channel."); } // retrieve CG data, take only new or finished ones, and then update cache IEnumerable <CommunityGoal> allCGs = await QueryCommunityGoalsAsync(cancellationToken).ConfigureAwait(false); IList <CommunityGoal> newOrJustFinishedCGs = new List <CommunityGoal>(allCGs.Count()); foreach (CommunityGoal cg in allCGs) { CommunityGoal historyCg = await _cgHistoryStore.GetAsync(cg.ID, cancellationToken).ConfigureAwait(false); if (historyCg == null || historyCg.IsCompleted != cg.IsCompleted) { newOrJustFinishedCGs.Add(cg); await _cgHistoryStore.SetAsync(cg, cancellationToken).ConfigureAwait(false); } } _log.LogTrace("New or just finished CGs count: {Count}", newOrJustFinishedCGs.Count); // post all CGs _log.LogTrace("Sending CGs"); foreach (CommunityGoal cg in newOrJustFinishedCGs) { await guildChannel.SendMessageAsync(null, false, CommunityGoalToEmbed(cg).Build(), cancellationToken).ConfigureAwait(false); } _lastRetrievalTime = DateTime.UtcNow; } } catch (OperationCanceledException) { } catch (Exception ex) when(ex.LogAsError(_log, "Error occured in automatic ED CG checker loop")) { } finally { _log.LogDebug("Stopping automatic ED CG checker"); // clear CTS on exiting if it wasn't cleared yet if (_autoModeCTS?.Token == cancellationToken) { _autoModeCTS = null; } } }, _autoModeCTS.Token); }