mirror of
				https://github.com/qist/tvbox.git
				synced 2025-10-28 18:52:23 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			535 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			535 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | ||
|  * live2cms.js
 | ||
|  * 配置设置 {"key":"Live2CMS","name":"直播转点播V2","type":3,"api":"{{host}}/libs/live2cms.js","searchable":2,"quickSearch":0,"filterable":0,"ext":"{{host}}/txt/json/live2mv_data.json"}
 | ||
|  * live2mv_data.json
 | ||
|  * 支持m3u类直播,支持线路归并。支持筛选切换显示模式
 | ||
| [
 | ||
| {"name": "甜蜜",     "url": "http://zdir.kebedd69.repl.co/public/live.txt"},
 | ||
| {"name": "俊于",     "url": "http://home.jundie.top:81/Cat/tv/live.txt"},
 | ||
| {"name": "菜妮丝",     "url": "http://xn--ihqu10cn4c.xn--z7x900a.love:63/TV/tvzb.txt"},
 | ||
| {"name": "布里m3u",     "url": "http://jiexi.bulisite.top/m3u.php"},
 | ||
| {"name": "吾爱",     "url": "http://52bsj.vip:81/api/v3/file/get/763/live.txt?sign=87BTGT1_6AOry7FPwy_uuxFTv2Wcb9aDMj46rDdRTD8%3D%3A0"},
 | ||
| {"name": "饭太硬",     "url": "http://ftyyy.tk/live.txt"}
 | ||
| ]
 | ||
| 
 | ||
|  * 提示 ext文件格式为json列表,name,url参数
 | ||
|  *	取消加密,减少性能问题
 | ||
|  */
 | ||
| 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'; //默认请求ua
 | ||
| const __ext = {data_dict:{}};
 | ||
| const tips = `\n道长直播转点播js-当前版本${VERSION}`;
 | ||
| const def_pic = 'https://avatars.githubusercontent.com/u/58679624?s=400&u=246b55fcda2b4850b444aebd6b8f8d6a12883f8c&v=4';
 | ||
| 
 | ||
| /**
 | ||
|  * 存在数据库配置表里, key字段对应值value,没有就新增,有就更新,调用此方法会清除key对应的内存缓存
 | ||
|  * @param k 键
 | ||
|  * @param v 值
 | ||
|  */
 | ||
| function setItem(k,v){
 | ||
|     local.set(RKEY,k,v);
 | ||
|     console.log(`规则${RKEY}设置${k} => ${v}`)
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  *  获取数据库配置表对应的key字段的value,没有这个key就返回value默认传参.需要有缓存,第一次获取后会存在内存里
 | ||
|  * @param k 键
 | ||
|  * @param v 值
 | ||
|  * @returns {*}
 | ||
|  */
 | ||
| function getItem(k,v){
 | ||
|     return local.get(RKEY,k) || v;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  *  删除数据库key对应的一条数据,并清除此key对应的内存缓存
 | ||
|  * @param k
 | ||
|  */
 | ||
| function clearItem(k){
 | ||
|     local.delete(RKEY,k);
 | ||
| }
 | ||
| 
 | ||
| var showMode = getItem('showMode','groups'); // groups按组分类显示 all全部一条线路展示
 | ||
| var groupDict = JSON.parse(getItem('groupDict','{}')); // 搜索分组字典
 | ||
| 
 | ||
| /**
 | ||
|  * 打印日志
 | ||
|  * @param any 任意变量
 | ||
|  */
 | ||
| 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('print:'+e.message);
 | ||
| 			console.log(typeof(any)+':'+any.length);
 | ||
| 		}
 | ||
| 	}else if(typeof(any)=='object'&&Object.keys(any).length<1){
 | ||
| 		console.log('null object');
 | ||
| 	}else{
 | ||
| 		console.log(any);
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /*** js自封装的方法 ***/
 | ||
| 
 | ||
| /**
 | ||
|  * 获取链接的host(带http协议的完整链接)
 | ||
|  * @param url 任意一个正常完整的Url,自动提取根
 | ||
|  * @returns {string}
 | ||
|  */
 | ||
| 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
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * m3u直播格式转一般直播格式
 | ||
|  * @param m3u
 | ||
|  * @returns {string}
 | ||
|  */
 | ||
| function convertM3uToNormal(m3u) {
 | ||
| 	try {
 | ||
| 	  const lines = m3u.split('\n');
 | ||
| 	  let result = '';
 | ||
| 	  let TV='';
 | ||
| 	  // let flag='#genre#';
 | ||
| 	  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
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * 线路归类
 | ||
|  * @param arr
 | ||
|  * @returns {*[][]}
 | ||
|  */
 | ||
| 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
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * 线路归类/小棉袄算法
 | ||
|  * @param arr 数组
 | ||
|  * @param parse 解析式
 | ||
|  * @returns {[[*]]}
 | ||
|  */
 | ||
| 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;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * 搜索结果生成分组字典
 | ||
|  * @param arr
 | ||
|  * @param parse x=>x.split(',')[0]
 | ||
|  * @returns {{}}
 | ||
|  */
 | ||
| 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);
 | ||
| 		// if(options.headers['Authorization']){
 | ||
| 		// 	console.log(res.content);
 | ||
| 		// }
 | ||
| 		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 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 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:it.split(',')[0],
 | ||
| 				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 = vod_name+'$'+_get_url;
 | ||
| 		// print(vod_play_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},#[\\s\\S].*?#`);
 | ||
|     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 = [];
 | ||
| 
 | ||
| 
 | ||
| 	// plays.forEach((it)=>{
 | ||
| 	// 	_list.push({
 | ||
| 	// 		'vod_name':it.split(',')[0],
 | ||
| 	// 		'vod_id':it.split(',')[1].trim()+'$'+it.split(',')[0].trim()+'#search#',
 | ||
| 	// 		'vod_pic':def_pic,
 | ||
| 	// 	})
 | ||
| 	// });
 | ||
| 
 | ||
| 	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
 | ||
| }
 |