@@ -5,41 +5,93 @@ using System.Linq;
namespace Discord.Net
namespace Discord.Net
{
{
/// <summary>
/// Represents a ratelimit bucket.
/// </summary>
public class BucketId : IEquatable<BucketId>
public class BucketId : IEquatable<BucketId>
{
{
/// <summary>
/// Gets the http method used to make the request if available.
/// </summary>
public string HttpMethod { get; }
public string HttpMethod { get; }
/// <summary>
/// Gets the endpoint that is going to be requested if available.
/// </summary>
public string Endpoint { get; }
public string Endpoint { get; }
public IOrderedEnumerable<KeyValuePair<string, string>> MajorParams { get; }
/// <summary>
/// Gets the major parameters of the route.
/// </summary>
public IOrderedEnumerable<KeyValuePair<string, string>> MajorParameters { get; }
/// <summary>
/// Gets the hash of this bucket.
/// </summary>
/// <remarks>
/// The hash is provided by Discord to group ratelimits.
/// </remarks>
public string BucketHash { get; }
public string BucketHash { get; }
/// <summary>
/// Gets if this bucket is a hash type.
/// </summary>
public bool IsHashBucket { get => BucketHash != null; }
public bool IsHashBucket { get => BucketHash != null; }
private BucketId(string httpMethod, string endpoint, IEnumerable<KeyValuePair<string, string>> majorParams, string bucketHash)
private BucketId(string httpMethod, string endpoint, IEnumerable<KeyValuePair<string, string>> majorParameter s, string bucketHash)
{
{
HttpMethod = httpMethod;
HttpMethod = httpMethod;
Endpoint = endpoint;
Endpoint = endpoint;
MajorParams = majorParams.OrderBy(x => x.Key);
MajorParameter s = majorParameter s.OrderBy(x => x.Key);
BucketHash = bucketHash;
BucketHash = bucketHash;
}
}
/// <summary>
/// Creates a new <see cref="BucketId"/> based on the
/// <see cref="HttpMethod"/> and <see cref="Endpoint"/>.
/// </summary>
/// <param name="httpMethod">Http method used to make the request.</param>
/// <param name="endpoint">Endpoint that is going to receive requests.</param>
/// <param name="majorParams">Major parameters of the route of this endpoint.</param>
/// <returns>
/// A <see cref="BucketId"/> based on the <see cref="HttpMethod"/>
/// and the <see cref="Endpoint"> with the provided data.
/// </returns>
public static BucketId Create(string httpMethod, string endpoint, Dictionary<string, string> majorParams)
public static BucketId Create(string httpMethod, string endpoint, Dictionary<string, string> majorParams)
{
{
Preconditions.NotNullOrWhitespace(httpMethod, nameof(httpMethod));
Preconditions.NotNullOrWhitespace(endpoint, nameof(endpoint));
Preconditions.NotNullOrWhitespace(endpoint, nameof(endpoint));
majorParams ??= new Dictionary<string, string>();
majorParams ??= new Dictionary<string, string>();
return new BucketId(httpMethod, endpoint, majorParams, null);
return new BucketId(httpMethod, endpoint, majorParams, null);
}
}
/// <summary>
/// Creates a new <see cref="BucketId"/> based on a
/// <see cref="BucketHash"/> and a previous <see cref="BucketId"/>.
/// </summary>
/// <param name="hash">Bucket hash provided by Discord.</param>
/// <param name="oldBucket"><see cref="BucketId"/> that is going to be upgraded to a hash type.</param>
/// <returns>
/// A <see cref="BucketId"/> based on the <see cref="BucketHash"/>
/// and <see cref="MajorParameters"/>.
/// </returns>
public static BucketId Create(string hash, BucketId oldBucket)
public static BucketId Create(string hash, BucketId oldBucket)
{
{
Preconditions.NotNullOrWhitespace(hash, nameof(hash));
Preconditions.NotNullOrWhitespace(hash, nameof(hash));
Preconditions.NotNull(oldBucket, nameof(oldBucket));
Preconditions.NotNull(oldBucket, nameof(oldBucket));
return new BucketId(null, null, oldBucket.MajorParams, hash);
return new BucketId(null, null, oldBucket.MajorParameter s, hash);
}
}
/// <summary>
/// Gets the string that will define this bucket as a hash based one.
/// </summary>
/// <returns>
/// A <see cref="string"/> that defines this bucket as a hash based one.
/// </returns>
public string GetBucketHash()
public string GetBucketHash()
=> IsHashBucket ? $"{BucketHash}:{string.Join("/", MajorParams.Select(x => x.Value))}" : null;
=> IsHashBucket ? $"{BucketHash}:{string.Join("/", MajorParameter s.Select(x => x.Value))}" : null;
/// <summary>
/// Gets the string that will define this bucket as an endpoint based one.
/// </summary>
/// <returns>
/// A <see cref="string"/> that defines this bucket as an endpoint based one.
/// </returns>
public string GetUniqueEndpoint()
public string GetUniqueEndpoint()
=> HttpMethod != null ? $"{HttpMethod} {Endpoint}" : Endpoint;
=> HttpMethod != null ? $"{HttpMethod} {Endpoint}" : Endpoint;
@@ -47,7 +99,7 @@ namespace Discord.Net
=> Equals(obj as BucketId);
=> Equals(obj as BucketId);
public override int GetHashCode()
public override int GetHashCode()
=> IsHashBucket ? (BucketHash, string.Join("/", MajorParams.Select(x => x.Value))).GetHashCode() : (HttpMethod, Endpoint).GetHashCode();
=> IsHashBucket ? (BucketHash, string.Join("/", MajorParameter s.Select(x => x.Value))).GetHashCode() : (HttpMethod, Endpoint).GetHashCode();
public override string ToString()
public override string ToString()
=> GetBucketHash() ?? GetUniqueEndpoint();
=> GetBucketHash() ?? GetUniqueEndpoint();