爱壹帆
https://www.iyf.lv/
Simwoodone (12535)06/08 15:24
该用户很懒,什么介绍也没有写!
{
"bookSourceUrl": "https:\/\/www.iyf.lv\/",
"bookSourceName": "爱壹帆",
"enabledExplore": true,
"enabled": true,
"bookSourceGroup": "有声漫画",
"author": "",
"help": true,
"html": "<!DOCTYPE html>\n<html lang=\"zh\">\n<head>\n <meta charset=\"UTF-8\">\n <title>爱壹帆<\/title>\n<\/head>\n<body>\n<\/body>\n<script src=\"https:\/\/vc.jd.com\/web\/js\/jquery-3.1.1.min.js\"><\/script>\n<script>\nvar isCookieJar = true;\nvar baseurl = \"https:\/\/www.iyf.lv\";\nvar header = {\n \"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\"\n};\n\n\/\/ ===========================================================\n\/\/ FlutterJSBridge\n\/\/ ===========================================================\nclass FlutterJSBridge {\n constructor() {}\n async log(str) {\n try { await window.flutter_inappwebview.callHandler('log', str); } catch (e) {}\n }\n async text(type, str) {\n try { await window.flutter_inappwebview.callHandler('text', type, str); } catch (e) {}\n }\n async showToast(str) {\n try { await window.flutter_inappwebview.callHandler('showToast', str); } catch (e) {}\n }\n async getDevice() {\n try { return await window.flutter_inappwebview.callHandler('getDevice'); } catch (e) { return \"\"; }\n }\n async getversion() {\n try { return await window.flutter_inappwebview.callHandler('getversion'); } catch (e) { return \"\"; }\n }\n async base64encode(str) {\n try { return await window.flutter_inappwebview.callHandler('base64encode', str); } catch (e) { return \"\"; }\n }\n async base64decode(str) {\n try { return await window.flutter_inappwebview.callHandler('base64decode', str); } catch (e) { return \"\"; }\n }\n async utf8ToGbkUrlEncoded(str) {\n try { return await window.flutter_inappwebview.callHandler('utf8ToGbkUrlEncoded', str); } catch (e) { return encodeURIComponent(str); }\n }\n async webview(url, js, html, body, header) {\n try { return await window.flutter_inappwebview.callHandler('webview', url, js, html, body, header); } catch (e) { return \"\"; }\n }\n async webViewGetSource(url, js, html, body, header, key) {\n try { return await window.flutter_inappwebview.callHandler('webViewGetSource', url, js, html, body, header, key); } catch (e) { return \"\"; }\n }\n async addbook(bookurl) {\n try { await window.flutter_inappwebview.callHandler('addbook', bookurl); } catch (e) {}\n }\n async toSimplified(str) {\n try { return await window.flutter_inappwebview.callHandler('toSimplified', str); } catch (e) { return str; }\n }\n async toTraditional(str) {\n try { return await window.flutter_inappwebview.callHandler('toTraditional', str); } catch (e) { return str; }\n }\n async getVerificationCode(str, header) {\n try { return await window.flutter_inappwebview.callHandler('getVerificationCode', str, header); } catch (e) { return \"\"; }\n }\n async getDeviceid() {\n try { return await window.flutter_inappwebview.callHandler('getDeviceid'); } catch (e) { return \"\"; }\n }\n async showvideoplay(url, title, key) {\n try { await window.flutter_inappwebview.callHandler('showvideoplay', url, title, key); } catch (e) {}\n }\n}\n\n\/\/ ===========================================================\n\/\/ Http\n\/\/ ===========================================================\nclass Http {\n constructor() {}\n async Get(url, headers, followRedirects) {\n return await window.flutter_inappwebview.callHandler('http', \"get\", url, \"\", JSON.stringify(headers), followRedirects, \"\");\n }\n async Head(url, headers, followRedirects) {\n return await window.flutter_inappwebview.callHandler('http', \"head\", url, \"\", JSON.stringify(headers), followRedirects, \"\");\n }\n async Post(url, headers, body, contenttype, followRedirects) {\n return await window.flutter_inappwebview.callHandler('http', \"post\", url, body, JSON.stringify(headers), followRedirects, contenttype);\n }\n}\n\n\/\/ ===========================================================\n\/\/ Cache\n\/\/ ===========================================================\nclass Cache {\n async get(key) {\n try { return await window.flutter_inappwebview.callHandler('cacheGet', key); } catch (e) { return null; }\n }\n async set(key, value) {\n try { await window.flutter_inappwebview.callHandler('cacheSet', key, value); } catch (e) {}\n }\n async remove(key) {\n try { await window.flutter_inappwebview.callHandler('cacheRemove', key); } catch (e) {}\n }\n async getLoginInfo() {\n try { return await window.flutter_inappwebview.callHandler('getLoginInfo'); } catch (e) { return null; }\n }\n async putLoginInfo(info) {\n try { await window.flutter_inappwebview.callHandler('putLoginInfo', info); } catch (e) {}\n }\n async getbookVariable(bookurl) {\n try { return await window.flutter_inappwebview.callHandler('getbookVariable', bookurl); } catch (e) { return null; }\n }\n async setbookVariable(bookurl, value) {\n try { await window.flutter_inappwebview.callHandler('setbookVariable', bookurl, value); } catch (e) {}\n }\n}\n\n\/\/ ===========================================================\n\/\/ Cookie\n\/\/ ===========================================================\nclass Cookie {\n async get(url) {\n try { return await window.flutter_inappwebview.callHandler('cookie', \"get\", url, \"\"); } catch (e) { return \"\"; }\n }\n async remove(url) {\n try { await window.flutter_inappwebview.callHandler('cookie', \"remove\", url, \"\"); } catch (e) {}\n }\n async set(url, value) {\n try { await window.flutter_inappwebview.callHandler('cookie', \"set\", url, value); } catch (e) {}\n }\n async setCookie(url, key, value) {\n try { await window.flutter_inappwebview.callHandler('cookie', \"setCookie\", url, key + \"=\" + value); } catch (e) {}\n }\n async getCookie(url, key) {\n try { return await window.flutter_inappwebview.callHandler('cookie', \"getCookie\", url, key); } catch (e) { return \"\"; }\n }\n}\n\n\/\/ ===========================================================\n\/\/ 全局实例\n\/\/ ===========================================================\nconst flutterBridge = new FlutterJSBridge();\nconst cache = new Cache();\nconst http = new Http();\nconst cookie = new Cookie();\n\n\/\/ 播放按钮 SVG (base64)\nvar PLAY_SVG = \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIiB2aWV3Qm94PSIwIDAgMjMgMjgiPgo8ZGVmcz4KPGZpbHRlciBpZD0icyI+CjxmZURyb3BTaGFkb3cgZHg9IjAiIGR5PSIwLjYiIHN0ZERldmlhdGlvbj0iMC43IiBmbG9vZC1jb2xvcj0iIzAwMCIgZmxvb2Qtb3BhY2l0eT0iMC4zNSIvPgo8L2ZpbHRlcj4KPC9kZWZzPgo8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0LjUsIDQpIj4KPHBhdGggZD0iTTAgMGgxNHYxNEgweiIgZmlsbD0ibm9uZSIvPgo8ZyBmaWxsPSJub25lIj4KPHBhdGggZmlsbD0iIzI4NTljNSIgZD0iTTQuNSA4Ljg4MlY1LjExOGExIDEgMCAwIDEgMS40NDctLjg5NGwzLjc2NCAxLjg4MmExIDEgMCAwIDEgMCAxLjc4OEw1Ljk0NyA5Ljc3NkExIDEgMCAwIDEgNC41IDguODgyIi8+CjxwYXRoIGZpbGw9IiM4ZmJmZmEiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTguMDkuMDg0YS43NS43NSAwIDAgMC0uMjMyIDEuNDgyQTUuNTAyIDUuNTAyIDAgMCAxIDcgMTIuNWE1LjUgNS41IDAgMCAxLTUuMTE2LTMuNDc1YS43NS43NSAwIDAgMC0xLjM5NC41NTJBNy4wMDIgNy4wMDIgMCAwIDAgMTQgN0E3IDcgMCAwIDAgOC4wOS4wODRtLTIuNDY2IDEuNDlBLjc1Ljc1IDAgMCAwIDUuMjUxLjEyM2E3IDcgMCAwIDAtLjkzOC4zMTRhLjc1Ljc1IDAgMCAwIC41NzYgMS4zODVxLjM1Ni0uMTQ4LjczNS0uMjQ2TTMuMTcgMi45NTVhLjc1Ljc1IDAgMCAwLTEuMDQ0LTEuMDc2QTcgNyAwIDAgMCAuOTE3IDMuNDM1YS43NS43NSAwIDEgMCAxLjMwMy43NDRjLjI1OC0uNDUyLjU3OC0uODY0Ljk1LTEuMjI0TTEuNTU0IDYuMTI3YS43NS43NSAwIDEgMC0xLjQ4NS0uMjFBNyA3IDAgMCAwIDAgNi45MDNhLjc1Ljc1IDAgMSAwIDEuNSAwcTAtLjM5Ni4wNTQtLjc3NiIgY2xpcC1ydWxlPSJldmVub2RkIi8+CjwvZz4KPC9nPgo8dGV4dCB4PSIxMS41IiB5PSIyNS41IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEuMyIgZm9udC1mYW1pbHk9InN5c3RlbS11aSwtYXBwbGUtc3lzdGVtLFBpbmdGYW5nIFNDLE1pY3Jvc29mdCBZYUhlaSxzYW5zLXNlcmlmIiBmaWxsPSIjMjg1OWM1IiBmb250LXdlaWdodD0iYm9sZCIgZmlsdGVyPSJ1cmwoI3MpIj7ngrnlh7vmkq3mlL48L3RleHQ+Cjwvc3ZnPg==\";\n\n\/\/ showvideoplay jQuery 扩展 + 全局函数\n$.showvideoplay = function (url, title, key) {\n flutterBridge.showvideoplay(url, title, key);\n};\nfunction showvideoplay(url, title, key) {\n flutterBridge.showvideoplay(url, title, key);\n}\n\n\/\/ 编解码 (用 encodeURIComponent 避免 btoa\/atob 兼容问题)\nfunction enc(str) {\n return encodeURIComponent(str);\n}\nfunction dec(str) {\n return decodeURIComponent(str);\n}\nfunction full(x) {\n return x.indexOf(\"http\") === 0 ? x : (baseurl + x);\n}\n\n\/\/ ===========================================================\n\/\/ 工具函数\n\/\/ ===========================================================\nfunction parseHTMLSafely(htmlStr) {\n try {\n var tempDiv = document.createElement('div');\n tempDiv.innerHTML = htmlStr;\n return $(tempDiv);\n } catch (e) {\n flutterBridge.log(\"HTML解析错误:\" + e.message);\n return $('<div>');\n }\n}\n\nfunction removeHTMLSafely(tempContainer) {\n try {\n tempContainer.innerHTML = '';\n if (tempContainer.parentNode) {\n tempContainer.parentNode.removeChild(tempContainer);\n }\n } catch (e) {\n flutterBridge.log(\"HTML移除失败:\" + e.message);\n }\n}\n\nfunction removeHTMLTags(htmlString) {\n let result = htmlString.replace(\/<script\\b[^<]*(?:(?!<\\\/script>)<[^<]*)*<\\\/script>\/gi, '');\n result = result.replace(\/<style\\b[^<]*(?:(?!<\\\/style>)<[^<]*)*<\\\/style>\/gi, '');\n return result;\n}\n\nfunction getVid(url) {\n var m = url.match(\/\\\/(\\d+)\\\/\/);\n return m ? m[1] : \"\";\n}\n\n\/\/ ===========================================================\n\/\/ 搜索\n\/\/ ===========================================================\nasync function search(key, page) {\n if (page > 2) return \"[]\";\n var url = baseurl + \"\/s\/\" + encodeURIComponent(key) + \"----------\" + page + \"---\/\";\n var res = await http.Get(url, JSON.stringify(header), true);\n flutterBridge.text(0, res.data);\n\n var books = [];\n var html = $.parseHTML(res.data);\n $(html).find(\"div.module-card-item.module-item\").each(function(index) {\n var $el = $(this);\n var href = $el.find(\"a.module-card-item-poster\").attr('href');\n var title = $el.find(\".module-card-item-title a\").text() || \"\";\n var cover = $el.find(\"img\").attr('data-original') || \"\";\n var status = $el.find(\".module-item-note\").first().text() || \"\";\n var typeLabel = $el.find(\".module-card-item-class\").text() || \"\";\n\n if (!href) return;\n if (cover && !cover.startsWith(\"http\")) cover = baseurl + cover;\n\n books.push({\n bookUrl: baseurl + href,\n name: title,\n author: typeLabel,\n kind: \"\",\n coverUrl: cover,\n intro: \"\",\n tocUrl: baseurl + href,\n wordCount: \"\",\n type: 0,\n latestChapterTitle: status\n });\n });\n return JSON.stringify(books);\n}\n\n\/\/ ===========================================================\n\/\/ 详情\n\/\/ ===========================================================\nasync function info(bookurl) {\n var res = await http.Get(bookurl, JSON.stringify(header), true);\n flutterBridge.text(1, res.data);\n\n var html = $.parseHTML(res.data);\n var $html = $(html);\n var vid = getVid(bookurl);\n\n \/\/ 标题\n var title = $html.find(\"h1\").first().text() || \"\";\n if (!title) {\n title = $html.find(\"title\").text().replace(\/免费在线观看.*$\/, \"\").replace(\/爱壹帆.*$\/, \"\").trim();\n }\n\n \/\/ 封面\n var cover = $html.find(\".module-info-poster img\").attr('data-original') || \n $html.find(\".module-item-pic img\").attr('data-original') || \"\";\n if (cover && !cover.startsWith(\"http\") && cover.indexOf(\"loading.png\") < 0) cover = baseurl + cover;\n\n \/\/ 简介\n var intro = $html.find(\".module-info-introduction-content\").html() || \n $html.find(\".des\").html() || \"\";\n\n \/\/ 分类\n var kind = \"\";\n var kindMap = {\"1\":\"电影\",\"2\":\"剧集\",\"3\":\"综艺\",\"4\":\"动漫\"};\n var km = bookurl.match(\/\\\/t\\\/(\\d+)\\\/\/);\n if (!km) {\n var ka = $html.find(\"a[href*='\/t\/']\").first();\n if (ka.length) {\n var href = ka.attr('href');\n var m2 = href.match(\/\\\/t\\\/(\\d+)\\\/\/);\n if (m2) kind = kindMap[m2[1]] || ka.text();\n }\n } else {\n kind = kindMap[km[1]] || \"\";\n }\n\n \/\/ 最新章节\n var latestChapter = \"\";\n if (vid) {\n var epRegex = new RegExp('\/iyfplay\/' + vid + '-1-(\\\\d+)\/', 'g');\n var matchStr = res.data.match(epRegex);\n if (matchStr) {\n var maxEp = 0;\n matchStr.forEach(function(s) {\n var ep = parseInt(s.match(\/\\d+$\/));\n if (ep > maxEp) maxEp = ep;\n });\n if (maxEp > 0) latestChapter = \"第\" + maxEp + \"集\";\n }\n }\n\n return JSON.stringify({\n bookUrl: bookurl,\n name: title,\n author: \"\",\n kind: kind,\n coverUrl: cover,\n intro: intro ? \"@html:\" + intro : \"\",\n tocUrl: bookurl,\n wordCount: \"\",\n type: 0,\n latestChapterTitle: latestChapter\n });\n}\n\n\/\/ ===========================================================\n\/\/ 目录\/选集\n\/\/ ===========================================================\nasync function chapter(tocUrl) {\n var res = await http.Get(tocUrl, JSON.stringify(header), true);\n flutterBridge.text(2, res.data);\n\n var vid = getVid(tocUrl);\n if (!vid) return \"[]\";\n\n var html = $.parseHTML(res.data);\n var $html = $(html);\n var chapters = [];\n\n \/\/ 尝试匹配播放链接(自营1线优先)\n var epRegex = new RegExp('\/iyfplay\/' + vid + '-1-(\\\\d+)\/', 'g');\n var matchStr = res.data.match(epRegex);\n\n if (!matchStr || matchStr.length === 0) {\n \/\/ 回退: 取第一条线\n var fallRegex = new RegExp('\/iyfplay\/' + vid + '-(\\\\d+)-(\\\\d+)\/', 'g');\n var fm;\n var firstLine = -1;\n matchStr = [];\n while ((fm = fallRegex.exec(res.data)) !== null) {\n var lid = parseInt(fm[1]);\n if (firstLine === -1) firstLine = lid;\n if (lid === firstLine) matchStr.push(fm[0]);\n }\n }\n\n if (matchStr && matchStr.length > 0) {\n matchStr.forEach(function(s, idx) {\n var ep = parseInt(s.match(\/-(\\d+)\\\/\/)[1]);\n chapters.push({\n name: \"第\" + ep + \"集\",\n chapterId: enc(baseurl + s),\n index: ep - 1,\n isPay: false,\n isVip: false,\n isVolume: false,\n tag: \"\"\n });\n });\n } else {\n \/\/ 电影\/单集:详情页即播放页\n chapters.push({\n name: \"正片\",\n chapterId: enc(baseurl + tocUrl.replace(\"\/iyftv\/\", \"\/iyfplay\/\").replace(\/\\\/$\/, \"-1-1\/\")),\n index: 0,\n isPay: false,\n isVip: false,\n isVolume: false,\n tag: \"\"\n });\n }\n\n chapters.sort(function(a, b) { return a.index - b.index; });\n return JSON.stringify(chapters);\n}\n\n\/\/ ===========================================================\n\/\/ 播放 (限制: 点击播放按钮才加载; 直接用原生 showvideoplay)\n\/\/ ===========================================================\nasync function content(url, bookurl) {\n var playUrl = dec(url);\n if (playUrl.indexOf('http') !== 0) playUrl = baseurl + playUrl;\n if (playUrl.indexOf('-1-') < 0) {\n playUrl = playUrl.replace(\/-\\d+-\\d+\\\/\/, '-1-1\/');\n }\n\n try {\n var res = await http.Get(playUrl, JSON.stringify(header), true);\n var h = res.data || '';\n if (!h) return '获取失败';\n\n var v = '';\n var m;\n\n \/\/ player_aaaa 对象\n m = h.match(\/var\\s+player_aaaa\\s*=\\s*({[^;]+});?\/);\n if (m) {\n try { v = (JSON.parse(m[1]).url || '').replace(\/\\\\\\\/\/g, '\/'); } catch (e) {}\n }\n\n \/\/ m3u8\n if (!v) { m = h.match(\/\"url\"\\s*:\\s*\"(https?:[^\"]+\\.m3u8[^\"]*)\"\/i); if (m) v = m[1].replace(\/\\\\\\\/\/g, '\/'); }\n if (!v) { m = h.match(\/(https?:\\\/\\\/[^\\s\"'<>]+\\.m3u8[^\\s\"'<>]*)\/i); if (m) v = m[1]; }\n\n \/\/ mp4\n if (!v) { m = h.match(\/\"url\"\\s*:\\s*\"(https?:[^\"]+\\.mp4[^\"]*)\"\/i); if (m) v = m[1].replace(\/\\\\\\\/\/g, '\/'); }\n if (!v) { m = h.match(\/(https?:\\\/\\\/[^\\s\"'<>]+\\.mp4[^\\s\"'<>]*)\/i); if (m) v = m[1]; }\n\n \/\/ thisUrl\n if (!v) { m = h.match(\/thisUrl\\s*=\\s*\"([^\"]+)\"\/i); if (m) v = m[1]; }\n\n \/\/ video 标签\n if (!v) {\n var $h = $.parseHTML(h);\n v = $($h).find(\"video source\").attr('src') ||\n $($h).find(\"video\").attr('src') || '';\n }\n\n if (v) {\n return '<img src=\"data:image\/svg+xml;base64,' + PLAY_SVG +\n ',{"js":"showvideoplay(\\'' + v +\n '\\',\\'爱壹帆\\',\\'' + v + '\\')"}\"\/>';\n }\n\n \/\/ 降级: WebView 打开播放页\n return '<img src=\"data:image\/svg+xml;base64,' + PLAY_SVG +\n ',{"js":"flutterBridge.startBrowser(\\'' + playUrl +\n '\\',\\'爱壹帆\\',\\'' +\n JSON.stringify(header).replace(\/\"\/g, '\\\\\\\\\"') + '\\')"}\"\/>';\n\n } catch (e) {\n return '播放出错';\n }\n}\n\n\/\/ ===========================================================\n\/\/ 发现分类\n\/\/ ===========================================================\nasync function getfinds() {\n return JSON.stringify([\n { title: \"电影\", url: \"\/t\/1\/\", type: 0 },\n { title: \"剧集\", url: \"\/t\/2\/\", type: 0 },\n { title: \"综艺\", url: \"\/t\/3\/\", type: 0 },\n { title: \"动漫\", url: \"\/t\/4\/\", type: 0 },\n { title: \"热榜\", url: \"\/label\/hot\/\", type: 0 },\n { title: \"更新\", url: \"\/label\/new\/\", type: 0 }\n ]);\n}\n\n\/\/ ===========================================================\n\/\/ 发现列表\n\/\/ ===========================================================\nasync function find(url, page) {\n if (page > 2) return \"[]\";\n var fullUrl = baseurl + url;\n if (page > 1) {\n fullUrl = fullUrl.replace(\/\\\/$\/, \"\") + \"\/page\/\" + page + \"\/\";\n }\n var res = await http.Get(fullUrl, JSON.stringify(header), true);\n flutterBridge.text(0, res.data);\n\n var books = [];\n var html = $.parseHTML(res.data);\n\n \/\/ 格式1: 分类页 - a.module-poster-item.module-item (海报卡片)\n $(html).find(\"a.module-poster-item.module-item\").each(function(index) {\n var $el = $(this);\n var href = $el.attr('href');\n if (!href) return;\n var title = $el.attr('title') || $el.find(\"img\").attr('alt') || \"\";\n var cover = $el.find(\"img\").attr('data-original') || \"\";\n var status = $el.find(\".module-item-note\").text() || \"\";\n if (cover && !cover.startsWith(\"http\")) cover = baseurl + cover;\n books.push({\n bookUrl: baseurl + href, name: title, author: status, kind: \"\",\n coverUrl: cover, intro: \"\", tocUrl: baseurl + href,\n wordCount: \"\", type: 0, latestChapterTitle: status\n });\n });\n\n \/\/ 格式2: 热榜\/更新页 - div.module-card-item.module-item (列表卡片)\n if (books.length === 0) {\n $(html).find(\"div.module-card-item.module-item\").each(function(index) {\n var $el = $(this);\n var href = $el.find(\"a.module-card-item-poster\").attr('href');\n if (!href) return;\n var title = $el.find(\".module-card-item-title a\").text() || \"\";\n var cover = $el.find(\"img\").attr('data-original') || \"\";\n var status = $el.find(\".module-item-note\").first().text() || \"\";\n var typeLabel = $el.find(\".module-card-item-class\").text() || \"\";\n if (cover && !cover.startsWith(\"http\")) cover = baseurl + cover;\n books.push({\n bookUrl: baseurl + href, name: title, author: typeLabel, kind: \"\",\n coverUrl: cover, intro: \"\", tocUrl: baseurl + href,\n wordCount: \"\", type: 0, latestChapterTitle: status\n });\n });\n }\n return JSON.stringify(books);\n}\n\n\/\/ ===========================================================\n\/\/ 登录(不需要)\n\/\/ ===========================================================\nasync function getloginurl() {\n return baseurl;\n}\nasync function login() {}\n\n\/\/ ===========================================================\n\/\/ 付费(不需要)\n\/\/ ===========================================================\nasync function pay(bookurl, url) {}\n\n\/\/ ===========================================================\n\/\/ 图片解密(不需要)\n\/\/ ===========================================================\nasync function imagedecrypt(url, image) {}\n\n\/\/ ===========================================================\n\/\/ WebView 拦截(不需要)\n\/\/ ===========================================================\nasync function shouldOverrideUrlLoading(url) {\n return true;\n}\n<\/script>\n<\/html>\n",
"login": false,
"lastUpdateTime": "1780903453619"
}