| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| String.prototype.rstrip = function (chars) { |
| let regex = new RegExp(chars + "$"); |
| return this.replace(regex, ""); |
| }; |
| const request_timeout = 5000; |
| const RKEY = 'live2cms'; |
| const VERSION = 'live2cms 20230619'; |
| const UA = 'Mozilla/5.0'; |
| const __ext = {data_dict:{}}; |
| const tips = `\n道长直播转点播js-当前版本${VERSION}`; |
| const def_pic = 'https://avatars.githubusercontent.com/u/58679624?s=400&u=246b55fcda2b4850b444aebd6b8f8d6a12883f8c&v=4'; |
|
|
| |
| |
| |
| |
| |
| function setItem(k,v){ |
| local.set(RKEY,k,v); |
| console.log(`规则${RKEY}设置${k} => ${v}`) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function getItem(k,v){ |
| return local.get(RKEY,k) || v; |
| } |
|
|
| |
| |
| |
| |
| function clearItem(k){ |
| local.delete(RKEY,k); |
| } |
|
|
| var showMode = getItem('showMode','groups'); |
| var groupDict = JSON.parse(getItem('groupDict','{}')); |
|
|
| |
| |
| |
| |
| function print(any){ |
| any = any||''; |
| if(typeof(any)=='object'&&Object.keys(any).length>0){ |
| try { |
| any = JSON.stringify(any); |
| console.log(any); |
| }catch (e) { |
| |
| console.log(typeof(any)+':'+any.length); |
| } |
| }else if(typeof(any)=='object'&&Object.keys(any).length<1){ |
| console.log('null object'); |
| }else{ |
| console.log(any); |
| } |
| } |
|
|
| |
|
|
| |
| |
| |
| |
| |
| function getHome(url){ |
| if(!url){ |
| return '' |
| } |
| let tmp = url.split('//'); |
| url = tmp[0] + '//' + tmp[1].split('/')[0]; |
| try { |
| url = decodeURIComponent(url); |
| }catch (e) {} |
| return url |
| } |
|
|
| |
| |
| |
| |
| |
| function convertM3uToNormal(m3u) { |
| try { |
| const lines = m3u.split('\n'); |
| let result = ''; |
| let TV=''; |
| |
| let flag='#m3u#'; |
| let currentGroupTitle = ''; |
| lines.forEach((line) => { |
| if (line.startsWith('#EXTINF:')) { |
| const groupTitle = line.split('"')[1].trim(); |
| TV= line.split('"')[2].substring(1); |
| if (currentGroupTitle !== groupTitle) { |
| currentGroupTitle = groupTitle; |
| result += `\n${currentGroupTitle},${flag}\n`; |
| } |
| } else if (line.startsWith('http')) { |
| const splitLine = line.split(','); |
| result += `${TV}\,${splitLine[0]}\n`; |
| } |
| }); |
| return result.trim(); |
| }catch (e) { |
| print(`m3u直播转普通直播发生错误:${e.message}`); |
| return m3u |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| function merge(arr) { |
| var parse = arguments[1] ? arguments[1] : ''; |
| var p = []; |
| if (parse !== '' && typeof(parse)=="function") { |
| p = arr.map(parse); |
| } |
| const createEmptyArrays = (length) => Array.from({ |
| length |
| }, () => []); |
| let lists = createEmptyArrays(arr.length); |
| let sl = createEmptyArrays(arr.length); |
| (p.length ? p : arr).forEach((k, index) => { |
| var i = 0; |
| while (sl[i].includes(k)) { |
| i = i + 1 |
| } |
| sl[i].push(k); |
| lists[i].push(arr[index]); |
| }) |
| lists=lists.filter(x=>x.some(k=>k.length)); |
| return lists |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function splitArray(arr,parse) { |
| parse = parse&&typeof(parse)=='function'?parse:''; |
| let result = [[arr[0]]]; |
| for (let i = 1; i < arr.length; i++) { |
| let index = -1; |
| for (let j = 0; j < result.length; j++) { |
| if (parse&&result[j].map(parse).includes(parse(arr[i]))) { |
| index = j; |
| }else if((!parse) && result[j].includes(arr[i])){ |
| index = j; |
| } |
| } |
| if (index >= result.length - 1) { |
| result.push([]); |
| result[result.length - 1].push(arr[i]); |
| } else { |
| result[index + 1].push(arr[i]); |
| } |
| } |
| return result; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| function gen_group_dict(arr,parse){ |
| let dict = {}; |
| arr.forEach((it)=>{ |
| let k = it.split(',')[0]; |
| if(parse && typeof(parse)==='function'){ |
| k = parse(k); |
| } |
| if(!dict[k]){ |
| dict[k] = [it] |
| }else{ |
| dict[k].push(it); |
| } |
| }); |
| return dict |
| } |
|
|
| const http = function (url, options = {}) { |
| if(options.method ==='POST' && options.data){ |
| options.body = JSON.stringify(options.data); |
| options.headers = Object.assign({'content-type':'application/json'}, options.headers); |
| } |
| options.timeout = request_timeout; |
| if(!options.headers){ |
| options.headers = {}; |
| } |
| let keys = Object.keys(options.headers).map(it=>it.toLowerCase()); |
| if(!keys.includes('referer')){ |
| options.headers['Referer'] = getHome(url); |
| } |
| if(!keys.includes('user-agent')){ |
| options.headers['User-Agent'] = UA; |
| } |
| console.log(JSON.stringify(options.headers)); |
| try { |
| const res = req(url, options); |
| |
| |
| |
| res.json = () => res&&res.content ? JSON.parse(res.content) : null; |
| res.text = () => res&&res.content ? res.content:''; |
| return res |
| }catch (e) { |
| return { |
| json() { |
| return null |
| }, text() { |
| return '' |
| } |
| } |
| } |
| }; |
| ["get", "post"].forEach(method => { |
| http[method] = function (url, options = {}) { |
| return http(url, Object.assign(options, {method: method.toUpperCase()})); |
| } |
| }); |
|
|
| function init(ext) { |
| console.log("当前版本号:"+VERSION); |
| let data; |
| if (typeof ext == 'object'){ |
| data = ext; |
| print('live ext:object'); |
| } else if (typeof ext == 'string') { |
| if (ext.startsWith('http')) { |
| let ext_paramas = ext.split(';'); |
| let data_url = ext_paramas[0]; |
| print(data_url); |
| data = http.get(data_url).json(); |
| } |
| } |
| print(data); |
| __ext.data = data; |
| print('init执行完毕'); |
| } |
|
|
| function home(filter) { |
| let classes = __ext.data.map(it => ({ |
| type_id: it.url, |
| type_name: it.name, |
| })); |
| print("----home----"); |
| let filter_dict = {}; |
| let filters = [ |
| {'key': 'show', 'name': '播放展示', 'value': [{'n': '多线路分组', 'v': 'groups'},{'n': '单线路', 'v': 'all'}]} |
| ]; |
| classes.forEach(it=>{ |
| filter_dict[it.type_id] = filters; |
| }); |
| print(classes); |
| return JSON.stringify({ 'class': classes,'filters': filter_dict}); |
| } |
|
|
| function homeVod(params) { |
| let _get_url = __ext.data[0].url; |
| let html; |
| if(__ext.data_dict[_get_url]){ |
| html = __ext.data_dict[_get_url]; |
| }else{ |
| html = http.get(_get_url).text(); |
| if(/#EXTM3U/.test(html)){ |
| html = convertM3uToNormal(html); |
| } |
| __ext.data_dict[_get_url] = html; |
| } |
| |
| let arr = html.match(/.*?[,,]#[\s\S].*?#/g); |
| let _list = []; |
| try { |
| arr.forEach(it=>{ |
| let vname = it.split(/[,,]/)[0]; |
| let vtab = it.match(/#(.*?)#/)[0]; |
| _list.push({ |
| vod_name:vname, |
| vod_id:_get_url+'$'+vname, |
| vod_pic:def_pic, |
| vod_remarks:vtab, |
| }); |
| }); |
| }catch (e) { |
| print('Live2cms获取首页推荐发送错误:'+e.message); |
| } |
| return JSON.stringify({ 'list': _list }); |
| } |
|
|
| function category(tid, pg, filter, extend) { |
| let fl = filter?extend:{}; |
| if(fl.show){ |
| showMode = fl.show; |
| setItem('showMode',showMode); |
| } |
| if(parseInt(pg)>1){ |
| return JSON.stringify({ |
| 'list': [], |
| }); |
| } |
| let _get_url = tid; |
| let html; |
| if(__ext.data_dict[_get_url]){ |
| html = __ext.data_dict[_get_url]; |
| }else{ |
| html = http.get(_get_url).text(); |
| if(/#EXTM3U/.test(html)){ |
| html = convertM3uToNormal(html); |
| } |
| __ext.data_dict[_get_url] = html; |
| } |
| |
| let arr = html.match(/.*?[,,]#[\s\S].*?#/g); |
| let _list = []; |
| try { |
| arr.forEach(it=>{ |
| let vname = it.split(/[,,]/)[0]; |
| let vtab = it.match(/#(.*?)#/)[0]; |
| _list.push({ |
| |
| vod_name:vname, |
| vod_id:_get_url+'$'+vname, |
| vod_pic:def_pic, |
| vod_remarks:vtab, |
| }); |
| }); |
| }catch (e) { |
| print('Live2cms获取一级分类页发生错误:'+e.message); |
| } |
|
|
| return JSON.stringify({ |
| 'page': 1, |
| 'pagecount': 1, |
| 'limit': _list.length, |
| 'total': _list.length, |
| 'list': _list, |
| }); |
| } |
|
|
| function detail(tid) { |
| let _get_url = tid.split('$')[0]; |
| let _tab = tid.split('$')[1]; |
| if(tid.includes('#search#')){ |
| let vod_name = _tab.replace('#search#',''); |
| let vod_play_from = '来自搜索'; |
| vod_play_from+=`:${_get_url}`; |
|
|
| |
| |
|
|
| let vod_play_url = groupDict[_get_url].map(x=>x.replace(',','$')).join('#'); |
|
|
| return JSON.stringify({ |
| list: [{ |
| vod_id: tid, |
| vod_name: '搜索:'+vod_name, |
| type_name: "直播列表", |
| vod_pic: def_pic, |
| vod_content: tid, |
| vod_play_from: vod_play_from, |
| vod_play_url: vod_play_url, |
| vod_director: tips, |
| vod_remarks: `道长直播转点播js-当前版本${VERSION}`, |
| }] |
| }); |
| } |
| let html; |
| if(__ext.data_dict[_get_url]){ |
| html = __ext.data_dict[_get_url]; |
| }else{ |
| html = http.get(_get_url).text(); |
| if(/#EXTM3U/.test(html)){ |
| html = convertM3uToNormal(html); |
| } |
| __ext.data_dict[_get_url] = html; |
| } |
| |
| let a = new RegExp(`.*?${_tab.replace('(','\\(').replace(')','\\)')}[,,]#[\\s\\S].*?#`); |
| let b = html.match(a)[0]; |
| let c = html.split(b)[1]; |
| if(c.match(/.*?[,,]#[\s\S].*?#/)){ |
| let d = c.match(/.*?[,,]#[\s\S].*?#/)[0]; |
| c = c.split(d)[0]; |
| } |
| let arr = c.trim().split('\n'); |
| let _list = []; |
| arr.forEach((it)=>{ |
| if(it.trim()){ |
| let t = it.trim().split(',')[0]; |
| let u = it.trim().split(',')[1]; |
| _list.push(t+'$'+u); |
| } |
| }); |
|
|
| let vod_name = __ext.data.find(x=>x.url===_get_url).name; |
| let vod_play_url; |
| let vod_play_from; |
|
|
| if(showMode==='groups'){ |
| let groups = splitArray(_list,x=>x.split('$')[0]); |
| let tabs = []; |
| for(let i=0;i<groups.length;i++){ |
| if(i===0){ |
| tabs.push(vod_name+'1') |
| }else{ |
| tabs.push(` ${i+1} `) |
| } |
| } |
| vod_play_url = groups.map(it=>it.join('#')).join('$$$'); |
| vod_play_from = tabs.join('$$$'); |
| }else{ |
| vod_play_url = _list.join('#'); |
| vod_play_from = vod_name; |
| } |
| let vod = { |
| vod_id: tid, |
| vod_name: vod_name+'|'+_tab, |
| type_name: "直播列表", |
| vod_pic: def_pic, |
| vod_content: tid, |
| vod_play_from: vod_play_from, |
| vod_play_url: vod_play_url, |
| vod_director: tips, |
| vod_remarks: `道长直播转点播js-当前版本${VERSION}`, |
| }; |
|
|
| return JSON.stringify({ |
| list: [vod] |
| }); |
| } |
|
|
| function play(flag, id, flags) { |
| let vod = { |
| 'parse': /m3u8/.test(id)?0:1, |
| 'playUrl': '', |
| 'url': id |
| }; |
| print(vod); |
| return JSON.stringify(vod); |
| } |
|
|
| function search(wd, quick) { |
| let _get_url = __ext.data[0].url; |
| let html; |
| if(__ext.data_dict[_get_url]){ |
| html = __ext.data_dict[_get_url]; |
| }else{ |
| html = http.get(_get_url).text(); |
| if(/#EXTM3U/.test(html)){ |
| html = convertM3uToNormal(html); |
| } |
| __ext.data_dict[_get_url] = html; |
| } |
| let str=''; |
| Object.keys(__ext.data_dict).forEach(()=>{ |
| str+=__ext.data_dict[_get_url]; |
| }); |
| let links = str.split('\n').filter(it=>it.trim() && it.includes(',') && it.split(',')[1].trim().startsWith('http')); |
| links = links.map(it=>it.trim()); |
| let plays = Array.from(new Set(links)); |
| print('搜索关键词:'+wd); |
| print('过滤前:'+plays.length); |
| plays = plays.filter(it=>it.includes(wd)); |
| print('过滤后:'+plays.length); |
| print(plays); |
| let new_group = gen_group_dict(plays); |
| groupDict = Object.assign(groupDict,new_group); |
| |
| setItem('groupDict',JSON.stringify(groupDict)); |
| let _list = []; |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| Object.keys(groupDict).forEach((it)=>{ |
| _list.push({ |
| 'vod_name':it, |
| 'vod_id':it+'$'+wd+'#search#', |
| 'vod_pic':def_pic, |
| }); |
| }); |
| return JSON.stringify({ |
| 'list': _list |
| }); |
| } |
|
|
| |
| export default { |
| init: init, |
| home: home, |
| homeVod: homeVod, |
| category: category, |
| detail: detail, |
| play: play, |
| search: search |
| } |
|
|