Потоки Love защищены: клиент берёт UID из их player/config (со своего IP) и подставляет в n340-поток — играет музыка. LoveStreamResolver + LoveApi. Каталог переведён на n340. Now-playing главного Love Radio по ICY; саб-каналы трек не отдают нигде — показываем без трека. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
32 lines
1.1 KiB
Kotlin
32 lines
1.1 KiB
Kotlin
package com.radiola.data.remote
|
||
|
||
import javax.inject.Inject
|
||
import javax.inject.Singleton
|
||
|
||
/**
|
||
* Потоки Love Radio (n340.com) отдают музыку только с валидным сессионным UID,
|
||
* привязанным к IP клиента. Берём UID с устройства из их player/config и
|
||
* подставляем в URL потока. UID кэшируем (он стабилен в рамках сессии).
|
||
*/
|
||
@Singleton
|
||
class LoveStreamResolver @Inject constructor(
|
||
private val loveApi: LoveApi
|
||
) {
|
||
@Volatile
|
||
private var cachedUid: String? = null
|
||
|
||
private fun isLove(url: String): Boolean =
|
||
url.contains("n340.com") || url.contains("loveradio")
|
||
|
||
suspend fun resolve(url: String): String {
|
||
if (!isLove(url)) return url
|
||
val uid = cachedUid ?: runCatching { loveApi.getConfig().data.uid }
|
||
.getOrNull()
|
||
?.takeIf { it.isNotBlank() }
|
||
?.also { cachedUid = it }
|
||
if (uid.isNullOrBlank()) return url // фолбэк: пусть играет что есть
|
||
val base = url.substringBefore("?")
|
||
return "$base?type=aac&UID=$uid"
|
||
}
|
||
}
|