直播兼容txt格式
This commit is contained in:
+84
-2
@@ -70,7 +70,9 @@ export async function refreshLiveChannels(liveInfo: {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
const result = parseM3U(liveInfo.key, data);
|
const result = isM3UContent(data)
|
||||||
|
? parseM3U(liveInfo.key, data)
|
||||||
|
: parseTxtLive(liveInfo.key, data);
|
||||||
const epgUrl = liveInfo.epg || result.tvgUrl;
|
const epgUrl = liveInfo.epg || result.tvgUrl;
|
||||||
const tvgIds = result.channels
|
const tvgIds = result.channels
|
||||||
.map((channel) => channel.tvgId)
|
.map((channel) => channel.tvgId)
|
||||||
@@ -367,6 +369,86 @@ function parseEpgLines(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stripBom(value: string) {
|
||||||
|
return value.replace(/^\uFEFF/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isM3UContent(content: string) {
|
||||||
|
const normalized = stripBom(content).trim();
|
||||||
|
return normalized.includes('#EXTM3U') || normalized.includes('#EXTINF');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isHttpUrl(value: string) {
|
||||||
|
return /^https?:\/\//i.test(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseTxtLive(
|
||||||
|
sourceKey: string,
|
||||||
|
txtContent: string
|
||||||
|
): {
|
||||||
|
tvgUrl: string;
|
||||||
|
channels: {
|
||||||
|
id: string;
|
||||||
|
tvgId: string;
|
||||||
|
name: string;
|
||||||
|
logo: string;
|
||||||
|
group: string;
|
||||||
|
url: string;
|
||||||
|
}[];
|
||||||
|
} {
|
||||||
|
const channels: {
|
||||||
|
id: string;
|
||||||
|
tvgId: string;
|
||||||
|
name: string;
|
||||||
|
logo: string;
|
||||||
|
group: string;
|
||||||
|
url: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
const lines = txtContent
|
||||||
|
.split('\n')
|
||||||
|
.map((line) => stripBom(line).trim())
|
||||||
|
.filter((line) => line.length > 0);
|
||||||
|
|
||||||
|
let currentGroup = '无分组';
|
||||||
|
let channelIndex = 0;
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const commaIndex = line.indexOf(',');
|
||||||
|
if (commaIndex === -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = line.slice(0, commaIndex).trim();
|
||||||
|
const value = line.slice(commaIndex + 1).trim();
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === '#genre#') {
|
||||||
|
currentGroup = name;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value || !isHttpUrl(value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
channels.push({
|
||||||
|
id: `${sourceKey}-${channelIndex}`,
|
||||||
|
tvgId: name,
|
||||||
|
name,
|
||||||
|
logo: '',
|
||||||
|
group: currentGroup,
|
||||||
|
url: value,
|
||||||
|
});
|
||||||
|
channelIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { tvgUrl: '', channels };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析M3U文件内容,提取频道信息
|
* 解析M3U文件内容,提取频道信息
|
||||||
* @param m3uContent M3U文件的内容字符串
|
* @param m3uContent M3U文件的内容字符串
|
||||||
@@ -397,7 +479,7 @@ function parseM3U(
|
|||||||
|
|
||||||
const lines = m3uContent
|
const lines = m3uContent
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map((line) => line.trim())
|
.map((line) => stripBom(line).trim())
|
||||||
.filter((line) => line.length > 0);
|
.filter((line) => line.length > 0);
|
||||||
|
|
||||||
let tvgUrl = '';
|
let tvgUrl = '';
|
||||||
|
|||||||
Reference in New Issue
Block a user