Advertisement
Guest User

Untitled

a guest
Nov 9th, 2017
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 3.74 KB | None | 0 0
  1. /**
  2.  * Permits Rate limiting in discord based applications
  3.  *
  4.  * @param shouldWait indicates whether or not the interceptor should throw an exception when rate limit is hit
  5.  */
  6. open class RateLimitInterceptor @JvmOverloads constructor(protected val shouldWait: Boolean = false) : Interceptor
  7. {
  8.     @Throws(RateLimitException::class)
  9.     override fun intercept(chain: Interceptor.Chain): Response
  10.     {
  11.         val request = chain.request()
  12.         val requestUrl = request.url().encodedPathSegments()
  13.         val type = requestUrl[2]
  14.         val identifier = requestUrl[3]
  15.         val map = when (type)
  16.         {
  17.             GUILD ->
  18.             {
  19.                 limitsPerGuild
  20.             }
  21.             CHANNELS ->
  22.             {
  23.                 limitsPerChannel
  24.             }
  25.             else ->
  26.             {
  27.                 globalLimits
  28.             }
  29.         }
  30.         var limit = map[identifier]
  31.         if (limit == null)
  32.         {
  33.             limit = Channel(10)
  34.             map[identifier] = limit
  35.         }
  36.         else
  37.         {
  38.             val actualLimit = runBlocking<Limit> { limit!!.receive() }
  39.             if (actualLimit.remaining == 0)
  40.                 waitForLimit(actualLimit)
  41.         }
  42.  
  43.         val response = chain.proceed(request)
  44.         val responseLimit = Limit(response)
  45.         if (responseLimit.reset == null)
  46.         {
  47.             responseLimit.reset = 0
  48.         }
  49.         launch(CommonPool) { limit!!.send(responseLimit) }
  50.         if (response.code() == 429)
  51.         {
  52.             return intercept(chain)
  53.         }
  54.         return response
  55.     }
  56.  
  57.     @Throws(RateLimitException::class)
  58.     protected open fun waitForLimit(limit: Limit)
  59.     {
  60.         if (limit.isExpired)
  61.             return
  62.         if (shouldWait)
  63.             limit.delayUntilReset()
  64.         else
  65.             throw RateLimitException()
  66.     }
  67.  
  68.     companion object
  69.     {
  70.         @JvmStatic
  71.         protected val CHANNELS = "channels"
  72.  
  73.         @JvmStatic
  74.         protected val GUILD = "guilds"
  75.  
  76.         @JvmStatic
  77.         protected val limitsPerGuild: ConcurrentHashMap<String, Channel<Limit>> = ConcurrentHashMap()
  78.  
  79.         @JvmStatic
  80.         protected val limitsPerChannel: ConcurrentHashMap<String, Channel<Limit>> = ConcurrentHashMap()
  81.  
  82.         @JvmStatic
  83.         protected val globalLimits: ConcurrentHashMap<String, Channel<Limit>> = ConcurrentHashMap()
  84.     }
  85.  
  86.     open class Limit(response: Response)
  87.     {
  88.         open val global: Boolean? = response.header(X_RATELIMIT_GLOBAL)?.toBoolean()
  89.         open val limit: Int? = response.header(X_RATELIMIT_LIMIT)?.toInt()
  90.         open val remaining: Int? = response.header(X_RATELIMIT_REMAINING)?.toInt()
  91.         open var reset: Long? = response.header(X_RATELIMIT_RESET)?.toLong()
  92.         open val isExpired: Boolean
  93.             get()
  94.             {
  95.                 return getDelay() <= 0
  96.             }
  97.  
  98.         open fun getDelay(): Long
  99.         {
  100.             val reset = this@Limit.reset ?: throw NullPointerException("Reset epoch was not specified")
  101.             val time = Date().time.div(1000).minus(reset)
  102.             return time
  103.         }
  104.  
  105.         open fun delayUntilReset() = runBlocking<Unit>()
  106.         {
  107.             if (isExpired)
  108.                 return@runBlocking
  109.             val time = getDelay()
  110.             delay(time)
  111.         }
  112.  
  113.         companion object
  114.         {
  115.             @JvmStatic
  116.             protected val X_RATELIMIT_GLOBAL = "X-RateLimit-Global"
  117.             @JvmStatic
  118.             protected val X_RATELIMIT_LIMIT = "X-RateLimit-Limit"
  119.             @JvmStatic
  120.             protected val X_RATELIMIT_REMAINING = "X-RateLimit-REMAINING"
  121.             @JvmStatic
  122.             protected val X_RATELIMIT_RESET = "X-RateLimit-RESET"
  123.         }
  124.     }
  125. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement