my-tv/app/src/main/java/com/lizongying/mytv/Request.kt

208 lines
8.4 KiB
Kotlin
Raw Normal View History

2023-12-15 13:04:32 +08:00
package com.lizongying.mytv
import android.content.Context
2023-12-15 18:12:11 +08:00
import android.util.Base64
2023-12-15 13:04:32 +08:00
import android.util.Log
import com.lizongying.mytv.api.ApiClient
import com.lizongying.mytv.api.LiveInfo
import com.lizongying.mytv.api.LiveInfoRequest
import com.lizongying.mytv.api.ProtoClient
import com.lizongying.mytv.api.YSP
import com.lizongying.mytv.api.YSPApiService
import com.lizongying.mytv.api.YSPProtoService
import com.lizongying.mytv.models.TVViewModel
import com.lizongying.mytv.proto.Ysp.cn.yangshipin.oms.common.proto.pageModel
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
2023-12-15 18:12:11 +08:00
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
2023-12-15 13:04:32 +08:00
class Request(var context: Context) {
private var ysp: YSP? = null
private var yspApiService: YSPApiService? = null
private var yspProtoService: YSPProtoService? = null
private var mapping = mapOf(
"CCTV4K" to "CCTV4K",
"CCTV1" to "CCTV1 综合",
"CCTV2" to "CCTV2 财经",
"CCTV4" to "CCTV4 中文国际",
"CCTV5" to "CCTV5 体育",
"CCTV5+" to "CCTV5+ 体育赛事",
"CCTV7" to "CCTV7 国防军事",
"CCTV9" to "CCTV9 记录",
"CCTV10" to "CCTV10 科教",
"CCTV11" to "CCTV11 戏曲",
"CCTV12" to "CCTV12 社会与法",
2023-12-18 10:12:52 +08:00
"CCTV13" to "CCTV13 新闻",
2023-12-15 13:04:32 +08:00
"CCTV14" to "CCTV14 少儿",
"CCTV15" to "CCTV15 音乐",
"CCTV16-HD" to "CCTV16 奥林匹克",
"CCTV17" to "CCTV17 农业农村",
"CGTN" to "CGTN",
2023-12-18 10:12:52 +08:00
"CGTN外语纪录频道" to "CGTN 纪录频道",
2023-12-15 13:04:32 +08:00
"CGTN法语频道" to "CGTN 法语频道",
"CGTN俄语频道" to "CGTN 俄语频道",
"CGTN阿拉伯语频道" to "CGTN 阿拉伯语频道",
"CGTN西班牙语频道" to "CGTN 西班牙语频道",
"东方卫视" to "东方卫视",
"湖南卫视" to "湖南卫视",
"湖北卫视" to "湖北卫视",
"辽宁卫视" to "辽宁卫视",
"江苏卫视" to "江苏卫视",
"江西卫视" to "江西卫视",
"山东卫视" to "山东卫视",
"广东卫视" to "广东卫视",
"广西卫视" to "广西卫视",
"重庆卫视" to "重庆卫视",
"河南卫视" to "河南卫视",
"河北卫视" to "河北卫视",
"贵州卫视" to "贵州卫视",
"北京卫视" to "北京卫视",
"黑龙江卫视" to "黑龙江卫视",
"浙江卫视" to "浙江卫视",
"安徽卫视" to "安徽卫视",
"深圳卫视" to "深圳卫视",
"四川卫视" to "四川卫视",
"福建东南卫视" to "东南卫视",
"海南卫视" to "海南卫视",
)
init {
if (context is MainActivity) {
ysp = YSP(context)
}
yspApiService = ApiClient().yspApiService
yspProtoService = ProtoClient().yspProtoService
}
fun fetchData(tvModel: TVViewModel) {
val data = ysp?.switch(tvModel)
2023-12-18 10:12:52 +08:00
val title = tvModel.getTV().title
2023-12-15 13:04:32 +08:00
val request = data?.let { LiveInfoRequest(it) }
request?.let { yspApiService?.getLiveInfo(it) }
?.enqueue(object : Callback<LiveInfo> {
override fun onResponse(call: Call<LiveInfo>, response: Response<LiveInfo>) {
if (response.isSuccessful) {
val liveInfo = response.body()
if (liveInfo?.data?.playurl != null) {
2023-12-15 18:12:11 +08:00
val chanll = liveInfo.data.chanll
val decodedBytes = Base64.decode(
chanll.substring(9, chanll.length - 3),
Base64.DEFAULT
)
val decodedString = String(decodedBytes)
val regex = Regex("""des_key = "([^"]+).+var des_iv = "([^"]+)""")
val matchResult = regex.find(decodedString)
if (matchResult != null) {
val (key, iv) = matchResult.destructured
2023-12-18 10:12:52 +08:00
val keyBytes = Base64.decode(key, Base64.DEFAULT)
val ivBytes = Base64.decode(iv, Base64.DEFAULT)
val url = liveInfo.data.playurl + "&revoi=" + encryptTripleDES(
2023-12-16 08:19:02 +08:00
keyBytes + byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
2023-12-15 18:12:11 +08:00
ivBytes
2023-12-16 08:19:02 +08:00
).uppercase()
2023-12-18 10:12:52 +08:00
Log.i(TAG, "$title url $url")
tvModel.addVideoUrl(url)
} else {
Log.e(TAG, "$title key error")
tvModel.firstSource()
}
} else {
2023-12-18 12:47:21 +08:00
Log.e(TAG, "$title url error $request")
2023-12-18 10:12:52 +08:00
tvModel.firstSource()
2023-12-15 13:04:32 +08:00
}
2023-12-18 10:12:52 +08:00
} else {
Log.e(TAG, "$title status error")
tvModel.firstSource()
2023-12-15 13:04:32 +08:00
}
}
override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
2023-12-18 10:12:52 +08:00
Log.e(TAG, "${tvModel.getTV().title} request error")
tvModel.firstSource()
2023-12-15 13:04:32 +08:00
}
})
}
fun fetchPage() {
yspProtoService?.getPage()?.enqueue(object : Callback<pageModel.Response> {
override fun onResponse(
call: Call<pageModel.Response>,
response: Response<pageModel.Response>
) {
if (response.isSuccessful) {
val body = response.body()
if (body?.data?.feedModuleListCount == 1) {
for (item in body.data?.feedModuleListList!![0]?.dataTvChannelListList!!) {
if (item.isVip && !item.isLimitedFree) {
continue
}
Log.i(
TAG,
"${item.channelName} ,${item.tvLogo},${item.pid},${item.streamId}"
)
var channelType = "央视频道"
if (item?.channelType === "weishi") {
channelType = "地方频道"
}
if (!mapping.containsKey(item.channelName)) {
continue
}
val tv = TVList.list[channelType]?.get(mapping[item.channelName])
if (tv != null) {
tv.logo = item.tvLogo
tv.pid = item.pid
tv.sid = item.streamId
}
}
}
}
}
override fun onFailure(call: Call<pageModel.Response>, t: Throwable) {
Log.e(TAG, "Page request failed", t)
}
})
}
fun fetchProgram(tvModel: TVViewModel) {
yspProtoService?.getProgram("", "")?.enqueue(object : Callback<LiveInfo> {
override fun onResponse(call: Call<LiveInfo>, response: Response<LiveInfo>) {
if (response.isSuccessful) {
val liveInfo = response.body()
Log.i(TAG, "${liveInfo?.data?.playurl}")
}
}
override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
}
})
}
2023-12-15 18:12:11 +08:00
private fun encryptTripleDES(key: ByteArray, iv: ByteArray): String {
2023-12-16 08:19:02 +08:00
var plaintext =
2023-12-15 18:12:11 +08:00
"""{"mver":"1","subver":"1.2","host":"www.yangshipin.cn/#/tv/home?pid=","referer":"","canvas":"YSPANGLE(Apple,AppleM1Pro,OpenGL4.1)"}"""
return try {
val keySpec = SecretKeySpec(key, "DESede")
val ivSpec = IvParameterSpec(iv)
2023-12-16 08:19:02 +08:00
val cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding")
2023-12-15 18:12:11 +08:00
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
val encryptedBytes = cipher.doFinal(plaintext.toByteArray())
2023-12-16 08:19:02 +08:00
return encryptedBytes.let { it -> it.joinToString("") { "%02x".format(it) } }
2023-12-15 18:12:11 +08:00
} catch (e: Exception) {
e.printStackTrace()
""
}
}
2023-12-15 13:04:32 +08:00
companion object {
private const val TAG = "Request"
}
}