Skip to content

Instantly share code, notes, and snippets.

@Hamsterland
Created May 31, 2020 23:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hamsterland/a69d60aaa416e5174322b7f0280e8c37 to your computer and use it in GitHub Desktop.
Save Hamsterland/a69d60aaa416e5174322b7f0280e8c37 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Beatbox.Enums;
using Discord;
using Discord.Commands;
namespace Beatbox.Preconditions
{
public class CooldownAttribute : PreconditionAttribute
{
private readonly TimeSpan _invokeLimitPeriod;
private readonly uint _invokeLimit;
private readonly bool _skipAdmin;
private readonly Dictionary<ulong, CommandTimeout> _invokeTracker = new Dictionary<ulong, CommandTimeout>();
public CooldownAttribute(double period, Measure measure, uint times, bool skipAdmin = false)
{
_invokeLimit = times;
_skipAdmin = skipAdmin;
_invokeLimitPeriod = measure switch
{
Measure.Days => TimeSpan.FromDays(period),
Measure.Hours => TimeSpan.FromHours(period),
Measure.Minutes => TimeSpan.FromMinutes(period),
Measure.Seconds => TimeSpan.FromSeconds(period),
_ => _invokeLimitPeriod
};
}
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
{
var now = DateTime.UtcNow;
var key = context.User.Id;
var timeout = _invokeTracker.TryGetValue(key, out var t) && now - t.FirstInvoke < _invokeLimitPeriod ? t : new CommandTimeout(now);
timeout.TimesInvoked++;
if (timeout.TimesInvoked <= _invokeLimit || _skipAdmin && (context.User as IGuildUser).GuildPermissions.Administrator)
{
_invokeTracker[key] = timeout;
return Task.FromResult(PreconditionResult.FromSuccess());
}
return Task.FromResult(PreconditionResult.FromError($"{context.User.Mention} Please wait `{timeout.FirstInvoke - now + _invokeLimitPeriod:hh\\:mm\\:ss}`"));
}
}
public sealed class CommandTimeout
{
public uint TimesInvoked { get; set; }
public DateTime FirstInvoke { get; }
public CommandTimeout(DateTime timeStarted)
{
FirstInvoke = timeStarted;
}
}
public enum Measure
{
Days,
Hours,
Minutes,
Seconds
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment