@@ -13,6 +13,8 @@ import com.lagradost.cloudstream3.utils.newExtractorLink
1313import java.util.EnumSet
1414import javax.crypto.Mac
1515import javax.crypto.spec.SecretKeySpec
16+ import kotlinx.coroutines.sync.Mutex
17+ import kotlinx.coroutines.sync.withLock
1618
1719class AnimeVerseProvider : MainAPI () {
1820 override var mainUrl = " https://animeverse.to"
@@ -35,6 +37,9 @@ class AnimeVerseProvider : MainAPI() {
3537 private var catalogCache: List <CatalogItem >? = null
3638 private var cacheTimestamp: Long = 0
3739
40+ private val sessionMutex = Mutex ()
41+ private val catalogMutex = Mutex ()
42+
3843 // Custom browser fingerprint parameters accepted by the API
3944 private val fingerprint = mapOf (
4045 " ua" to " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ,
@@ -86,29 +91,35 @@ class AnimeVerseProvider : MainAPI() {
8691
8792 // Requests a signed API session — retries up to 3 times since the server is flaky
8893 private suspend fun establishSession () {
89- var lastError: Exception ? = null
90- repeat(3 ) { attempt ->
91- try {
92- val response = app.post(
93- " $mainUrl /api/v1/session" ,
94- json = mapOf (" fp" to fingerprint),
95- headers = mapOf (
96- " User-Agent" to fingerprint[" ua" ].toString(),
97- " Referer" to " $mainUrl /"
94+ sessionMutex.withLock {
95+ val currentTime = System .currentTimeMillis() / 1000
96+ if (clientAuthKey != null && currentTime < expiresAt) {
97+ return
98+ }
99+ var lastError: Exception ? = null
100+ repeat(3 ) { attempt ->
101+ try {
102+ val response = app.post(
103+ " $mainUrl /api/v1/session" ,
104+ json = mapOf (" fp" to fingerprint),
105+ headers = mapOf (
106+ " User-Agent" to fingerprint[" ua" ].toString(),
107+ " Referer" to " $mainUrl /"
108+ )
98109 )
99- )
100- val res = localMapper.readValue(response.text, SessionResponse :: class .java)
101- clientAuthKey = res.clientAuthKey
102- expiresAt = res.expiresAt
103- sessionCookies = response.cookies
104- return // success — exit early
105- } catch (e : Exception ) {
106- lastError = e
107- // brief pause before next attempt
108- kotlinx.coroutines.delay((attempt + 1 ) * 1000L )
110+ val res = localMapper.readValue(response.text, SessionResponse :: class .java )
111+ clientAuthKey = res.clientAuthKey
112+ expiresAt = res.expiresAt
113+ sessionCookies = response.cookies
114+ return // success — exit early
115+ } catch (e : Exception ) {
116+ lastError = e
117+ // brief pause before next attempt
118+ kotlinx.coroutines.delay(( attempt + 1 ) * 1000L )
119+ }
109120 }
121+ throw lastError ? : Exception (" Failed to establish session after 3 attempts" )
110122 }
111- throw lastError ? : Exception (" Failed to establish session after 3 attempts" )
112123 }
113124
114125 // Signed GET — re-establishes session when expired or missing
@@ -137,17 +148,24 @@ class AnimeVerseProvider : MainAPI() {
137148 return cache
138149 }
139150
140- return try {
141- val jsonText = signedGet(" /api/v1/catalog" )
142- val response = localMapper.readValue(jsonText, CatalogResponse ::class .java)
143- val items = response.items.filter { it.slug.isNotEmpty() && it.title.isNotEmpty() }
144- catalogCache = items
145- cacheTimestamp = current
146- Log .d(" AnimeVerse" , " Catalog loaded: ${items.size} items" )
147- items
148- } catch (e: Exception ) {
149- Log .e(" AnimeVerse" , " getCatalog FAILED: ${e.javaClass.simpleName} : ${e.message} " )
150- emptyList()
151+ return catalogMutex.withLock {
152+ val doubleCheckCache = catalogCache
153+ if (doubleCheckCache != null && System .currentTimeMillis() - cacheTimestamp < 10 * 60 * 1000 ) {
154+ return @withLock doubleCheckCache
155+ }
156+
157+ try {
158+ val jsonText = signedGet(" /api/v1/catalog" )
159+ val response = localMapper.readValue(jsonText, CatalogResponse ::class .java)
160+ val items = response.items.filter { it.slug.isNotEmpty() && it.title.isNotEmpty() }
161+ catalogCache = items
162+ cacheTimestamp = System .currentTimeMillis()
163+ Log .d(" AnimeVerse" , " Catalog loaded: ${items.size} items" )
164+ items
165+ } catch (e: Exception ) {
166+ Log .e(" AnimeVerse" , " getCatalog FAILED: ${e.javaClass.simpleName} : ${e.message} " )
167+ emptyList()
168+ }
151169 }
152170 }
153171
0 commit comments