Compare commits

...
6 Commits
Author SHA1 Message Date
Li ZongYing c1143afb4e fix ysp 2024-05-20 22:23:16 +08:00
Li ZongYing 68f158e556 fix ysp 2024-05-20 22:08:37 +08:00
Li ZongYing 4ef95d60c4 fix ysp 2024-05-20 22:02:51 +08:00
Li ZongYing b782d1f841 fix some bug 2024-05-16 15:35:48 +08:00
Li ZongYing 7e57aa8c03 fix error in playing 2024-05-16 14:37:16 +08:00
Li ZongYing c16a4bcb9c optimize time 2024-05-09 22:26:37 +08:00
25 changed files with 546 additions and 120 deletions
+24 -1
View File
@@ -37,6 +37,13 @@ jobs:
# override default build-tools version (29.0.3) -- optional # override default build-tools version (29.0.3) -- optional
BUILD_TOOLS_VERSION: "34.0.0" BUILD_TOOLS_VERSION: "34.0.0"
- name: Get History
id: get_history
run: |
chmod +x history.sh
output=$(./history.sh)
echo "$output" > history.md
- name: Create Release - name: Create Release
id: create_release id: create_release
uses: actions/create-release@v1 uses: actions/create-release@v1
@@ -47,6 +54,7 @@ jobs:
release_name: Release ${{ github.ref }} release_name: Release ${{ github.ref }}
draft: false draft: false
prerelease: false prerelease: false
body_path: history.md
- name: Upload Release Asset - name: Upload Release Asset
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
@@ -56,4 +64,19 @@ jobs:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ steps.sign_app.outputs.signedReleaseFile }} asset_path: ${{ steps.sign_app.outputs.signedReleaseFile }}
asset_name: my-tv-${{ github.ref_name }}.apk asset_name: my-tv-${{ github.ref_name }}.apk
asset_content_type: application/vnd.android.package-archive asset_content_type: application/vnd.android.package-archive
- name: Gitee Create Release
run: |
latest_commit=$(git rev-parse HEAD)
history=$(cat history.md)
curl -v POST https://gitee.com/api/v5/repos/${{ github.repository }}/releases \
-H "Content-Type: application/json" \
-d '{
"access_token": "${{ secrets.GITEE_ACCESS_TOKEN}}",
"tag_name": "${{ github.ref_name }}",
"name": "Release ${{ github.ref_name }}",
"body": "'"$history"'",
"prerelease": false,
"target_commitish": "'"$latest_commit"'"
}'
+23 -2
View File
@@ -1,5 +1,26 @@
## 更新日志 ## 更新日志
### v2.0.4
* 修复不能播放的问题
* 包含国际频道
### v2.0.3
* 修复不能播放的问题
* 不包含国际频道
### v2.0.0
* 解决卡顿问题
* 解决网格样式时,点击空白处不退出的问题
* 解决频道列表样式切换可能不生效的问题
### v1.9.8(通用)
* 优化在线升级
* 优化可能状态错误的问题
### v1.9.6(通用) ### v1.9.6(通用)
* 优化在线升级 * 优化在线升级
@@ -41,6 +62,8 @@
* 修复无法播放问题 * 修复无法播放问题
### 以下已不可用
### v1.8.0(通用) ### v1.8.0(通用)
* 修复返回键无法退出问题 * 修复返回键无法退出问题
@@ -176,8 +199,6 @@
* 修复播放失败的问题 * 修复播放失败的问题
### 以下已不可用
### v1.5.3(安卓5及以上专用) ### v1.5.3(安卓5及以上专用)
* 修复部分情况下APP切换后无法继续播放的问题 * 修复部分情况下APP切换后无法继续播放的问题
+1 -1
View File
@@ -14,6 +14,6 @@ gen-version:
git describe --tags --always git describe --tags --always
git describe --tags --always | sed 's/v/ /g' | sed 's/\./ /g' | sed 's/-/ /g' | awk '{print ($$1*16777216)+($$2*65536)+($$3*256)+$$4}' git describe --tags --always | sed 's/v/ /g' | sed 's/\./ /g' | sed 's/-/ /g' | awk '{print ($$1*16777216)+($$2*65536)+($$3*256)+$$4}'
#make gen v=v1.1.3 #make gen v=v2.0.0
gen: gen:
echo $(v) | sed 's/v/ /g' | sed 's/\./ /g' | sed 's/-/ /g' | awk '{print "{\"version_code\": " ($$1*16777216)+($$2*65536)+($$3*256)+$$4 ", \"version_name\": \"" "$(v)" "\"}"}' > version.json echo $(v) | sed 's/v/ /g' | sed 's/\./ /g' | sed 's/-/ /g' | awk '{print "{\"version_code\": " ($$1*16777216)+($$2*65536)+($$3*256)+$$4 ", \"version_name\": \"" "$(v)" "\"}"}' > version.json
+2 -2
View File
@@ -26,7 +26,7 @@
## TODO ## TODO
* 音量不同 * 音量不同
* 大湾区卫视、广东4k超高清、广东珠江、三沙卫视 * 大湾区卫视、广东4k超高清、广东珠江、三沙卫视、翡翠
* CHC高清三个电影频道 * CHC高清三个电影频道
* 地方频道 * 地方频道
* 收藏夹 * 收藏夹
@@ -35,7 +35,7 @@
* 亮度调节 * 亮度调节
* 音量调节 * 音量调节
* 軟解 * 軟解
* 自動更新 * 网格空白处退出
## 版权说明 ## 版权说明
+8 -3
View File
@@ -77,10 +77,9 @@ static def VersionCode() {
def replace = [v: "", ".": " ", "-": " "] def replace = [v: "", ".": " ", "-": " "]
def arr = (process.text.trim().replace(replace) + " 0").split(" ") def arr = (process.text.trim().replace(replace) + " 0").split(" ")
def versionCode = arr[0].toInteger() * 16777216 + arr[1].toInteger() * 65536 + arr[2].toInteger() * 256 + arr[3].toInteger() def versionCode = arr[0].toInteger() * 16777216 + arr[1].toInteger() * 65536 + arr[2].toInteger() * 256 + arr[3].toInteger()
println("VersionCode $versionCode")
return versionCode return versionCode
} catch (ignored) { } catch (ignored) {
return 0 return 1
} }
} }
@@ -88,13 +87,19 @@ static def VersionName() {
try { try {
def process = "git describe --tags --always".execute() def process = "git describe --tags --always".execute()
process.waitFor() process.waitFor()
return process.text.trim() - "v" def versionName = process.text.trim() - "v"
if (versionName.isEmpty()) {
versionName = "1.0.0"
}
return versionName
} catch (ignored) { } catch (ignored) {
return "1.0.0" return "1.0.0"
} }
} }
dependencies { dependencies {
// minSdk17
def media3_version = "1.2.1" def media3_version = "1.2.1"
implementation "androidx.media3:media3-ui:$media3_version" implementation "androidx.media3:media3-ui:$media3_version"
Binary file not shown.
Binary file not shown.
@@ -25,7 +25,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MainActivity : FragmentActivity(), Request.RequestListener { class MainActivity : FragmentActivity(), Request.RequestListener, OnSharedPreferenceChangeListener {
private var ready = 0 private var ready = 0
private val playerFragment = PlayerFragment() private val playerFragment = PlayerFragment()
@@ -122,6 +122,8 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
// Log.i(TAG, "net ${Build.VERSION.SDK_INT}") // Log.i(TAG, "net ${Build.VERSION.SDK_INT}")
// ready++ // ready++
// } // }
SP.setOnSharedPreferenceChangeListener(this)
} }
fun showInfoFragment(tvViewModel: TVViewModel) { fun showInfoFragment(tvViewModel: TVViewModel) {
@@ -358,8 +360,6 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
private val hideSetting = Runnable { private val hideSetting = Runnable {
if (settingFragment.isVisible) { if (settingFragment.isVisible) {
settingFragment.dismiss() settingFragment.dismiss()
showTime()
mainFragment.changeMenu()
} }
} }
@@ -499,7 +499,7 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
} }
KeyEvent.KEYCODE_UNKNOWN -> { KeyEvent.KEYCODE_UNKNOWN -> {
showSetting() // showSetting()
return true return true
} }
@@ -612,4 +612,12 @@ class MainActivity : FragmentActivity(), Request.RequestListener {
private companion object { private companion object {
const val TAG = "MainActivity" const val TAG = "MainActivity"
} }
override fun onSharedPreferenceChanged(key: String) {
Log.i(TAG, "$key changed")
when (key) {
SP.KEY_GRID -> mainFragment.changeMenu()
SP.KEY_TIME -> showTime()
}
}
} }
@@ -2,8 +2,10 @@ package com.lizongying.mytv
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.GestureDetector
import android.view.KeyEvent import android.view.KeyEvent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
@@ -42,10 +44,13 @@ class MainFragment : Fragment(), CardAdapter.ItemListener {
private lateinit var application: MyTvApplication private lateinit var application: MyTvApplication
private lateinit var gestureDetector: GestureDetector
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
val context = requireContext()
_binding = MenuBinding.inflate(inflater, container, false) _binding = MenuBinding.inflate(inflater, container, false)
application = requireActivity().applicationContext as MyTvApplication application = requireActivity().applicationContext as MyTvApplication
@@ -57,9 +62,19 @@ class MainFragment : Fragment(), CardAdapter.ItemListener {
hideSelf() hideSelf()
} }
gestureDetector = GestureDetector(context, GestureListener())
return binding.root return binding.root
} }
private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
Log.i(TAG, "onSingleTapConfirmed")
hideSelf()
return true
}
}
private fun hideSelf() { private fun hideSelf() {
requireActivity().supportFragmentManager.beginTransaction() requireActivity().supportFragmentManager.beginTransaction()
.hide(this) .hide(this)
@@ -134,6 +149,21 @@ class MainFragment : Fragment(), CardAdapter.ItemListener {
hideSelf() hideSelf()
} }
itemBinding.items.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
gestureDetector.onTouchEvent(e)
return false
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {
TODO("Not yet implemented")
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
TODO("Not yet implemented")
}
})
val layoutParamsHeader = val layoutParamsHeader =
itemBinding.header.layoutParams as ViewGroup.MarginLayoutParams itemBinding.header.layoutParams as ViewGroup.MarginLayoutParams
layoutParamsHeader.topMargin = application.px2Px(itemBinding.header.marginTop) layoutParamsHeader.topMargin = application.px2Px(itemBinding.header.marginTop)
@@ -0,0 +1,6 @@
package com.lizongying.mytv
interface OnSharedPreferenceChangeListener {
fun onSharedPreferenceChanged(key: String)
}
@@ -15,6 +15,7 @@ import androidx.media3.common.PlaybackException
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.common.VideoSize import androidx.media3.common.VideoSize
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.DefaultRenderersFactory
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView import androidx.media3.ui.PlayerView
import com.google.android.exoplayer2.SimpleExoPlayer import com.google.android.exoplayer2.SimpleExoPlayer
@@ -52,10 +53,16 @@ class PlayerFragment : Fragment(), SurfaceHolder.Callback {
playerView?.viewTreeObserver?.addOnGlobalLayoutListener(object : playerView?.viewTreeObserver?.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener { ViewTreeObserver.OnGlobalLayoutListener {
@OptIn(UnstableApi::class)
override fun onGlobalLayout() { override fun onGlobalLayout() {
playerView!!.viewTreeObserver.removeOnGlobalLayoutListener(this) playerView!!.viewTreeObserver.removeOnGlobalLayoutListener(this)
// val renderersFactory = context?.let { DefaultRenderersFactory(it) }
// renderersFactory?.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON)
playerView!!.player = activity?.let { playerView!!.player = activity?.let {
ExoPlayer.Builder(it) ExoPlayer.Builder(it)
// .setRenderersFactory(renderersFactory!!)
.build() .build()
} }
playerView!!.player?.playWhenReady = true playerView!!.player?.playWhenReady = true
+20 -4
View File
@@ -13,12 +13,12 @@ object SP {
// If use channel num to select channel or not // If use channel num to select channel or not
private const val KEY_CHANNEL_NUM = "channel_num" private const val KEY_CHANNEL_NUM = "channel_num"
private const val KEY_TIME = "time" const val KEY_TIME = "time"
// If start app on device boot or not // If start app on device boot or not
private const val KEY_BOOT_STARTUP = "boot_startup" private const val KEY_BOOT_STARTUP = "boot_startup"
private const val KEY_GRID = "grid" const val KEY_GRID = "grid"
// Position in list of the selected channel item // Position in list of the selected channel item
private const val KEY_POSITION = "position" private const val KEY_POSITION = "position"
@@ -28,6 +28,8 @@ object SP {
private lateinit var sp: SharedPreferences private lateinit var sp: SharedPreferences
private var listener: OnSharedPreferenceChangeListener? = null
/** /**
* The method must be invoked as early as possible(At least before using the keys) * The method must be invoked as early as possible(At least before using the keys)
*/ */
@@ -35,6 +37,10 @@ object SP {
sp = context.getSharedPreferences(SP_FILE_NAME, Context.MODE_PRIVATE) sp = context.getSharedPreferences(SP_FILE_NAME, Context.MODE_PRIVATE)
} }
fun setOnSharedPreferenceChangeListener(listener: OnSharedPreferenceChangeListener) {
this.listener = listener
}
var channelReversal: Boolean var channelReversal: Boolean
get() = sp.getBoolean(KEY_CHANNEL_REVERSAL, false) get() = sp.getBoolean(KEY_CHANNEL_REVERSAL, false)
set(value) = sp.edit().putBoolean(KEY_CHANNEL_REVERSAL, value).apply() set(value) = sp.edit().putBoolean(KEY_CHANNEL_REVERSAL, value).apply()
@@ -45,7 +51,12 @@ object SP {
var time: Boolean var time: Boolean
get() = sp.getBoolean(KEY_TIME, true) get() = sp.getBoolean(KEY_TIME, true)
set(value) = sp.edit().putBoolean(KEY_TIME, value).apply() set(value) {
if (value != this.time) {
sp.edit().putBoolean(KEY_TIME, value).apply()
listener?.onSharedPreferenceChanged(KEY_TIME)
}
}
var bootStartup: Boolean var bootStartup: Boolean
get() = sp.getBoolean(KEY_BOOT_STARTUP, false) get() = sp.getBoolean(KEY_BOOT_STARTUP, false)
@@ -53,7 +64,12 @@ object SP {
var grid: Boolean var grid: Boolean
get() = sp.getBoolean(KEY_GRID, false) get() = sp.getBoolean(KEY_GRID, false)
set(value) = sp.edit().putBoolean(KEY_GRID, value).apply() set(value) {
if (value != this.grid) {
sp.edit().putBoolean(KEY_GRID, value).apply()
listener?.onSharedPreferenceChanged(KEY_GRID)
}
}
var itemPosition: Int var itemPosition: Int
get() = sp.getInt(KEY_POSITION, 0) get() = sp.getInt(KEY_POSITION, 0)
@@ -1,11 +1,16 @@
package com.lizongying.mytv package com.lizongying.mytv
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.marginEnd import androidx.core.view.marginEnd
import androidx.core.view.marginTop import androidx.core.view.marginTop
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
@@ -87,13 +92,10 @@ class SettingFragment : DialogFragment() {
} }
} }
updateManager = UpdateManager(context, context.appVersionCode) binding.checkVersion.setOnClickListener {
binding.checkVersion.setOnClickListener( (activity as MainActivity).settingDelayHide()
OnClickListenerCheckVersion( requestInstallPermissions()
activity as MainActivity, }
updateManager
)
)
val application = requireActivity().applicationContext as MyTvApplication val application = requireActivity().applicationContext as MyTvApplication
@@ -159,23 +161,67 @@ class SettingFragment : DialogFragment() {
requireActivity().finishAffinity() requireActivity().finishAffinity()
} }
updateManager = UpdateManager(context, context.appVersionCode)
return binding.root return binding.root
} }
fun setVersionName(versionName: String) { private fun requestInstallPermissions() {
if (_binding != null) { val context = requireContext()
binding.versionName.text = versionName val permissionsList: MutableList<String> = ArrayList()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !context.packageManager.canRequestPackageInstalls()) {
permissionsList.add(Manifest.permission.REQUEST_INSTALL_PACKAGES)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
permissionsList.add(Manifest.permission.READ_EXTERNAL_STORAGE)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
ContextCompat.checkSelfPermission(
context,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
permissionsList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
if (permissionsList.isNotEmpty()) {
ActivityCompat.requestPermissions(
requireActivity(),
permissionsList.toTypedArray<String>(),
PERMISSIONS_REQUEST_CODE
)
} else {
updateManager.checkAndUpdate()
} }
} }
internal class OnClickListenerCheckVersion( override fun onRequestPermissionsResult(
private val mainActivity: MainActivity, requestCode: Int,
private val updateManager: UpdateManager permissions: Array<out String>,
) : grantResults: IntArray
View.OnClickListener { ) {
override fun onClick(view: View?) { super.onRequestPermissionsResult(requestCode, permissions, grantResults)
mainActivity.settingDelayHide() if (requestCode == PERMISSIONS_REQUEST_CODE) {
updateManager.checkAndUpdate() var allPermissionsGranted = true
for (result in grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allPermissionsGranted = false
break
}
}
if (allPermissionsGranted) {
updateManager.checkAndUpdate()
} else {
Toast.makeText(context, "权限授权失败", Toast.LENGTH_LONG).show()
}
} }
} }
@@ -186,6 +232,7 @@ class SettingFragment : DialogFragment() {
companion object { companion object {
const val TAG = "SettingFragment" const val TAG = "SettingFragment"
const val PERMISSIONS_REQUEST_CODE = 1
} }
} }
@@ -1,6 +1,5 @@
package com.lizongying.mytv package com.lizongying.mytv
import android.app.Activity
import android.app.DownloadManager import android.app.DownloadManager
import android.app.DownloadManager.Request import android.app.DownloadManager.Request
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
@@ -14,9 +13,6 @@ import android.os.Environment
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.content.PermissionChecker
import androidx.core.content.PermissionChecker.checkSelfPermission
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import com.lizongying.mytv.api.ApiClient import com.lizongying.mytv.api.ApiClient
import com.lizongying.mytv.requests.ReleaseRequest import com.lizongying.mytv.requests.ReleaseRequest
@@ -39,9 +35,6 @@ class UpdateManager(
private var downloadReceiver: DownloadReceiver? = null private var downloadReceiver: DownloadReceiver? = null
fun checkAndUpdate() { fun checkAndUpdate() {
if (!haveStoragePermission()) {
return
}
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
var text = "版本获取失败" var text = "版本获取失败"
var update = false var update = false
@@ -68,39 +61,9 @@ class UpdateManager(
dialog.show((context as FragmentActivity).supportFragmentManager, TAG) dialog.show((context as FragmentActivity).supportFragmentManager, TAG)
} }
private fun haveStoragePermission(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
=== PermissionChecker.PERMISSION_GRANTED
) {
Log.e("Permission error", "You have permission")
return true
} else {
Log.e("Permission error", "You have asked for permission")
ActivityCompat.requestPermissions(
context as Activity, arrayOf(
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
), 1
)
return false
}
} else { //you don't need to worry about these stuff below api level 23
Log.e("Permission error", "You already have the permission")
return true
}
}
private fun startDownload(release: ReleaseResponse) { private fun startDownload(release: ReleaseResponse) {
val packageInstaller = context.packageManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!packageInstaller.canRequestPackageInstalls()) {
}
}
val apkName = "my-tv" val apkName = "my-tv"
val apkFileName = "$apkName-${release.version_name}.apk" val apkFileName = "$apkName-${release.version_name}.apk"
Log.i(TAG, "apkFileName $apkFileName")
val downloadManager = val downloadManager =
context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val request = val request =
@@ -2,7 +2,6 @@ package com.lizongying.mytv
import android.content.res.Resources import android.content.res.Resources
import android.os.Build import android.os.Build
import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import com.google.gson.Gson import com.google.gson.Gson
import com.lizongying.mytv.api.TimeResponse import com.lizongying.mytv.api.TimeResponse
@@ -37,13 +36,14 @@ object Utils {
} }
suspend fun init() { suspend fun init() {
var currentTimeMillis: Long = 0
try { try {
currentTimeMillis = getTimestampFromServer() val currentTimeMillis = getTimestampFromServer()
if (currentTimeMillis > 0) {
between = System.currentTimeMillis() - currentTimeMillis
}
} catch (e: Exception) { } catch (e: Exception) {
println("Failed to retrieve timestamp from server: ${e.message}") println("Failed to retrieve timestamp from server: ${e.message}")
} }
between = System.currentTimeMillis() - currentTimeMillis
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
listener?.onRequestFinished(null) listener?.onRequestFinished(null)
@@ -71,8 +71,6 @@ object Utils {
private suspend fun getTimestampFromServer(): Long { private suspend fun getTimestampFromServer(): Long {
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
val client = okhttp3.OkHttpClient.Builder() val client = okhttp3.OkHttpClient.Builder()
.connectTimeout(500, java.util.concurrent.TimeUnit.MILLISECONDS)
.readTimeout(1, java.util.concurrent.TimeUnit.SECONDS)
.addInterceptor(RetryInterceptor(3)) .addInterceptor(RetryInterceptor(3))
.build() .build()
val request = okhttp3.Request.Builder() val request = okhttp3.Request.Builder()
@@ -85,7 +83,6 @@ object Utils {
Gson().fromJson(string, TimeResponse::class.java).data.t.toLong() Gson().fromJson(string, TimeResponse::class.java).data.t.toLong()
} }
} catch (e: IOException) { } catch (e: IOException) {
// Handle network errors
throw IOException("Error during network request", e) throw IOException("Error during network request", e)
} }
} }
@@ -24,6 +24,7 @@ class ApiClient {
private val protoUrl = "https://capi.yangshipin.cn/" private val protoUrl = "https://capi.yangshipin.cn/"
private val traceUrl = "https://btrace.yangshipin.cn/" private val traceUrl = "https://btrace.yangshipin.cn/"
private val trace2Url = "https://aatc-api.yangshipin.cn/" private val trace2Url = "https://aatc-api.yangshipin.cn/"
private val tokenUrl = "https://h5access.yangshipin.cn/"
private val trace3Url = "https://dtrace.ysp.cctv.cn/" private val trace3Url = "https://dtrace.ysp.cctv.cn/"
private val jceUrl = "https://jacc.ysp.cctv.cn/" private val jceUrl = "https://jacc.ysp.cctv.cn/"
private val fUrl = "https://m.fengshows.com/" private val fUrl = "https://m.fengshows.com/"
@@ -78,6 +79,14 @@ class ApiClient {
.build().create(YSPBtraceService::class.java) .build().create(YSPBtraceService::class.java)
} }
val yspToken2Service: YSPApiService by lazy {
Retrofit.Builder()
.baseUrl(tokenUrl)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build().create(YSPApiService::class.java)
}
val yspBtraceService3: YSPBtraceService by lazy { val yspBtraceService3: YSPBtraceService by lazy {
Retrofit.Builder() Retrofit.Builder()
.baseUrl(trace3Url) .baseUrl(trace3Url)
@@ -157,7 +166,7 @@ class ApiClient {
val sslContext = SSLContext.getInstance("SSL") val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, java.security.SecureRandom()) sslContext.init(null, trustAllCerts, java.security.SecureRandom())
val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("10.0.2.2", 8888)) // val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("10.0.2.2", 8888))
val builder = OkHttpClient.Builder() val builder = OkHttpClient.Builder()
.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager) .sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
@@ -1,17 +1,17 @@
package com.lizongying.mytv.api package com.lizongying.mytv.api
data class KvcollectRequest( data class KvcollectRequest(
val BossId: Int = 2727, val BossId: Int = 99150,
val Pwd: Int = 1424084450, val Pwd: Int = 1999332929,
val cdn: String = "waibao", val cdn: String = "waibao",
val cmd: Int = 263, val cmd: Int = 263,
val defn: String = "fhd", val defn: String = "fhd",
val downspeed: Double = 10.0, val downspeed: Int = 10,
val durl: String = "", // val durl: String = "", //
val errcode: String = "", val errcode: String = "",
val fact1: String = "ysp_pc_live_b", val fact1: String = "ysp_pc_live_b",
val firstreport: Int = 0, val firstreport: Int = 0,
val fplayerver: String = "100", val fplayerver: String = "180",
val ftime: String = "", // val ftime: String = "", //
val geturltime: Int = 0, val geturltime: Int = 0,
val guid: String = "", // val guid: String = "", //
@@ -39,17 +39,17 @@ data class KvcollectRequest(
data class KvcollectRequest2( data class KvcollectRequest2(
val BossId: Int = 2727, val BossId: Int = 99150,
val Pwd: Int = 1424084450, val Pwd: Int = 1999332929,
val cdn: String = "waibao", val cdn: String = "waibao",
val cmd: Int = 263, val cmd: Int = 263,
val defn: String = "fhd", val defn: String = "fhd",
val downspeed: String = "10", val downspeed: Int = 10,
val durl: String = "", // val durl: String = "", //
val errcode: String = "", val errcode: String = "",
val fact1: String = "ysp_pc_live_b", val fact1: String = "ysp_pc_live_b",
val firstreport: Int = 0, val firstreport: Int = 0,
val fplayerver: String = "100", val fplayerver: String = "180",
val ftime: String = "", // val ftime: String = "", //
val geturltime: Int = 0, val geturltime: Int = 0,
val guid: String = "", // val guid: String = "", //
@@ -68,9 +68,9 @@ data class KvcollectRequest2(
val sRef: String = "", val sRef: String = "",
val sUrl: String = "", // val sUrl: String = "", //
val sdtfrom: String = "ysp_pc_01", val sdtfrom: String = "ysp_pc_01",
val seq: Int = 9, // val seq: Int = 0, //
var signature: String = "", var signature: String = "",
val url: String = "", // val url: String = "", //
val viewid: String = "", // val viewid: String = "", //
val _dc: Double = 0.0, val _dc: String = "",
) )
@@ -0,0 +1,11 @@
package com.lizongying.mytv.api
data class Token2(
val ret: Int?,
val msg: String?,
val data: Data,
) {
data class Data(
val token: String,
)
}
@@ -1,9 +1,11 @@
package com.lizongying.mytv.api package com.lizongying.mytv.api
import android.content.Context import android.content.Context
import android.util.Log
import com.lizongying.mytv.SP import com.lizongying.mytv.SP
import com.lizongying.mytv.Utils.getDateTimestamp import com.lizongying.mytv.Utils.getDateTimestamp
import com.lizongying.mytv.models.TVViewModel import com.lizongying.mytv.models.TVViewModel
import java.security.MessageDigest
import kotlin.math.floor import kotlin.math.floor
import kotlin.random.Random import kotlin.random.Random
@@ -52,6 +54,13 @@ object YSP {
private var appid = "ysp_pc" private var appid = "ysp_pc"
var token = "" var token = ""
var token2 = ""
var yspsdkinput = ""
var openapi_signature = ""
var nseqId = 1
var nrequest_id = ""
private var encryptor = Encryptor() private var encryptor = Encryptor()
@@ -75,10 +84,43 @@ object YSP {
cKey = cKey =
encryptor.encrypt(cnlid, timeStr, appVer, guid, platform) encryptor.encrypt(cnlid, timeStr, appVer, guid, platform)
randStr = getRand()
signature = getSignature() signature = getSignature()
return """{"cnlid":"$cnlid","livepid":"$livepid","stream":"$stream","guid":"$guid","cKey":"$cKey","adjust":$adjust,"sphttps":"$sphttps","platform":"$platform","cmd":"$cmd","encryptVer":"$encryptVer","dtype":"$dtype","devid":"$devid","otype":"$otype","appVer":"$appVer","app_version":"$appVersion","rand_str":"$randStr","channel":"$channel","defn":"$defn","signature":"$signature"}""" return """{"cnlid":"$cnlid","livepid":"$livepid","stream":"$stream","guid":"$guid","cKey":"$cKey","adjust":$adjust,"sphttps":"$sphttps","platform":"$platform","cmd":"$cmd","encryptVer":"$encryptVer","dtype":"$dtype","devid":"$devid","otype":"$otype","appVer":"$appVer","app_version":"$appVersion","rand_str":"$randStr","channel":"$channel","defn":"$defn","signature":"$signature"}"""
} }
fun getTokenData(tvModel: TVViewModel) {
livepid = tvModel.getTV().pid
cnlid = tvModel.getTV().sid
defn = "fhd"
randStr = getRand()
if (tvModel.retryTimes > 0) {
guid = newGuid()
}
cKey =
encryptor.encrypt(cnlid, timeStr, appVer, guid, platform)
Log.i(TAG,"yspsdkinput ${"""{"cnlid":"$cnlid","livepid":"$livepid","stream":"$stream","guid":"$guid","cKey":"$cKey","adjust":$adjust,"sphttps":"$sphttps","platform":"$platform","cmd":"$cmd","encryptVer":"$encryptVer","dtype":"$dtype","devid":"$devid","otype":"$otype","appVer":"$appVer","app_version":"$appVersion","channel":"$channel","defn":"$defn"}"""}" )
yspsdkinput = md("adjust=$adjust&app_version=$appVersion&appVer=$appVer&channel=$channel&cKey=$cKey&cmd=$cmd&cnlid=$cnlid&defn=$defn&devid=$devid&dtype=$dtype&encryptVer=$encryptVer&guid=$guid&livepid=$livepid&otype=$otype&platform=$platform&sphttps=$sphttps&stream=$stream")
nseqId++
nrequest_id = "999999" + getRand() + getTimeStr()
openapi_signature = md("yspappid:519748109;host:www.yangshipin.cn;protocol:https:;token:$token2;input:$yspsdkinput-$guid-$nseqId-$nrequest_id;")
}
fun md(str:String):String {
val md = MessageDigest.getInstance("MD5")
md.update(str.toByteArray())
val digest = md.digest()
return digest.let { it -> it.joinToString("") { "%02x".format(it) } }
}
fun getAuthData(tvModel: TVViewModel): String { fun getAuthData(tvModel: TVViewModel): String {
livepid = tvModel.getTV().pid livepid = tvModel.getTV().pid
@@ -92,7 +134,7 @@ object YSP {
return """pid=$livepid&guid=$guid&appid=$appid&rand_str=$randStr&signature=$signature""" return """pid=$livepid&guid=$guid&appid=$appid&rand_str=$randStr&signature=$signature"""
} }
private fun getTimeStr(): String { fun getTimeStr(): String {
return getDateTimestamp().toString() return getDateTimestamp().toString()
} }
@@ -2,9 +2,11 @@ package com.lizongying.mytv.api
import retrofit2.Call import retrofit2.Call
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header import retrofit2.http.Header
import retrofit2.http.Headers import retrofit2.http.Headers
import retrofit2.http.POST import retrofit2.http.POST
import retrofit2.http.Query
interface YSPApiService { interface YSPApiService {
@@ -18,6 +20,11 @@ interface YSPApiService {
fun getLiveInfo( fun getLiveInfo(
@Header("cookie") cookie: String, @Header("cookie") cookie: String,
@Header("Yspplayertoken") token: String, @Header("Yspplayertoken") token: String,
@Header("Yspsdkinput") Yspsdkinput: String,
@Header("yspsdksign") yspsdksign: String,
@Header("Seqid") Seqid: String,
@Header("Request-Id") RequestId: String,
@Header("Yspappid") Yspappid: String="519748109",
@Body request: LiveInfoRequest, @Body request: LiveInfoRequest,
): Call<LiveInfo> ): Call<LiveInfo>
@@ -32,4 +39,20 @@ interface YSPApiService {
@Header("cookie") cookie: String, @Header("cookie") cookie: String,
@Body request: AuthRequest, @Body request: AuthRequest,
): Call<Auth> ): Call<Auth>
@GET("web/open/token")
@Headers(
"content-type: application/json",
"referer: https://www.yangshipin.cn/",
"user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
)
fun getToken(
@Header("cookie") cookie: String,
@Query("yspappid") yspappid: String = "519748109",
@Query("guid") guid: String = "",
@Query("vappid") vappid: String = "59306155",
@Query("vsecret") vsecret: String = "b42702bf7309a179d102f3d51b1add2fda0bc7ada64cb801",
@Query("raw") raw: String = "1",
@Query("ts") ts: String = "",
): Call<Token2>
} }
@@ -87,8 +87,8 @@ interface YSPBtraceService {
"referer: https://www.yangshipin.cn/", "referer: https://www.yangshipin.cn/",
) )
fun kvcollect3( fun kvcollect3(
@Field("BossId") BossId: String = "9141", @Field("BossId") BossId: String = "9150",
@Field("Pwd") Pwd: String = "1137850982", @Field("Pwd") Pwd: String = "1999332929",
@Field("prog") prog: String = "", // @Field("prog") prog: String = "", //
@Field("playno") playno: String = "", // @Field("playno") playno: String = "", //
@Field("guid") guid: String = "", // @Field("guid") guid: String = "", //
@@ -102,7 +102,7 @@ interface YSPBtraceService {
@Field("firstreport") firstreport: String = "-", @Field("firstreport") firstreport: String = "-",
@Field("sUrl") sUrl: String = "", // @Field("sUrl") sUrl: String = "", //
@Field("sRef") sRef: String = "-", @Field("sRef") sRef: String = "-",
@Field("fplayerver") fplayerver: String = "100", @Field("fplayerver") fplayerver: String = "180",
@Field("livepid") livepid: String = "", @Field("livepid") livepid: String = "",
@Field("viewid") viewid: String = "", @Field("viewid") viewid: String = "",
@Field("seq") seq: String = "", @Field("seq") seq: String = "",
@@ -118,8 +118,8 @@ interface YSPBtraceService {
@Field("_dc") _dc: String = "", @Field("_dc") _dc: String = "",
@Field("live_type") live_type: String = "-", @Field("live_type") live_type: String = "-",
@Field("ftime") ftime: String = "", @Field("ftime") ftime: String = "",
@Field("url") url: String = "", // @Field("url") url: String = "",
@Field("rand_str") rand_str: String = "", // // @Field("rand_str") rand_str: String = "", //
@Field("signature") signature: String = "", // @Field("signature") signature: String = "",
): Call<Void> ): Call<Void>
} }
@@ -15,7 +15,7 @@ class TVViewModel(private var tv: TV) : ViewModel() {
private var itemPosition: Int = 0 private var itemPosition: Int = 0
var retryTimes = 0 var retryTimes = 0
var retryMaxTimes = 8 var retryMaxTimes = 1
var authYSPRetryTimes = 0 var authYSPRetryTimes = 0
var authYSPRetryMaxTimes = 3 var authYSPRetryMaxTimes = 3
var tokenYSPRetryTimes = 0 var tokenYSPRetryTimes = 0
@@ -18,6 +18,7 @@ import com.lizongying.mytv.api.KvcollectRequest
import com.lizongying.mytv.api.KvcollectRequest2 import com.lizongying.mytv.api.KvcollectRequest2
import com.lizongying.mytv.api.LiveInfo import com.lizongying.mytv.api.LiveInfo
import com.lizongying.mytv.api.LiveInfoRequest import com.lizongying.mytv.api.LiveInfoRequest
import com.lizongying.mytv.api.Token2
import com.lizongying.mytv.api.YSP import com.lizongying.mytv.api.YSP
import com.lizongying.mytv.api.YSPApiService import com.lizongying.mytv.api.YSPApiService
import com.lizongying.mytv.api.YSPBtraceService import com.lizongying.mytv.api.YSPBtraceService
@@ -42,6 +43,7 @@ import kotlin.random.Random
object Request { object Request {
private const val TAG = "Request" private const val TAG = "Request"
private var yspTokenService: YSPTokenService = ApiClient().yspTokenService private var yspTokenService: YSPTokenService = ApiClient().yspTokenService
private var yspToken2Service: YSPApiService = ApiClient().yspToken2Service
private var yspApiService: YSPApiService = ApiClient().yspApiService private var yspApiService: YSPApiService = ApiClient().yspApiService
private var yspBtraceService: YSPBtraceService = ApiClient().yspBtraceService private var yspBtraceService: YSPBtraceService = ApiClient().yspBtraceService
private var yspBtraceService2: YSPBtraceService = ApiClient().yspBtraceService2 private var yspBtraceService2: YSPBtraceService = ApiClient().yspBtraceService2
@@ -56,6 +58,7 @@ object Request {
private var needAuth = true private var needAuth = true
private var needToken = false private var needToken = false
private var needToken2 = true
private val handler = Handler(Looper.getMainLooper()) private val handler = Handler(Looper.getMainLooper())
private lateinit var btraceRunnable: BtraceRunnable private lateinit var btraceRunnable: BtraceRunnable
@@ -74,6 +77,7 @@ object Request {
} }
private var call: Call<LiveInfo>? = null private var call: Call<LiveInfo>? = null
private var callToken: Call<Token2>? = null
private var callAuth: Call<Auth>? = null private var callAuth: Call<Auth>? = null
private var callInfo: Call<Info>? = null private var callInfo: Call<Info>? = null
private var callFAuth: Call<FAuth>? = null private var callFAuth: Call<FAuth>? = null
@@ -84,11 +88,117 @@ object Request {
private fun cancelCall() { private fun cancelCall() {
call?.cancel() call?.cancel()
callAuth?.cancel() callAuth?.cancel()
callToken?.cancel()
callInfo?.cancel() callInfo?.cancel()
callFAuth?.cancel() callFAuth?.cancel()
callPage?.cancel() callPage?.cancel()
} }
private fun fetchToken(tvModel: TVViewModel, cookie: String) {
cancelCall()
val title = tvModel.getTV().title
callToken = yspToken2Service.getToken("guid=${YSP.getGuid()}; $cookie", "519748109", YSP.getGuid(), "59306155", "b42702bf7309a179d102f3d51b1add2fda0bc7ada64cb801" ,"1", YSP.getTimeStr())
callToken?.enqueue(object : Callback<Token2> {
override fun onResponse(call: Call<Token2>, response: Response<Token2>) {
if (response.isSuccessful) {
val liveInfo = response.body()
if (liveInfo?.data?.token != null) {
Log.i(TAG, "token ${liveInfo.data.token}")
YSP.token2 = liveInfo.data.token
YSP.getTokenData(tvModel)
fetchAuth(tvModel, cookie)
} else {
Log.e(TAG, "$title token error")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
if (tvModel.getTV().needToken) {
if (needToken && tvModel.tokenYSPRetryTimes < tvModel.tokenYSPRetryMaxTimes) {
tvModel.tokenYSPRetryTimes++
tvModel.needGetToken = true
fetchToken(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
fetchToken(tvModel, cookie)
} else {
val err = "错误"
Log.e(TAG, "$title $err")
tvModel.setErrInfo(err)
}
}
} else {
fetchToken(tvModel, cookie)
}
} else {
val err = "认证结果错误"
Log.e(TAG, "$title $err")
tvModel.setErrInfo(err)
}
}
} else {
Log.e(TAG, "$title token status error")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
if (tvModel.getTV().needToken) {
if (needToken && tvModel.tokenYSPRetryTimes < tvModel.tokenYSPRetryMaxTimes) {
tvModel.tokenYSPRetryTimes++
tvModel.needGetToken = true
fetchToken(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
fetchToken(tvModel, cookie)
} else {
val err = "错误"
Log.e(TAG, "$title $err")
tvModel.setErrInfo(err)
}
}
} else {
fetchToken(tvModel, cookie)
}
} else {
val err = "认证状态错误"
Log.e(TAG, "$title $err")
tvModel.setErrInfo(err)
}
}
}
override fun onFailure(call: Call<Token2>, t: Throwable) {
Log.e(TAG, "$title token request error $t")
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++
if (tvModel.getTV().needToken) {
if (needToken && tvModel.tokenYSPRetryTimes < tvModel.tokenYSPRetryMaxTimes) {
tvModel.tokenYSPRetryTimes++
tvModel.needGetToken = true
fetchToken(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
fetchToken(tvModel, cookie)
} else {
val err = "错误"
Log.e(TAG, "$title $err")
tvModel.setErrInfo(err)
}
}
} else {
fetchToken(tvModel, cookie)
}
} else {
val err = "认证请求错误"
Log.e(TAG, "$title $err")
tvModel.setErrInfo(err)
}
}
})
}
private fun fetchAuth(tvModel: TVViewModel, cookie: String) { private fun fetchAuth(tvModel: TVViewModel, cookie: String) {
cancelCall() cancelCall()
@@ -103,11 +213,11 @@ object Request {
val liveInfo = response.body() val liveInfo = response.body()
if (liveInfo?.data?.token != null) { if (liveInfo?.data?.token != null) {
Log.i(TAG, "token ${liveInfo.data.token}") Log.i(TAG, "auth ${liveInfo.data.token}")
YSP.token = liveInfo.data.token YSP.token = liveInfo.data.token
fetchVideo(tvModel, cookie) fetchVideo(tvModel, cookie)
} else { } else {
Log.e(TAG, "$title token error") Log.e(TAG, "$title auth error")
if (tvModel.retryTimes < tvModel.retryMaxTimes) { if (tvModel.retryTimes < tvModel.retryMaxTimes) {
tvModel.retryTimes++ tvModel.retryTimes++
if (tvModel.getTV().needToken) { if (tvModel.getTV().needToken) {
@@ -206,8 +316,13 @@ object Request {
val request = LiveInfoRequest(data) val request = LiveInfoRequest(data)
call = request.let { call = request.let {
yspApiService.getLiveInfo( yspApiService.getLiveInfo(
"guid=${YSP.getGuid()}; $cookie", "guid=${YSP.getGuid()}; gr_user_id=261eecf2-0ce4-4316-a6a1-7171e3de7389; $cookie; newLogin=1; nseqId=${YSP.nseqId}; nrequest-id=${YSP.nrequest_id}",
YSP.token, YSP.token,
YSP.yspsdkinput,
YSP.openapi_signature,
"${YSP.nseqId}",
YSP.nrequest_id,
"519748109",
it it
) )
} }
@@ -392,6 +507,66 @@ object Request {
}) })
} }
private fun fetchToken(tvModel: TVViewModel) {
cancelCall()
if (tvModel.needGetToken) {
callInfo = yspTokenService.getInfo("")
callInfo?.enqueue(object : Callback<Info> {
override fun onResponse(call: Call<Info>, response: Response<Info>) {
if (response.isSuccessful && response.body()?.data?.token != null) {
token = response.body()?.data?.token!!
Log.i(TAG, "info success $token")
tvModel.needGetToken = false
tvModel.tokenYSPRetryTimes = 0
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=124; appid=1400421205; yspappid=519748109;yspopenid=$openid; vusession=$token"
fetchAuth(tvModel, cookie)
} else if (response.code() == 304) {
tvModel.needGetToken = false
tvModel.tokenYSPRetryTimes = 0
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=124; appid=1400421205; yspappid=519748109; yspopenid=$openid; vusession=$token"
fetchVideo(tvModel, cookie)
} else {
Log.e(TAG, "info status error")
if (tvModel.tokenYSPRetryTimes < tvModel.tokenYSPRetryMaxTimes) {
tvModel.tokenYSPRetryTimes++
fetchToken(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=124; appid=1400421205; yspappid=519748109"
fetchToken(tvModel, cookie)
} else {
// TODO
}
}
}
}
override fun onFailure(call: Call<Info>, t: Throwable) {
Log.e(TAG, "info request error $t")
if (tvModel.tokenYSPRetryTimes < tvModel.tokenYSPRetryMaxTimes) {
tvModel.tokenYSPRetryTimes++
fetchAuth(tvModel)
} else {
if (!tvModel.getTV().mustToken) {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=124; appid=1400421205; yspappid=519748109"
fetchToken(tvModel, cookie)
} else {
// TODO
}
}
}
})
} else {
val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=124; appid=1400421205; yspappid=519748109;yspopenid=$openid; vusession=$token"
fetchToken(tvModel, cookie)
}
}
private fun fetchAuth(tvModel: TVViewModel) { private fun fetchAuth(tvModel: TVViewModel) {
cancelCall() cancelCall()
if (tvModel.needGetToken) { if (tvModel.needGetToken) {
@@ -447,7 +622,7 @@ object Request {
}) })
} else { } else {
val cookie = val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=120; appid=1400421205; yspappid=519748109;yspopenid=$openid; vusession=$token" "versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=124; yspopenid=$openid; vusession=$token"
fetchAuth(tvModel, cookie) fetchAuth(tvModel, cookie)
} }
} }
@@ -569,19 +744,42 @@ object Request {
if (token == "") { if (token == "") {
tvModel.needGetToken = true tvModel.needGetToken = true
} }
if (needAuth) { if (needToken2) {
fetchAuth(tvModel) if (needAuth) {
fetchToken(tvModel)
} else {
fetchAuth(tvModel)
}
} else { } else {
fetchVideo(tvModel) if (needAuth) {
fetchAuth(tvModel)
} else {
fetchVideo(tvModel)
}
} }
} else { } else {
val cookie = val cookie =
"versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; updateProtocol=1; deviceModel=120" "versionName=99.99.99; versionCode=999999; vplatform=109; platformVersion=Chrome; deviceModel=124"
if (needAuth) {
fetchAuth(tvModel, cookie) if (needToken2) {
if (needAuth) {
fetchToken(tvModel, cookie)
} else {
fetchAuth(tvModel, cookie)
}
} else { } else {
fetchVideo(tvModel, cookie) if (needAuth) {
fetchAuth(tvModel, cookie)
} else {
fetchVideo(tvModel, cookie)
}
} }
//
// if (needAuth) {
// fetchAuth(tvModel, cookie)
// } else {
// fetchVideo(tvModel, cookie)
// }
} }
} }
@@ -700,7 +898,7 @@ object Request {
seq = tvModel.seq, seq = tvModel.seq,
durl = url, durl = url,
url = url, url = url,
_dc = randomNumber, // _dc = "",
) )
val e = val e =
@@ -732,7 +930,7 @@ object Request {
val guid = YSP.getGuid() val guid = YSP.getGuid()
val pid = tvModel.getTV().pid val pid = tvModel.getTV().pid
val sid = tvModel.getTV().sid val sid = tvModel.getTV().sid
val randomNumber = Random.nextDouble() // val randomNumber = Random.nextDouble()
val url = tvModel.getTV().videoUrl.first() val url = tvModel.getTV().videoUrl.first()
val r = KvcollectRequest2( val r = KvcollectRequest2(
@@ -747,12 +945,12 @@ object Request {
seq = tvModel.seq, seq = tvModel.seq,
durl = url, durl = url,
url = url, url = url,
_dc = randomNumber, _dc = "",
) )
val e = // val e =
"BossId=${r.BossId}&Pwd=${r.Pwd}&_dc=${r._dc}&cdn=${r.cdn}&cmd=${r.cmd}&defn=${r.defn}&downspeed=${r.downspeed}&durl=${r.durl}&errcode=${r.errcode}&fact1=${r.fact1}&firstreport=${r.firstreport}&fplayerver=${r.fplayerver}&ftime=${r.ftime}&geturltime=${r.geturltime}&guid=${r.guid}&hc_openid=${r.hc_openid}&hh_ua=${r.hh_ua}&live_type=${r.live_type}&livepid=${r.livepid}&login_type=${r.login_type}&open_id=${r.open_id}&openid=${r.openid}&platform=${r.platform}&playno=${r.playno}&prd=${r.prd}&prog=${r.prog}&rand_str=${r.rand_str}&sRef=${r.sRef}&sUrl=${r.sUrl}&sdtfrom=${r.sdtfrom}&seq=${r.seq}&url=${r.url}&viewid=${r.viewid}" // "BossId=${r.BossId}&Pwd=${r.Pwd}&_dc=${r._dc}&cdn=${r.cdn}&cmd=${r.cmd}&defn=${r.defn}&downspeed=${r.downspeed}&durl=${r.durl}&errcode=${r.errcode}&fact1=${r.fact1}&firstreport=${r.firstreport}&fplayerver=${r.fplayerver}&ftime=${r.ftime}&geturltime=${r.geturltime}&guid=${r.guid}&hc_openid=${r.hc_openid}&hh_ua=${r.hh_ua}&live_type=${r.live_type}&livepid=${r.livepid}&login_type=${r.login_type}&open_id=${r.open_id}&openid=${r.openid}&platform=${r.platform}&playno=${r.playno}&prd=${r.prd}&prog=${r.prog}&rand_str=${r.rand_str}&sRef=${r.sRef}&sUrl=${r.sUrl}&sdtfrom=${r.sdtfrom}&seq=${r.seq}&url=${r.url}&viewid=${r.viewid}"
r.signature = YSP.getAuthSignature(e) // r.signature = YSP.getAuthSignature(e)
callBtracePage = yspBtraceService3.kvcollect3( callBtracePage = yspBtraceService3.kvcollect3(
guid = r.guid, guid = r.guid,
@@ -761,18 +959,18 @@ object Request {
livepid = r.livepid, livepid = r.livepid,
sUrl = r.sUrl, sUrl = r.sUrl,
playno = r.playno, playno = r.playno,
rand_str = r.rand_str, // rand_str = r.rand_str,
ftime = r.ftime, ftime = r.ftime,
seq = "${r.seq}", seq = "${r.seq}",
durl = r.durl, durl = r.durl,
url = r.url, // url = r.url,
_dc = "${r._dc}", _dc = "${r._dc}",
signature = r.signature // signature = r.signature
) )
callBtracePage?.enqueue(object : Callback<Void> { callBtracePage?.enqueue(object : Callback<Void> {
override fun onResponse(call: Call<Void>, response: Response<Void>) { override fun onResponse(call: Call<Void>, response: Response<Void>) {
if (response.isSuccessful) { if (response.isSuccessful) {
Log.d(TAG, "$title kvcollect success") Log.i(TAG, "$title kvcollect success")
} else { } else {
Log.e(TAG, "$title kvcollect status error") Log.e(TAG, "$title kvcollect status error")
} }
Executable
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
in_changelog=false
while IFS= read -r line; do
if [[ "$line" == "## "* ]]; then
continue
fi
if [[ $in_changelog == false ]] && [[ "$line" == "### "* ]]; then
in_changelog=true
continue
fi
if [[ $in_changelog == true ]] && [[ "$line" == "### "* ]]; then
break
fi
echo "$line"
done < HISTORY.md
+1 -1
View File
@@ -1 +1 @@
{"version_code": 17368576, "version_name": "v1.9.6"} {"version_code": 33555456, "version_name": "v2.0.4"}