-
Notifications
You must be signed in to change notification settings - Fork 292
Expand file tree
/
Copy path海龟.js
More file actions
executable file
·160 lines (139 loc) · 5.55 KB
/
海龟.js
File metadata and controls
executable file
·160 lines (139 loc) · 5.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
@header({
searchable: 1,
filterable: 1,
quickSearch: 1,
title: '海龟',
lang: 'cat'
})
*/
const host = 'https://www.haigui.tv';
const headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": host + "/"
};
async function init(cfg) {}
const m = (s, r, i = 1) => (s.match(r) || [])[i] || "";
const fixPic = p => p && p.startsWith('/') ? host + p : p;
function getList(html) {
return pdfa(html, ".module-item").map(it => {
let id = m(it, /href="\/video\/(.*?)\/"/);
let name = m(it, /title="(.*?)"/);
if (!id || !name) return null;
return {
vod_id: id,
vod_name: name,
vod_pic: fixPic(m(it, /data-original="(.*?)"/) || m(it, /src="(.*?)"/)),
vod_remarks: m(it, /module-item-note">(.*?)<\/div>/).replace(/<.*?>/g, "")
};
}).filter(Boolean);
}
async function home(filter) {
const classes = [
["dianying","电影"],["dianshiju","电视剧"],["zongyi","综艺"],
["dongman","动漫"],["jilupian","纪录片"],["duanju","短剧"]
].map(([id,name]) => ({type_id:id,type_name:name}));
const dict = {
area: ["中国大陆","中国香港","中国台湾","美国","韩国","日本","泰国"],
year: ["2025","2024","2023","2022","2021","2020"],
lang: ["国语","英语","粤语","韩语","日语"]
};
const filters = {};
classes.forEach(c => {
filters[c.type_id] = [
{ key:"class", name:"类型", value:getSubClasses(c.type_id) },
...Object.keys(dict).map(k => ({
key:k,
name:{area:"地区",year:"年份",lang:"语言"}[k],
value:[{n:"全部",v:""}].concat(dict[k].map(v=>({n:v,v})))
}))
];
});
return JSON.stringify({ class: classes, filters });
}
function getSubClasses(tid) {
const map = {
dianying: [
["dongzuopian","动作片"],["xijupian","喜剧片"],
["aiqingpian","爱情片"],["kehuanpian","科幻片"],["kongbupian","恐怖片"]
],
dianshiju: [
["guochanju","国产剧"],["gangtaiju","港台剧"],
["rihanju","日韩剧"],["oumeiju","欧美剧"]
]
};
return [{n:"全部",v:""}].concat((map[tid]||[]).map(([v,n])=>({n,v})));
}
async function homeVod() {
const r = await req(host,{headers});
return JSON.stringify({ list:getList(r.content) });
}
async function category(tid, pg, filter, extend={}) {
let p = pg || 1;
let id = extend.class || tid;
let url = `${host}/filter/${id}`;
["area","lang","year"].forEach(k=>{
if (extend[k]) url += `/${k}/${encodeURIComponent(extend[k])}`;
});
url += `/page/${p}/`;
const r = await req(url,{headers});
return JSON.stringify({ page:p, list:getList(r.content) });
}
async function detail(id) {
const r = await req(`${host}/video/${id}/`,{headers});
const h = r.content;
const playFrom = pdfa(h,".module-tab-item")
.map(it=>m(it,/<span>(.*?)<\/span>/)||"播放源")
.join("$$$");
const playUrl = pdfa(h,".module-player-list").map(l =>
pdfa(l,".module-blocklist a").map(it=>{
let pid = m(it,/href=\"\/play\/(.*?)\/\"/);
if (!pid) return null;
return `${m(it,/<span>(.*?)<\/span>/)||"正片"}$${pid}`;
}).filter(Boolean).join("#")
).join("$$$");
return JSON.stringify({
list:[{
vod_id:id,
vod_name:m(h,/page-title\">(.*?)<\/h1>/),
vod_pic:fixPic(m(h,/video-cover.*?data-src=\"(.*?)\"/)||m(h,/video-cover.*?src=\"(.*?)\"/)),
type_name:(
m(h,/tag-link[^>]*>[\s\S]*?icon-cate-[^<]*<\/i>\s*([^<\n]+)/) ||
m(h,/icon-cate-[^<]*<\/i>\s*([^<\n]+)/)
).trim(),
vod_year:m(h,/year\/(\d+)\//),
vod_area:m(h,/area\/.*?\/ \">(.*?)\t/s).trim(),
vod_director:m(h,/导演:<\/span>.*?<div.*?>(.*?)<\/div>/s).replace(/<.*?>|\//g,"").trim(),
vod_actor:m(h,/主演:<\/span>.*?<div.*?>(.*?)<\/div>/s).replace(/<.*?>|\//g,"").trim(),
vod_remarks:m(h,/备注:<\/span>.*?<div.*?>(.*?)<\/div>/),
vod_content:m(h,/vod_content.*?<span>(.*?)<\/span>/s)||"暂无简介",
vod_play_from:playFrom,
vod_play_url:playUrl
}]
});
}
async function search(wd, quick, pg=1) {
let url = `${host}/search/${encodeURIComponent(wd)}/${pg>1?`page/${pg}/`:""}`;
const r = await req(url,{headers});
const h = r.content;
const items = pdfa(h,".module-search-item") || pdfa(h,".module-item");
const list = items.map(it=>{
let id = m(it,/\/video\/(.*?)\//);
let name = m(it,/title=\"(.*?)\"/) || m(it,/alt=\"(.*?)\"/);
if (!id || !name) return null;
return {
vod_id:id,
vod_name:name,
vod_pic:fixPic(m(it,/data-src=\"(.*?)\"/)||m(it,/data-original=\"(.*?)\"/)||m(it,/src=\"(.*?)\"/)),
vod_remarks:m(it,/module-item-note\">(.*?)<\/div>/)||m(it,/video-serial\">(.*?)<\/span>/)
};
}).filter(Boolean);
return JSON.stringify({ page:pg, list });
}
async function play(flag, id, flags) {
const r = await req(`${host}/play/${id}/`,{headers});
let u = m(r.content,/"url":"([^"]+\.m3u8[^"]*)"/);
if (u) return JSON.stringify({ parse:0, url:u.replace(/\\/g,""), header:headers });
return JSON.stringify({ parse:1, url:`${host}/play/${id}/`, header:headers });
}
export default { init, home, homeVod, category, detail, search, play };