Skip to content

Commit 1a45f38

Browse files
committed
support m3u headers
1 parent 769b2e7 commit 1a45f38

File tree

12 files changed

+197
-140
lines changed

12 files changed

+197
-140
lines changed

HISTORY.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
## 更新日誌
22

3+
### v1.3.9.0
4+
5+
* 支持socks代理
6+
* 支持m3u設置headers
7+
8+
### v1.3.8.17-kitkat
9+
10+
* 優化LOGO緩存
11+
312
### v1.3.8.17
413

514
* 優化LOGO緩存

app/src/main/java/com/lizongying/mytv0/MainViewModel.kt

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class MainViewModel : ViewModel() {
4141
private var timeFormat = if (SP.displaySeconds) "HH:mm:ss" else "HH:mm"
4242

4343
private lateinit var appDirectory: File
44-
var listModel: List<TVModel> = listOf()
44+
var listModel: List<TVModel> = emptyList()
4545
val groupModel = TVGroupModel()
4646
private var cacheFile: File? = null
4747
private var cacheChannels = ""
@@ -396,10 +396,9 @@ class MainViewModel : ViewModel() {
396396
'[' -> {
397397
try {
398398
list = gson.fromJson(string, typeTvList)
399-
Log.i(TAG, "导入频道 ${list.size}")
399+
Log.i(TAG, "导入频道 ${list.size} $list")
400400
} catch (e: Exception) {
401-
Log.i(TAG, "parse error $string")
402-
Log.i(TAG, e.message, e)
401+
Log.e(TAG, "str2Channels", e)
403402
return false
404403
}
405404
}
@@ -413,41 +412,55 @@ class MainViewModel : ViewModel() {
413412

414413
val l = mutableListOf<TV>()
415414
val tvMap = mutableMapOf<String, List<TV>>()
416-
for ((index, line) in lines.withIndex()) {
415+
416+
var tv = TV()
417+
for (line in lines) {
417418
val trimmedLine = line.trim()
419+
if (trimmedLine.isEmpty()) {
420+
continue
421+
}
418422
if (trimmedLine.startsWith("#EXTM3U")) {
419423
epgUrl = epgRegex.find(trimmedLine)?.groupValues?.get(1)?.trim()
420424
} else if (trimmedLine.startsWith("#EXTINF")) {
425+
Log.i(TAG, "TV $tv")
426+
val key = tv.group + tv.name
427+
if (key.isNotEmpty()) {
428+
tvMap[key] =
429+
if (!tvMap.containsKey(key)) listOf(tv) else tvMap[key]!! + tv
430+
}
431+
tv = TV()
421432
val info = trimmedLine.split(",")
422-
val title = info.last().trim()
433+
tv.title = info.last().trim()
423434
var name = nameRegex.find(info.first())?.groupValues?.get(1)?.trim()
424-
name = name ?: title
425-
var group = groupRegex.find(info.first())?.groupValues?.get(1)?.trim()
426-
group = group ?: ""
427-
val logo = logRegex.find(info.first())?.groupValues?.get(1)?.trim()
428-
val uris =
429-
if (index + 1 < lines.size) listOf(lines[index + 1].trim()) else emptyList()
430-
val tv = TV(
431-
-1,
432-
name,
433-
title,
434-
"",
435-
logo ?: "",
436-
"",
437-
uris,
438-
0,
439-
mapOf(),
440-
group,
441-
SourceType.UNKNOWN,
442-
listOf(),
443-
)
444-
445-
if (!tvMap.containsKey(group + name)) {
446-
tvMap[group + name] = listOf()
435+
tv.name = if (name.isNullOrEmpty()) tv.title else name
436+
tv.logo = logRegex.find(info.first())?.groupValues?.get(1)?.trim() ?: ""
437+
tv.group = groupRegex.find(info.first())?.groupValues?.get(1)?.trim() ?: ""
438+
} else if (trimmedLine.startsWith("#EXTVLCOPT:http-")) {
439+
val keyValue =
440+
trimmedLine.substringAfter("#EXTVLCOPT:http-").split("=", limit = 2)
441+
if (keyValue.size == 2) {
442+
tv.headers = if (tv.headers == null) {
443+
mapOf<String, String>(keyValue[0] to keyValue[1])
444+
} else {
445+
tv.headers!!.toMutableMap().apply {
446+
this[keyValue[0]] = keyValue[1]
447+
}
448+
}
449+
}
450+
} else if (!trimmedLine.startsWith("#")) {
451+
tv.uris = if (tv.uris.isEmpty()) {
452+
listOf(trimmedLine)
453+
} else {
454+
tv.uris.toMutableList().apply {
455+
this.add(trimmedLine)
456+
}
447457
}
448-
tvMap[group + name] = tvMap[group + name]!! + tv
449458
}
450459
}
460+
val key = tv.group + tv.name
461+
if (key.isNotEmpty()) {
462+
tvMap[key] = if (!tvMap.containsKey(key)) listOf(tv) else tvMap[key]!! + tv
463+
}
451464
for ((_, tv) in tvMap) {
452465
val uris = tv.map { t -> t.uris }.flatten()
453466
val t0 = tv[0]
@@ -460,15 +473,15 @@ class MainViewModel : ViewModel() {
460473
"",
461474
uris,
462475
0,
463-
mapOf(),
476+
t0.headers,
464477
t0.group,
465478
SourceType.UNKNOWN,
466-
listOf(),
479+
emptyList(),
467480
)
468481
l.add(t1)
469482
}
470483
list = l
471-
Log.i(TAG, "导入频道 ${list.size}")
484+
Log.i(TAG, "导入频道 ${list.size} $list")
472485
}
473486

474487
else -> {
@@ -489,11 +502,11 @@ class MainViewModel : ViewModel() {
489502
val title = arr.first().trim()
490503
val uris = arr.drop(1)
491504

492-
if (!tvMap.containsKey(group + title)) {
493-
tvMap[group + title] = listOf()
494-
tvMap[group + title] = tvMap[group + title]!! + group
505+
val key = group + title
506+
if (!tvMap.containsKey(key)) {
507+
tvMap[key] = listOf(group)
495508
}
496-
tvMap[group + title] = tvMap[group + title]!! + uris
509+
tvMap[key] = tvMap[key]!! + uris
497510
}
498511
}
499512
}
@@ -509,10 +522,10 @@ class MainViewModel : ViewModel() {
509522
"",
510523
uris,
511524
0,
512-
mapOf(),
525+
emptyMap(),
513526
channelGroup,
514527
SourceType.UNKNOWN,
515-
listOf(),
528+
emptyList(),
516529
)
517530

518531
l.add(tv)

app/src/main/java/com/lizongying/mytv0/SimpleServer.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,10 @@ class SimpleServer(private val context: Context, private val viewModel: MainView
191191
if (req.proxy != null) {
192192
SP.proxy = req.proxy
193193
R.string.default_proxy_set_success.showToast()
194+
Log.i(TAG, "set proxy success")
194195
} else {
195196
R.string.default_proxy_set_failure.showToast()
197+
Log.i(TAG, "set proxy failure")
196198
}
197199
}
198200
}

app/src/main/java/com/lizongying/mytv0/Utils.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,18 +141,15 @@ object Utils {
141141
}
142142

143143
fun formatUrl(url: String): String {
144-
// Check if the URL already starts with "http://" or "https://"
145-
if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("file://")) {
144+
if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("file://") || url.startsWith("socks://") || url.startsWith("socks5://")) {
146145
return url
147146
}
148147

149-
// Check if the URL starts with "//"
150148
if (url.startsWith("//")) {
151-
return "http://$url"
149+
return "http:$url"
152150
}
153151

154-
// Otherwise, add "http://" to the beginning of the URL
155-
return "http://${url}"
152+
return "http://$url"
156153
}
157154

158155
fun getUrls(url: String): List<String> {

app/src/main/java/com/lizongying/mytv0/data/TV.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ data class TV(
99
var description: String? = null,
1010
var logo: String = "",
1111
var image: String? = null,
12-
var uris: List<String>,
12+
var uris: List<String> = emptyList(),
1313
var videoIndex: Int = 0,
1414
var headers: Map<String, String>? = null,
1515
var group: String = "",
1616
var sourceType: SourceType = SourceType.UNKNOWN,
17-
var child: List<TV>,
17+
var child: List<TV> = emptyList(),
1818
) : Serializable {
1919

2020
override fun toString(): String {
@@ -25,8 +25,8 @@ data class TV(
2525
", description='" + description + '\'' +
2626
", logo='" + logo + '\'' +
2727
", image='" + image + '\'' +
28-
", uris='" + uris + '\'' +
29-
", headers='" + headers + '\'' +
28+
", uris=" + uris +
29+
", headers=" + headers +
3030
", group='" + group + '\'' +
3131
", sourceType='" + sourceType + '\'' +
3232
'}'

app/src/main/java/com/lizongying/mytv0/models/Sources.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Sources {
2727
val sources: LiveData<List<Source>>
2828
get() = _sources
2929
private val sourcesValue: List<Source>
30-
get() = _sources.value ?: listOf()
30+
get() = _sources.value ?: emptyList()
3131

3232
private val _checked = MutableLiveData<Int>()
3333
val checked: LiveData<Int>

app/src/main/java/com/lizongying/mytv0/models/TVGroupModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class TVGroupModel : ViewModel() {
1414
val tvGroup: LiveData<List<TVListModel>>
1515
get() = _tvGroup
1616
val tvGroupValue: List<TVListModel>
17-
get() = _tvGroup.value ?: listOf()
17+
get() = _tvGroup.value ?: emptyList()
1818

1919
private val _position = MutableLiveData<Int>()
2020
val position: LiveData<Int>

app/src/main/java/com/lizongying/mytv0/models/TVListModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class TVListModel(private val name: String, private val groupIndex: Int) : ViewM
3434
val tvList: LiveData<List<TVModel>>
3535
get() = _tvList
3636
private val tvListValue: List<TVModel>
37-
get() = _tvList.value ?: listOf()
37+
get() = _tvList.value ?: emptyList()
3838

3939
private val _position = MutableLiveData<Int>()
4040
val position: LiveData<Int>

app/src/main/java/com/lizongying/mytv0/models/TVModel.kt

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ import androidx.lifecycle.ViewModel
88
import androidx.media3.common.MediaItem
99
import androidx.media3.common.util.UnstableApi
1010
import androidx.media3.datasource.DataSource
11-
import androidx.media3.datasource.DefaultHttpDataSource
11+
import androidx.media3.datasource.okhttp.OkHttpDataSource
1212
import androidx.media3.datasource.rtmp.RtmpDataSource
1313
import androidx.media3.exoplayer.dash.DashMediaSource
1414
import androidx.media3.exoplayer.hls.HlsMediaSource
1515
import androidx.media3.exoplayer.rtsp.RtspMediaSource
1616
import androidx.media3.exoplayer.source.MediaSource
1717
import androidx.media3.exoplayer.source.ProgressiveMediaSource
18-
import com.lizongying.mytv0.IgnoreSSLCertificate
1918
import com.lizongying.mytv0.SP
2019
import com.lizongying.mytv0.data.EPG
2120
import com.lizongying.mytv0.data.Program
2221
import com.lizongying.mytv0.data.SourceType
2322
import com.lizongying.mytv0.data.TV
23+
import com.lizongying.mytv0.requests.HttpClient
2424
import kotlin.math.max
2525
import kotlin.math.min
2626

@@ -119,15 +119,9 @@ class TVModel(var tv: TV) : ViewModel() {
119119
val path = uri.path ?: return@let null
120120
val scheme = uri.scheme ?: return@let null
121121

122-
// val okHttpDataSource = OkHttpDataSource.Factory(HttpClient.okHttpClient)
123-
// httpDataSource = okHttpDataSource
124-
125-
IgnoreSSLCertificate.ignore()
126-
val defaultHttpDataSource = DefaultHttpDataSource.Factory()
127-
defaultHttpDataSource.setKeepPostFor302Redirects(true)
128-
defaultHttpDataSource.setAllowCrossProtocolRedirects(true)
122+
val okHttpDataSource = OkHttpDataSource.Factory(HttpClient.okHttpClient)
129123
tv.headers?.let { i ->
130-
defaultHttpDataSource.setDefaultRequestProperties(i)
124+
okHttpDataSource.setDefaultRequestProperties(i)
131125
i.forEach { (key, value) ->
132126
if (key.equals("user-agent", ignoreCase = true)) {
133127
userAgent = value
@@ -136,7 +130,7 @@ class TVModel(var tv: TV) : ViewModel() {
136130
}
137131
}
138132

139-
_httpDataSource = defaultHttpDataSource
133+
_httpDataSource = okHttpDataSource
140134

141135
sourceTypeList = if (path.lowercase().endsWith(".m3u8")) {
142136
listOf(SourceType.HLS)

0 commit comments

Comments
 (0)