Created
December 29, 2019 11:58
-
-
Save nathan130200/f321d79f5107cb6a94fcbb517634be76 to your computer and use it in GitHub Desktop.
DSharpPlus: command cooldown visualizer using simple message update loop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections.Concurrent; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using DSharpPlus; | |
using DSharpPlus.CommandsNext; | |
using DSharpPlus.CommandsNext.Attributes; | |
using System.Threading; | |
using DSharpPlus.Entities; | |
using Hexae.Extensions; | |
namespace Hexae.Entities | |
{ | |
public class CooldownVisualizer | |
{ | |
static ConcurrentDictionary<string, CooldownVisualizer> _cache = new ConcurrentDictionary<string, CooldownVisualizer>(); | |
public static async Task CreateOrUpdateAsync(CommandContext ctx, CooldownAttribute attribute) | |
{ | |
var bucket = attribute.GetBucket(ctx)?.BucketId; | |
if (_cache.TryGetValue(bucket, out var visualizer)) | |
await visualizer.ShutdownAsync(); | |
visualizer = new CooldownVisualizer(ctx, attribute); | |
_cache.AddOrUpdate(bucket, visualizer, (key, old) => visualizer); | |
await visualizer.InitializeAsync(); | |
} | |
private CommandContext _context; | |
private CooldownAttribute _attribute; | |
private CancellationTokenSource _cts; | |
private DiscordMessage _state; | |
private volatile bool _disposed; | |
public CooldownVisualizer(CommandContext context, CooldownAttribute attribute) | |
{ | |
_context = context; | |
_attribute = attribute; | |
_cts = new CancellationTokenSource(); | |
_disposed = false; | |
} | |
public TimeSpan GetRemaingTime() | |
=> _attribute.GetRemainingCooldown(_context); | |
public string GetRemaingTimeString() | |
{ | |
var ts = this.GetRemaingTime(); | |
var res = string.Empty; | |
if (ts.TotalHours >= 1) | |
res += ts.Hours + "h "; | |
if (ts.TotalMinutes >= 1) | |
res += ts.Minutes + "m "; | |
if (ts.TotalSeconds >= 1) | |
res += ts.Seconds + "s "; | |
if (ts.TotalMilliseconds >= 1 && ts.TotalSeconds <= 0) | |
res += ts.Milliseconds + "ms "; | |
return res.TrimEnd(' '); | |
} | |
public Task InitializeAsync() | |
{ | |
if (_disposed) | |
return Task.CompletedTask; | |
_ = Task.Factory.StartNew(LoopAsync, _cts.Token, TaskCreationOptions.LongRunning); | |
return Task.CompletedTask; | |
} | |
async Task LoopAsync(object _) | |
{ | |
var fnBuildEmbed = new Func<DiscordEmbedBuilder>(() => new DiscordEmbedBuilder() | |
.WithColor(DiscordColor.Red) | |
.WithDescription($"Você está ainda em cooldown: `{this.GetRemaingTimeString()}`") | |
.WithRequestedBy(_context.User)); | |
_state = await _context.RespondAsync(embed: fnBuildEmbed()); | |
while (!_disposed) | |
{ | |
_state = await _state.ModifyAsync(embed: fnBuildEmbed().Build()); | |
if (this.GetRemaingTime().TotalMilliseconds <= 500) | |
break; | |
await Task.Delay(3000); | |
} | |
await ShutdownAsync(); | |
} | |
public Task ShutdownAsync() | |
{ | |
if (_disposed) | |
return Task.CompletedTask; | |
_disposed = true; | |
if(!_cts.IsCancellationRequested) | |
_cts.Cancel(); | |
if (_state != null) | |
_ = Task.Run(async () => await _state.DeleteAsync()); | |
return Task.CompletedTask; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment