using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; namespace Discord.Net { /// /// Represents a ratelimit bucket. /// public class BucketId : IEquatable { /// /// Gets the http method used to make the request if available. /// public string HttpMethod { get; } /// /// Gets the endpoint that is going to be requested if available. /// public string Endpoint { get; } /// /// Gets the major parameters of the route. /// public IOrderedEnumerable> MajorParameters { get; } /// /// Gets the hash of this bucket. /// /// /// The hash is provided by Discord to group ratelimits. /// public string BucketHash { get; } /// /// Gets if this bucket is a hash type. /// public bool IsHashBucket { get => BucketHash != null; } private BucketId(string httpMethod, string endpoint, IEnumerable> majorParameters, string bucketHash) { HttpMethod = httpMethod; Endpoint = endpoint; MajorParameters = majorParameters.OrderBy(x => x.Key); BucketHash = bucketHash; } /// /// Creates a new based on the /// and . /// /// Http method used to make the request. /// Endpoint that is going to receive requests. /// Major parameters of the route of this endpoint. /// /// A based on the /// and the with the provided data. /// public static BucketId Create(string httpMethod, string endpoint, Dictionary majorParams) { Preconditions.NotNullOrWhitespace(endpoint, nameof(endpoint)); majorParams ??= new Dictionary(); return new BucketId(httpMethod, endpoint, majorParams, null); } /// /// Creates a new based on a /// and a previous . /// /// Bucket hash provided by Discord. /// that is going to be upgraded to a hash type. /// /// A based on the /// and . /// public static BucketId Create(string hash, BucketId oldBucket) { Preconditions.NotNullOrWhitespace(hash, nameof(hash)); Preconditions.NotNull(oldBucket, nameof(oldBucket)); return new BucketId(null, null, oldBucket.MajorParameters, hash); } /// /// Gets the string that will define this bucket as a hash based one. /// /// /// A that defines this bucket as a hash based one. /// public string GetBucketHash() => IsHashBucket ? $"{BucketHash}:{string.Join("/", MajorParameters.Select(x => x.Value))}" : null; /// /// Gets the string that will define this bucket as an endpoint based one. /// /// /// A that defines this bucket as an endpoint based one. /// public string GetUniqueEndpoint() => HttpMethod != null ? $"{HttpMethod} {Endpoint}" : Endpoint; public override bool Equals(object obj) => Equals(obj as BucketId); public override int GetHashCode() => IsHashBucket ? (BucketHash, string.Join("/", MajorParameters.Select(x => x.Value))).GetHashCode() : (HttpMethod, Endpoint).GetHashCode(); public override string ToString() => GetBucketHash() ?? GetUniqueEndpoint(); public bool Equals(BucketId other) { if (other is null) return false; if (ReferenceEquals(this, other)) return true; if (GetType() != other.GetType()) return false; return ToString() == other.ToString(); } } }