mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	pull the rate limit interceptors from the extensions repo (#5163)
apply a rate limit to anilist, current limit is 90 per minute
This commit is contained in:
		| @@ -8,6 +8,7 @@ import com.afollestad.date.year | ||||
| import eu.kanade.tachiyomi.data.database.models.Track | ||||
| import eu.kanade.tachiyomi.data.track.model.TrackSearch | ||||
| import eu.kanade.tachiyomi.network.POST | ||||
| import eu.kanade.tachiyomi.network.RateLimitInterceptor | ||||
| import eu.kanade.tachiyomi.network.await | ||||
| import eu.kanade.tachiyomi.network.jsonMime | ||||
| import eu.kanade.tachiyomi.network.parseAs | ||||
| @@ -27,10 +28,14 @@ import kotlinx.serialization.json.putJsonObject | ||||
| import okhttp3.OkHttpClient | ||||
| import okhttp3.RequestBody.Companion.toRequestBody | ||||
| import java.util.Calendar | ||||
| import java.util.concurrent.TimeUnit.MINUTES | ||||
|  | ||||
| class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { | ||||
|  | ||||
|     private val authClient = client.newBuilder().addInterceptor(interceptor).build() | ||||
|     private val authClient = client.newBuilder() | ||||
|         .addInterceptor(interceptor) | ||||
|         .addInterceptor(RateLimitInterceptor(85, 1, MINUTES)) | ||||
|         .build() | ||||
|  | ||||
|     suspend fun addLibManga(track: Track): Track { | ||||
|         return withIOContext { | ||||
|   | ||||
| @@ -0,0 +1,59 @@ | ||||
| package eu.kanade.tachiyomi.network | ||||
|  | ||||
| import android.os.SystemClock | ||||
| import okhttp3.Interceptor | ||||
| import okhttp3.Response | ||||
| import timber.log.Timber | ||||
| import java.util.concurrent.TimeUnit | ||||
|  | ||||
| /** | ||||
|  * An OkHttp interceptor that handles rate limiting. | ||||
|  * | ||||
|  * Examples: | ||||
|  * | ||||
|  * permits = 5,  period = 1, unit = seconds  =>  5 requests per second | ||||
|  * permits = 10, period = 2, unit = minutes  =>  10 requests per 2 minutes | ||||
|  * | ||||
|  * @param permits {Int}   Number of requests allowed within a period of units. | ||||
|  * @param period {Long}   The limiting duration. Defaults to 1. | ||||
|  * @param unit {TimeUnit} The unit of time for the period. Defaults to seconds. | ||||
|  */ | ||||
| class RateLimitInterceptor( | ||||
|     private val permits: Int, | ||||
|     private val period: Long = 1, | ||||
|     private val unit: TimeUnit = TimeUnit.SECONDS | ||||
| ) : Interceptor { | ||||
|  | ||||
|     private val requestQueue = ArrayList<Long>(permits) | ||||
|     private val rateLimitMillis = unit.toMillis(period) | ||||
|  | ||||
|     override fun intercept(chain: Interceptor.Chain): Response { | ||||
|         synchronized(requestQueue) { | ||||
|             val now = SystemClock.elapsedRealtime() | ||||
|             val waitTime = if (requestQueue.size < permits) { | ||||
|                 0 | ||||
|             } else { | ||||
|                 val oldestReq = requestQueue[0] | ||||
|                 val newestReq = requestQueue[permits - 1] | ||||
|  | ||||
|                 if (newestReq - oldestReq > rateLimitMillis) { | ||||
|                     0 | ||||
|                 } else { | ||||
|                     oldestReq + rateLimitMillis - now // Remaining time | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (requestQueue.size == permits) { | ||||
|                 requestQueue.removeAt(0) | ||||
|             } | ||||
|             if (waitTime > 0) { | ||||
|                 requestQueue.add(now + waitTime) | ||||
|                 Thread.sleep(waitTime) // Sleep inside synchronized to pause queued requests | ||||
|             } else { | ||||
|                 requestQueue.add(now) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return chain.proceed(chain.request()) | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,65 @@ | ||||
| package eu.kanade.tachiyomi.network | ||||
|  | ||||
| import android.os.SystemClock | ||||
| import okhttp3.HttpUrl | ||||
| import okhttp3.Interceptor | ||||
| import okhttp3.Response | ||||
| import java.util.concurrent.TimeUnit | ||||
|  | ||||
| /** | ||||
|  * An OkHttp interceptor that handles given url host's rate limiting. | ||||
|  * | ||||
|  * Examples: | ||||
|  * | ||||
|  * httpUrl = "api.manga.com".toHttpUrlOrNull(), permits = 5, period = 1, unit = seconds  =>  5 requests per second to api.manga.com | ||||
|  * httpUrl = "imagecdn.manga.com".toHttpUrlOrNull(), permits = 10, period = 2, unit = minutes  =>  10 requests per 2 minutes to imagecdn.manga.com | ||||
|  * | ||||
|  * @param httpUrl {HttpUrl} The url host that this interceptor should handle. Will get url's host by using HttpUrl.host() | ||||
|  * @param permits {Int}   Number of requests allowed within a period of units. | ||||
|  * @param period {Long}   The limiting duration. Defaults to 1. | ||||
|  * @param unit {TimeUnit} The unit of time for the period. Defaults to seconds. | ||||
|  */ | ||||
| class SpecificHostRateLimitInterceptor( | ||||
|     private val httpUrl: HttpUrl, | ||||
|     private val permits: Int, | ||||
|     private val period: Long = 1, | ||||
|     private val unit: TimeUnit = TimeUnit.SECONDS | ||||
| ) : Interceptor { | ||||
|  | ||||
|     private val requestQueue = ArrayList<Long>(permits) | ||||
|     private val rateLimitMillis = unit.toMillis(period) | ||||
|     private val host = httpUrl.host | ||||
|  | ||||
|     override fun intercept(chain: Interceptor.Chain): Response { | ||||
|         if (chain.request().url.host != host) { | ||||
|             return chain.proceed(chain.request()) | ||||
|         } | ||||
|         synchronized(requestQueue) { | ||||
|             val now = SystemClock.elapsedRealtime() | ||||
|             val waitTime = if (requestQueue.size < permits) { | ||||
|                 0 | ||||
|             } else { | ||||
|                 val oldestReq = requestQueue[0] | ||||
|                 val newestReq = requestQueue[permits - 1] | ||||
|  | ||||
|                 if (newestReq - oldestReq > rateLimitMillis) { | ||||
|                     0 | ||||
|                 } else { | ||||
|                     oldestReq + rateLimitMillis - now // Remaining time | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (requestQueue.size == permits) { | ||||
|                 requestQueue.removeAt(0) | ||||
|             } | ||||
|             if (waitTime > 0) { | ||||
|                 requestQueue.add(now + waitTime) | ||||
|                 Thread.sleep(waitTime) // Sleep inside synchronized to pause queued requests | ||||
|             } else { | ||||
|                 requestQueue.add(now) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return chain.proceed(chain.request()) | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user