live2cms.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /**
  2. * live2cms.js
  3. * 配置设置 {"key":"Live2CMS","name":"直播转点播V2","type":3,"api":"{{host}}/libs/live2cms.js","searchable":2,"quickSearch":0,"filterable":0,"ext":"{{host}}/txt/json/live2mv_data.json"}
  4. * live2mv_data.json
  5. [
  6. {"name": "甜蜜", "url": "http://zdir.kebedd69.repl.co/public/live.txt"},
  7. {"name": "巧计", "url": "https://ghproxy.net/https://raw.githubusercontent.com/dxawi/1/main/tvlive.txt"},
  8. {"name": "星辰", "url": "http://tvmvip.com/xclive.txt"},
  9. {"name": "俊于", "url": "http://home.jundie.top:81/Cat/tv/live.txt"},
  10. {"name": "多多", "url": "https://yydsys.top/duo/txt/v.txt"},
  11. {"name": "菜妮丝", "url": "http://xn--ihqu10cn4c.xn--z7x900a.love:63/TV/tvzb.txt"},
  12. {"name": "乱世", "url": "http://www.dmtv.ml/mao/live/m3u.txt"},
  13. {"name": "吾爱", "url": "http://52bsj.vip:81/api/v3/file/get/763/live.txt?sign=87BTGT1_6AOry7FPwy_uuxFTv2Wcb9aDMj46rDdRTD8%3D%3A0"},
  14. {"name": "饭太硬", "url": "http://ftyyy.tk/live.txt"}
  15. ]
  16. * 提示 ext文件格式为json列表,name,url参数
  17. * 取消加密,减少性能问题
  18. */
  19. String.prototype.rstrip = function (chars) {
  20. let regex = new RegExp(chars + "$");
  21. return this.replace(regex, "");
  22. };
  23. const request_timeout = 5000;
  24. const VERSION = 'live2cms 20230616';
  25. const UA = 'Mozilla/5.0'; //默认请求ua
  26. const __ext = {data_dict:{}};
  27. const tips = `\n道长直播转点播js-当前版本${VERSION}`;
  28. const def_pic = 'https://avatars.githubusercontent.com/u/97389433?s=120&v=4';
  29. /**
  30. * 打印日志
  31. * @param any 任意变量
  32. */
  33. function print(any){
  34. any = any||'';
  35. if(typeof(any)=='object'&&Object.keys(any).length>0){
  36. try {
  37. any = JSON.stringify(any);
  38. console.log(any);
  39. }catch (e) {
  40. // console.log('print:'+e.message);
  41. console.log(typeof(any)+':'+any.length);
  42. }
  43. }else if(typeof(any)=='object'&&Object.keys(any).length<1){
  44. console.log('null object');
  45. }else{
  46. console.log(any);
  47. }
  48. }
  49. /*** js自封装的方法 ***/
  50. /**
  51. * 获取链接的host(带http协议的完整链接)
  52. * @param url 任意一个正常完整的Url,自动提取根
  53. * @returns {string}
  54. */
  55. function getHome(url){
  56. if(!url){
  57. return ''
  58. }
  59. let tmp = url.split('//');
  60. url = tmp[0] + '//' + tmp[1].split('/')[0];
  61. try {
  62. url = decodeURIComponent(url);
  63. }catch (e) {}
  64. return url
  65. }
  66. const http = function (url, options = {}) {
  67. if(options.method ==='POST' && options.data){
  68. options.body = JSON.stringify(options.data);
  69. options.headers = Object.assign({'content-type':'application/json'}, options.headers);
  70. }
  71. options.timeout = request_timeout;
  72. if(!options.headers){
  73. options.headers = {};
  74. }
  75. let keys = Object.keys(options.headers).map(it=>it.toLowerCase());
  76. if(!keys.includes('referer')){
  77. options.headers['Referer'] = getHome(url);
  78. }
  79. if(!keys.includes('user-agent')){
  80. options.headers['User-Agent'] = UA;
  81. }
  82. console.log(JSON.stringify(options.headers));
  83. try {
  84. const res = req(url, options);
  85. // if(options.headers['Authorization']){
  86. // console.log(res.content);
  87. // }
  88. res.json = () => res&&res.content ? JSON.parse(res.content) : null;
  89. res.text = () => res&&res.content ? res.content:'';
  90. return res
  91. }catch (e) {
  92. return {
  93. json() {
  94. return null
  95. }, text() {
  96. return ''
  97. }
  98. }
  99. }
  100. };
  101. ["get", "post"].forEach(method => {
  102. http[method] = function (url, options = {}) {
  103. return http(url, Object.assign(options, {method: method.toUpperCase()}));
  104. }
  105. });
  106. function init(ext) {
  107. console.log("当前版本号:"+VERSION);
  108. let data;
  109. if (typeof ext == 'object'){
  110. data = ext;
  111. print('live ext:object');
  112. } else if (typeof ext == 'string') {
  113. if (ext.startsWith('http')) {
  114. let ext_paramas = ext.split(';');
  115. let data_url = ext_paramas[0];
  116. print(data_url);
  117. data = http.get(data_url).json();
  118. }
  119. }
  120. print(data);
  121. __ext.data = data;
  122. print('init执行完毕');
  123. }
  124. function home(filter) {
  125. let classes = __ext.data.map(it => ({
  126. type_id: it.url,
  127. type_name: it.name,
  128. }));
  129. print("----home----");
  130. print(classes);
  131. return JSON.stringify({ 'class': classes});
  132. }
  133. function homeVod(params) {
  134. let _get_url = __ext.data[0].url;
  135. let html = http.get(_get_url).text();
  136. let arr = html.match(/.*?,#[\s\S].*?#/g);
  137. let _list = [];
  138. try {
  139. arr.forEach(it=>{
  140. _list.push({
  141. vod_name:it.split(',')[0],
  142. vod_id:_get_url+'$'+it.split(',')[0],
  143. vod_pic:def_pic,
  144. vod_remarks:it.split(',')[1],
  145. });
  146. });
  147. }catch (e) {
  148. print('Live2cms获取首页推荐发送错误:'+e.message);
  149. }
  150. return JSON.stringify({ 'list': _list });
  151. }
  152. function category(tid, pg, filter, extend) {
  153. let _get_url = tid;
  154. let html;
  155. if(__ext.data_dict[_get_url]){
  156. html = __ext.data_dict[_get_url];
  157. }else{
  158. html = http.get(_get_url).text();
  159. __ext.data_dict[_get_url] = html;
  160. }
  161. let arr = html.match(/.*?,#[\s\S].*?#/g);
  162. let _list = [];
  163. try {
  164. arr.forEach(it=>{
  165. _list.push({
  166. vod_name:it.split(',')[0],
  167. vod_id:_get_url+'$'+it.split(',')[0],
  168. vod_pic:def_pic,
  169. vod_remarks:it.split(',')[1],
  170. });
  171. });
  172. }catch (e) {
  173. print('Live2cms获取一级分类页发生错误:'+e.message);
  174. }
  175. return JSON.stringify({
  176. 'page': 1,
  177. 'pagecount': 1,
  178. 'limit': _list.length,
  179. 'total': _list.length,
  180. 'list': _list,
  181. });
  182. }
  183. function detail(tid) { // ⛵ 港•澳•台
  184. let _get_url = tid.split('$')[0];
  185. let _tab = tid.split('$')[1];
  186. if(tid.includes('#search#')){
  187. let vod_play_url = _tab.replace('#search#','')+'$'+_get_url;
  188. print(vod_play_url);
  189. return JSON.stringify({
  190. list: [{
  191. vod_id: tid,
  192. vod_name: '搜索:'+_tab.replace('#search#',''),
  193. type_name: "直播列表",
  194. vod_pic: def_pic,
  195. vod_content: tid,
  196. vod_play_from: '来自搜索',
  197. vod_play_url: vod_play_url,
  198. vod_director: tips,
  199. vod_remarks: `道长直播转点播js-当前版本${VERSION}`,
  200. }]
  201. });
  202. }
  203. let html;
  204. if(__ext.data_dict[_get_url]){
  205. html = __ext.data_dict[_get_url];
  206. }else{
  207. html = http.get(_get_url).text();
  208. __ext.data_dict[_get_url] = html;
  209. }
  210. let a = new RegExp(`.*?${_tab},#[\\s\\S].*?#`);
  211. let b = html.match(a)[0];
  212. let c = html.split(b)[1];
  213. if(c.match(/.*?,#[\s\S].*?#/)){
  214. let d = c.match(/.*?,#[\s\S].*?#/)[0];
  215. c = c.split(d)[0];
  216. }
  217. let arr = c.trim().split('\n');
  218. let _list = [];
  219. arr.forEach((it)=>{
  220. if(it.trim()){
  221. let t = it.trim().split(',')[0];
  222. let u = it.trim().split(',')[1];
  223. _list.push(t+'$'+u);
  224. }
  225. });
  226. let vod_name = __ext.data.find(x=>x.url===_get_url).name;
  227. let vod_play_url = _list.join('#');
  228. let vod = {
  229. vod_id: tid,
  230. vod_name: vod_name+'|'+_tab,
  231. type_name: "直播列表",
  232. vod_pic: def_pic,
  233. vod_content: tid,
  234. vod_play_from: vod_name,
  235. vod_play_url: vod_play_url,
  236. vod_director: tips,
  237. vod_remarks: `道长直播转点播js-当前版本${VERSION}`,
  238. };
  239. return JSON.stringify({
  240. list: [vod]
  241. });
  242. }
  243. function play(flag, id, flags) {
  244. let vod = {
  245. 'parse': /m3u8/.test(id)?0:1,
  246. 'playUrl': '',
  247. 'url': id
  248. };
  249. print(vod);
  250. return JSON.stringify(vod);
  251. }
  252. function search(wd, quick) {
  253. let _get_url = __ext.data[0].url;
  254. let html;
  255. if(__ext.data_dict[_get_url]){
  256. html = __ext.data_dict[_get_url];
  257. }else{
  258. html = http.get(_get_url).text();
  259. __ext.data_dict[_get_url] = html;
  260. }
  261. let str='';
  262. Object.keys(__ext.data_dict).forEach(()=>{
  263. str+=__ext.data_dict[_get_url];
  264. });
  265. let links = str.split('\n').filter(it=>it.trim() && it.includes(','));
  266. links = links.map(it=>it.trim());
  267. let plays = Array.from(new Set(links));
  268. print('搜索关键词:'+wd);
  269. print('过滤前:'+plays.length);
  270. plays = plays.filter(it=>it.includes(wd));
  271. print('过滤后:'+plays.length);
  272. print(plays);
  273. let _list = [];
  274. plays.forEach((it)=>{
  275. _list.push({
  276. 'vod_name':it.split(',')[0],
  277. 'vod_id':it.split(',')[1].trim()+'$'+it.split(',')[0].trim()+'#search#',
  278. 'vod_pic':def_pic,
  279. })
  280. });
  281. return JSON.stringify({
  282. 'list': _list
  283. });
  284. }
  285. // 导出函数对象
  286. export default {
  287. init: init,
  288. home: home,
  289. homeVod: homeVod,
  290. category: category,
  291. detail: detail,
  292. play: play,
  293. search: search
  294. }