豆包漫画

豆包漫画

Simwoodone (12535)07/19 12:52

该用户很懒,什么介绍也没有写!
二维码导入(APP尚未完成该功能)
{
    "bookSourceUrl": "豆包漫画",
    "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 src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/crypto-js\/4.1.1\/crypto-js.min.js\"><\/script>\n<script>\n  var isCookieJar = true;\n  class FlutterJSBridge {\n    constructor() {\n      this.init();\n    }\n\n    init() {\n      if (window.flutter_inappwebview) {\n        this.isReady = true;\n        this.CookieJar();\n      } else {\n        window.addEventListener('flutterInAppWebViewPlatformReady', () => {\n          this.isReady = true;\n          console.log('JSBridge初始化完成');\n          this.CookieJar();\n        });\n      }\n    }\n\n    async CookieJar() {\n      try {\n        await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar);\n      } catch (error) {\n        console.error('汇报完成准备失败:', error);\n      }\n    }\n\n    async showToast(str) {\n      try {\n        return await window.flutter_inappwebview.callHandler('showToast', str);\n      } catch (error) {\n        return false;\n      }\n    }\n\n    async showLongToast(str) {\n      try {\n        return await window.flutter_inappwebview.callHandler('showLongToast', str);\n      } catch (error) {\n        return false;\n      }\n    }\n\n    async log(str) {\n      try {\n        return await window.flutter_inappwebview.callHandler('log', str);\n      } catch (error) {\n        return false;\n      }\n    }\n\n    async text(type, str) {\n      try {\n        return await window.flutter_inappwebview.callHandler('text', type, str);\n      } catch (error) {\n        return false;\n      }\n    }\n\n    async getbuildNumber() {\n      try {\n        return await window.flutter_inappwebview.callHandler('buildNumber');\n      } catch (error) {\n        return 0;\n      }\n    }\n\n    async getWebViewUA() {\n      try {\n        return await window.flutter_inappwebview.callHandler('getWebViewUA');\n      } catch (error) {\n        return \"\";\n      }\n    }\n\n    async webview(url, js, html, body, header) {\n      try {\n        return await window.flutter_inappwebview.callHandler('webview', url, js, html, body, header, \"\", \"\");\n      } catch (error) {\n        return \"\";\n      }\n    }\n\n    async startBrowser(url, title, header) {\n      try {\n        return await window.flutter_inappwebview.callHandler('startBrowser', url, title, header);\n      } catch (error) {\n        return \"\";\n      }\n    }\n  }\n\n  class Http {\n    constructor() {\n      this.open = false;\n      this.requestTimestamps = [];\n      this.rateLimit = 5;\n      this.rateLimitWindow = 1000;\n    }\n\n    async checkRateLimit() {\n      if (!this.open) return;\n      const now = Date.now();\n      this.requestTimestamps = this.requestTimestamps.filter(timestamp => now - timestamp < this.rateLimitWindow);\n      if (this.requestTimestamps.length >= this.rateLimit) {\n        const oldestTimestamp = this.requestTimestamps[0];\n        const waitTime = this.rateLimitWindow - (now - oldestTimestamp);\n        await new Promise(resolve => setTimeout(resolve, waitTime));\n        return this.checkRateLimit();\n      }\n      this.requestTimestamps.push(now);\n    }\n\n    async Get(url, headers, followRedirects) {\n      try {\n        await this.checkRateLimit();\n        return await window.flutter_inappwebview.callHandler('http', \"get\", url, \"\", JSON.stringify(headers), followRedirects, \"\");\n      } catch (error) {\n        return null;\n      }\n    }\n\n    async Post(url, headers, body, contenttype, followRedirects) {\n      try {\n        await this.checkRateLimit();\n        return await window.flutter_inappwebview.callHandler('http', \"post\", url, body, JSON.stringify(headers), followRedirects, contenttype);\n      } catch (error) {\n        return null;\n      }\n    }\n  }\n\n  class Cache {\n    constructor() {}\n    async get(key) {\n      try {\n        return await window.flutter_inappwebview.callHandler('cache.get', key);\n      } catch (error) {\n        return null;\n      }\n    }\n    async set(key, value) {\n      try {\n        return await window.flutter_inappwebview.callHandler('cache.set', key, value);\n      } catch (error) {\n        return null;\n      }\n    }\n    async remove(key) {\n      try {\n        return await window.flutter_inappwebview.callHandler('cache.remove', key);\n      } catch (error) {\n        return null;\n      }\n    }\n  }\n\n  class Cookie {\n    constructor() {}\n    async get(url) {\n      try {\n        return await window.flutter_inappwebview.callHandler('cookie.get', url);\n      } catch (error) {\n        return null;\n      }\n    }\n    async remove(url) {\n      try {\n        return await window.flutter_inappwebview.callHandler('cookie.remove', url);\n      } catch (error) {\n        return null;\n      }\n    }\n    async set(url, value) {\n      try {\n        return await window.flutter_inappwebview.callHandler('cookie.set', url, value);\n      } catch (error) {\n        return null;\n      }\n    }\n  }\n\n  function 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\n  function 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\n  function removeHTMLTags(htmlString) {\n    var result = htmlString.replace(\/<script\\b[^<]*(?:(?!<\\\/script>)<[^<]*)*<\\\/script>\/gi, '');\n    result = result.replace(\/<style\\b[^<]*(?:(?!<\\\/style>)<[^<]*)*<\\\/style>\/gi, '');\n    return result;\n  }\n\n<\/script>\n\n<script>\n  const flutterBridge = new FlutterJSBridge();\n  const cache = new Cache();\n  const http = new Http();\n  const cookie = new Cookie();\n\n  const BASE = 'https:\/\/www.doubaomanhua.com';\n  const IMG_BASE = 'https:\/\/img.doubaomanhua.com';\n  const UA = {\n    'User-Agent': 'Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/126.0.0.0 Safari\/537.36'\n  };\n\n  \/\/ ============ CF检测与智能请求 ============\n  \/\/ 检测响应是否为Cloudflare验证页面\n  function isCloudflareChallenge(html) {\n    if (!html || html.length < 100) return false;\n    return html.indexOf('_cf_chl_opt') !== -1 ||\n           html.indexOf('Just a moment') !== -1 ||\n           html.indexOf('challenge-platform') !== -1 ||\n           html.indexOf('Enable JavaScript') !== -1;\n  }\n\n  \/\/ 智能请求:HTTP优先,检测到CF时自动降级WebView\n  async function smartFetch(url, useWebView) {\n    \/\/ 先尝试HTTP\n    var resp = await http.Get(url, UA, true);\n\n    if (resp && resp.data && !isCloudflareChallenge(resp.data)) {\n      flutterBridge.log(\"HTTP success for: \" + url.substring(0, 60));\n      return resp.data;\n    }\n\n    if (resp && resp.data && isCloudflareChallenge(resp.data)) {\n      flutterBridge.log(\"Cloudflare detected, switching to WebView: \" + url.substring(0, 60));\n    } else {\n      flutterBridge.log(\"HTTP failed, trying WebView: \" + url.substring(0, 60));\n    }\n\n    \/\/ 降级到WebView\n    var html = await flutterBridge.webview(url, '', '', '', '{}');\n    if (html && html.length >= 100 && !isCloudflareChallenge(html)) {\n      return html;\n    }\n\n    \/\/ WebView也被CF拦截,先预热主页\n    flutterBridge.log(\"WebView also got CF, visiting homepage first...\");\n    await flutterBridge.webview(BASE, '', '', '', '{}');\n\n    \/\/ 重试\n    html = await flutterBridge.webview(url, '', '', '', '{}');\n    if (html && html.length >= 100 && !isCloudflareChallenge(html)) {\n      return html;\n    }\n\n    return ''; \/\/ 完全失败\n  }\n\n  \/\/ ============ 通用解析:漫画列表 ============\n  \/\/ 从HTML中解析 .comic-list 或 .ewave-tab-content 列表\n  function parseComicList(html) {\n    var books = [];\n    var $doc = parseHTMLSafely(removeHTMLTags(html));\n\n    \/\/ 尝试匹配搜索结果列表:ul.row.comic-list > li\n    var items = $doc.find('.comic-list li');\n    if (items.length === 0) {\n      \/\/ 尝试匹配分类列表\n      items = $doc.find('.ewave-tab-content li.ewave-playlist-item');\n      \/\/ 分类列表是章节项,不是漫画项,跳过\n      if (items.length > 0) {\n        items = $(); \/\/ 重置,用其他方式匹配\n      }\n    }\n\n    \/\/ 如果是发现页的分类列表,匹配panel-body下的列表项\n    if (items.length === 0) {\n      items = $doc.find('.panel-body .row > li, .panel-body ul.row > li');\n    }\n\n    items.each(function() {\n      var $item = $(this);\n      var $link = $item.find('a[href*=\"\/detail\/\"]').first();\n      var $img = $item.find('.img-wrapper');\n      var $name = $item.find('.name h3 a, h3 a, .text-overflow');\n      var $status = $item.find('.item-status, p.text-overflow');\n\n      var bookUrl = $link.attr('href') || '';\n      var name = ($name.length ? $name.text().trim() : ($link.attr('title') || ''));\n      var coverUrl = $img.attr('data-original') || $img.attr('src') || '';\n\n      if (!bookUrl || !name) return;\n\n      \/\/ 确保URL是绝对路径\n      if (coverUrl && !coverUrl.startsWith('http')) {\n        coverUrl = '';\n      }\n\n      \/\/ 提取最新话\n      var latestChapter = '';\n      if ($status.length) {\n        var statusText = $status.first().text().trim();\n        \/\/ 排除纯数字的标题(可能是序号)\n        if (statusText && statusText.length < 30) {\n          latestChapter = statusText;\n        }\n      }\n\n      books.push({\n        bookUrl: bookUrl,\n        name: name,\n        author: '',\n        kind: '',\n        coverUrl: coverUrl,\n        intro: '',\n        tocUrl: bookUrl,\n        wordCount: '',\n        type: 2,\n        latestChapterTitle: latestChapter\n      });\n    });\n\n    removeHTMLSafely($doc[0]);\n    return books;\n  }\n\n  \/\/ ============ 搜索 ============\n  async function search(key, page, env) {\n    if (page > 1) return \"[]\";\n\n    var url = BASE + '\/search?q=' + encodeURIComponent(key) + '&page=' + page;\n    var html = await smartFetch(url);\n    if (!html) return \"[]\";\n\n    await flutterBridge.text(0, html);\n    var books = parseComicList(html);\n\n    \/\/ 如果搜索结果为空,尝试更模糊的匹配\n    if (books.length === 0) {\n      var $doc = parseHTMLSafely(removeHTMLTags(html));\n      $doc.find('a[href*=\"\/detail\/\"]').each(function() {\n        var $a = $(this);\n        var href = $a.attr('href');\n        var title = $a.attr('title') || $a.text().trim();\n        if (href && href.indexOf('\/detail\/') !== -1 && title && title.length > 1) {\n          \/\/ 检查是否已有\n          var exists = books.some(function(b) { return b.bookUrl === href; });\n          if (!exists) {\n            books.push({\n              bookUrl: href,\n              name: title,\n              author: '',\n              kind: '',\n              coverUrl: '',\n              intro: '',\n              tocUrl: href,\n              wordCount: '',\n              type: 2,\n              latestChapterTitle: ''\n            });\n          }\n        }\n      });\n      removeHTMLSafely($doc[0]);\n    }\n\n    return JSON.stringify(books);\n  }\n\n  \/\/ ============ 详情页 ============\n  async function info(bookurl) {\n    var fullUrl = bookurl.startsWith('http') ? bookurl : (BASE + bookurl);\n    var html = await smartFetch(fullUrl);\n    if (!html) return JSON.stringify({});\n\n    await flutterBridge.text(1, html);\n\n    var $doc = parseHTMLSafely(removeHTMLTags(html));\n\n    \/\/ 封面\n    var coverUrl = $doc.find('.comic-info .pic img').attr('data-original') ||\n                   $doc.find('.comic-info .pic img').attr('src') || '';\n\n    \/\/ 标题\n    var name = $doc.find('.comic-info .info h3 a').text().trim() ||\n               $doc.find('.comic-info .info h3').text().trim() || '';\n\n    \/\/ 作者\n    var author = '';\n    var $authorSpan = $doc.find('.comic-info .info .row span').eq(0);\n    if ($authorSpan.length) {\n      author = $authorSpan.text().replace('作者:', '').trim();\n    }\n\n    \/\/ 标签\/分类\n    var kind = '';\n    var $tagSpan = $doc.find('.comic-info .info .row span').eq(1);\n    if ($tagSpan.length) {\n      kind = $tagSpan.text().replace('标签:', '').trim();\n    }\n\n    \/\/ 状态\n    var status = '';\n    var $statusSpan = $doc.find('.comic-info .info .row span').eq(2);\n    if ($statusSpan.length) {\n      status = $statusSpan.text().replace('状态:', '').trim();\n    }\n\n    \/\/ 简介\n    var intro = '';\n    var $intro = $doc.find('.comic-info .info .text.text-row, .comic-info .info .text');\n    if ($intro.length) {\n      intro = $intro.first().text().replace('简介:', '').trim();\n    }\n\n    \/\/ 最新章节\n    var latestChapterTitle = '';\n    var $latest = $doc.find('.new-chapter a').first();\n    if ($latest.length) {\n      latestChapterTitle = $latest.text().trim();\n    }\n\n    removeHTMLSafely($doc[0]);\n\n    \/\/ 整理状态\n    var wordCount = status.indexOf('连载') !== -1 ? '连载中' : (status.indexOf('完结') !== -1 ? '已完结' : status);\n\n    var book = {\n      bookUrl: bookurl,\n      name: name,\n      author: author,\n      kind: kind,\n      coverUrl: coverUrl,\n      intro: intro,\n      tocUrl: bookurl,\n      wordCount: wordCount,\n      type: 2,\n      latestChapterTitle: latestChapterTitle\n    };\n\n    return JSON.stringify(book);\n  }\n\n  \/\/ ============ 目录页 ============\n  async function chapter(tocUrl, bookurl) {\n    var fullUrl = tocUrl.startsWith('http') ? tocUrl : (BASE + tocUrl);\n    var html = await smartFetch(fullUrl);\n    if (!html) return \"[]\";\n\n    await flutterBridge.text(2, html);\n\n    var $doc = parseHTMLSafely(removeHTMLTags(html));\n    var chapters = [];\n\n    \/\/ 正序\n    var $items = $doc.find('.ewave-playlist-content .ewave-playlist-item a');\n\n    $items.each(function(index) {\n      var $a = $(this);\n      var chapterUrl = $a.attr('href') || '';\n      var chapterName = $a.text().trim();\n\n      if (!chapterUrl || !chapterName) return;\n\n      chapters.push({\n        name: chapterName,\n        chapterId: chapterUrl,\n        index: index,\n        isPay: false,\n        isVip: false,\n        isVolume: false,\n        tag: ''\n      });\n    });\n\n    removeHTMLSafely($doc[0]);\n\n    return JSON.stringify(chapters);\n  }\n\n  \/\/ ============ 正文页(漫画图片) ============\n  \/\/ 站点使用xhr_mode加载图片,生成blob:URL仅在WebView会话中有效\n  \/\/ 需要用Canvas将blob图片转为base64 data URI才能被轻悦时光加载\n  async function content(url, bookurl) {\n    var fullUrl = url.startsWith('http') ? url : (BASE + url);\n\n    \/\/ JS: 等待图片通过XHR加载完成后,用Canvas转为base64\n    \/\/ 处理blob: URL(xhr_mode)和普通URL两种情况\n    var extractJs = '(function(){' +\n      'var imgs=document.querySelectorAll(\".chapter-images img\");' +\n      'if(imgs.length===0){' +\n      \/\/ 备用:检查.chapter-detail下的所有图片\n      '  imgs=document.querySelectorAll(\".chapter-detail img\");' +\n      '}' +\n      'var result=[];var pending=imgs.length;' +\n      'if(pending===0)return \"\";' +\n      \/\/ 等待图片加载并转为base64\n      'return new Promise(function(resolve){' +\n      '  var results=[];var done=0;var hasBase64=false;' +\n      '  function finish(){' +\n      '    done++;if(done>=pending){' +\n      '      if(hasBase64){resolve(results.join(\"\"))}else{resolve(\"\")}' +\n      '    }' +\n      '  }' +\n      '  imgs.forEach(function(img,i){' +\n      '    function convert(){' +\n      '      try{' +\n      '        if(img.complete&&img.naturalWidth>0){' +\n      '          var c=document.createElement(\"canvas\");' +\n      '          var maxW=1200;var w=img.naturalWidth;var h=img.naturalHeight;' +\n      '          if(w>maxW){h=h*maxW\/w;w=maxW}' +\n      '          c.width=w;c.height=h;' +\n      '          var ctx=c.getContext(\"2d\");ctx.drawImage(img,0,0,w,h);' +\n      '          var dataUrl=c.toDataURL(\"image\/webp\",0.7);' +\n      '          if(dataUrl&&dataUrl.length>100){' +\n      '            results[i]=\\'<img src=\"\\'+dataUrl+\\'\" \/>\\';hasBase64=true;' +\n      '            finish();return;' +\n      '          }' +\n      '        }' +\n      '      }catch(e){}' +\n      \/\/ Canvas转换失败或图片未加载 → 降级为原始URL\n      '      var src=img.getAttribute(\"data-original\")||img.src||\"\";' +\n      '      if(src&&src.indexOf(\"static\/img\")===-1){' +\n      '        results[i]=\\'<img src=\"\\'+src+\\'\" \/>\\';' +\n      '      }else{results[i]=\"\"}' +\n      '      finish();' +\n      '    }' +\n      '    if(img.complete){convert()}' +\n      '    else{' +\n      '      img.onload=function(){convert()};' +\n      '      img.onerror=function(){' +\n      '        results[i]=\"\";finish();' +\n      '      };' +\n      \/\/ 超时5秒\n      '      setTimeout(function(){if(!results[i]){convert()}},5000);' +\n      '    }' +\n      '  });' +\n      \/\/ 全局超时10秒\n      '  setTimeout(function(){if(done<pending){' +\n      '    for(var k=0;k<pending;k++){if(!results[k])results[k]=\"\"}' +\n      '    done=pending;resolve(results.join(\"\"));' +\n      '  }},10000);' +\n      '})})()';\n\n    try {\n      \/\/ 方式1: WebView + Promise → Canvas转base64\n      var result = await flutterBridge.webview(fullUrl, extractJs, '', '', '{}');\n\n      if (result && result.length >= 100 && result.indexOf('<img') !== -1) {\n        return result;\n      }\n\n      \/\/ 方式2: Promise不支持时降级 → 同步提取\n      var syncJs = '(function(){var r=[];var imgs=document.querySelectorAll(\".chapter-images img\");for(var i=0;i<imgs.length;i++){var img=imgs[i];try{if(img.complete&&img.naturalWidth>0){var c=document.createElement(\"canvas\");var maxW=1200;var w=img.naturalWidth;var h=img.naturalHeight;if(w>maxW){h=h*maxW\/w;w=maxW}c.width=w;c.height=h;var ctx=c.getContext(\"2d\");ctx.drawImage(img,0,0,w,h);var d=c.toDataURL(\"image\/webp\",0.7);if(d&&d.length>100){r.push(\\'<img src=\"\\'+d+\\'\" \/>\\')}else{var s=img.getAttribute(\"data-original\")||img.src||\"\";if(s)r.push(\\'<img src=\"\\'+s+\\'\" \/>\\')}}else{var s=img.getAttribute(\"data-original\")||img.src||\"\";if(s)r.push(\\'<img src=\"\\'+s+\\'\" \/>\\')}}catch(e){var s=img.getAttribute(\"data-original\")||img.src||\"\";if(s)r.push(\\'<img src=\"\\'+s+\\'\" \/>\\')}}return r.join(\"\")})()';\n\n      var syncResult = await flutterBridge.webview(fullUrl, syncJs, '', '', '{}');\n      if (syncResult && syncResult.length >= 50) {\n        return syncResult;\n      }\n\n      \/\/ 方式3: 完全失败\n      return \"图片加载失败,请先打开发现页浏览任意漫画完成验证后重试。\";\n    } catch (e) {\n      flutterBridge.log(\"content error: \" + e.message);\n      return \"图片加载失败:\" + e.message;\n    }\n  }\n\n  \/\/ ============ 发现 ============\n  async function getfinds() {\n    var discoveries = [\n      {\n        title: '最近更新',\n        url: BASE + '\/update?page={{page}}',\n        type: 0,\n        width: 0\n      },\n      {\n        title: '排行榜',\n        url: BASE + '\/rank?page={{page}}',\n        type: 0,\n        width: 0\n      },\n      {\n        title: '国内漫画',\n        url: BASE + '\/list\/area\/guonei?page={{page}}',\n        type: 0,\n        width: 0\n      },\n      {\n        title: '日本漫画',\n        url: BASE + '\/list\/area\/riben?page={{page}}',\n        type: 0,\n        width: 0\n      },\n      {\n        title: '韩国漫画',\n        url: BASE + '\/list\/area\/hanguo?page={{page}}',\n        type: 0,\n        width: 0\n      },\n      {\n        title: '欧美漫画',\n        url: BASE + '\/list\/area\/oumei?page={{page}}',\n        type: 0,\n        width: 0\n      }\n    ];\n\n    return JSON.stringify(discoveries);\n  }\n\n  \/\/ ============ 发现页分类浏览 ============\n  async function find(url, page) {\n    var fullUrl = url.replace('{{page}}', page);\n    var html = await smartFetch(fullUrl);\n    if (!html) return \"[]\";\n\n    await flutterBridge.text(0, html);\n\n    var books = [];\n    var $doc = parseHTMLSafely(removeHTMLTags(html));\n\n    \/\/ 排行榜页面有不同结构\n    if (fullUrl.indexOf('\/rank') !== -1) {\n      \/\/ 排行榜使用 .ranking-list .ranking-item\n      $doc.find('.ranking-list .ranking-item').each(function() {\n        var $item = $(this);\n        var $link = $item.find('a[href*=\"\/detail\/\"]').first();\n        var $img = $item.find('.img-wrapper');\n        var $name = $item.find('h4.text-overflow');\n        var $status = $item.find('.ranking-item-info p');\n\n        var bookUrl = $link.attr('href') || '';\n        var name = $name.text().trim();\n        var coverUrl = $img.attr('data-original') || '';\n        var latestChapter = $status.first().text().trim();\n\n        if (!bookUrl || !name) return;\n\n        books.push({\n          bookUrl: bookUrl,\n          name: name,\n          author: '',\n          kind: '',\n          coverUrl: coverUrl,\n          intro: '',\n          tocUrl: bookUrl,\n          wordCount: '',\n          type: 2,\n          latestChapterTitle: latestChapter\n        });\n      });\n    } else {\n      \/\/ 普通列表页:匹配 .panel-body 或其他容器中的漫画项目\n      \/\/ 查找包含 \/detail\/ 链接的列表项\n      var $items = $doc.find('.row > li, .panel-body li, ul.row > li');\n\n      $items.each(function() {\n        var $item = $(this);\n        var $link = $item.find('a[href*=\"\/detail\/\"]').first();\n        if (!$link.length) return;\n\n        var bookUrl = $link.attr('href') || '';\n        var name = $link.attr('title') || $link.text().trim();\n\n        \/\/ 排除导航链接\n        if (bookUrl.indexOf('\/detail\/') === -1) return;\n\n        var $img = $item.find('.img-wrapper');\n        var coverUrl = $img.attr('data-original') || '';\n        var $status = $item.find('.item-status, p.text-overflow');\n        var latestChapter = $status.first().text().trim();\n\n        \/\/ 排除过长的状态文字(可能是简介)\n        if (latestChapter.length > 30) latestChapter = '';\n\n        books.push({\n          bookUrl: bookUrl,\n          name: name,\n          author: '',\n          kind: '',\n          coverUrl: coverUrl,\n          intro: '',\n          tocUrl: bookUrl,\n          wordCount: '',\n          type: 2,\n          latestChapterTitle: latestChapter\n        });\n      });\n    }\n\n    \/\/ 如果上面都没解析到,用通用解析\n    if (books.length === 0) {\n      books = parseComicList(html);\n    }\n\n    removeHTMLSafely($doc[0]);\n\n    return JSON.stringify(books);\n  }\n\n  \/\/ ============ 登录(用于过Cloudflare) ============\n  async function getloginurl() {\n    return BASE;\n  }\n\n  async function login() {\n    \/\/ 用户在浏览器中过CF验证后自动完成\n  }\n\n  \/\/ ============ 帮助 ============\n  async function gethelp() {\n    return '@html:<div style=\"padding:16px;line-height:1.8;\">' +\n      '<h3>豆包漫画书源<\/h3>' +\n      '<p>来源:doubaomanhua.com<\/p>' +\n      '<p>类型:漫画<\/p>' +\n      '<p>支持搜索、分类浏览、排行榜<\/p>' +\n      '<p style=\"margin-top:12px;color:#999;\">如遇图片加载失败,请在发现页\"最近更新\"进入任意漫画后返回,以通过Cloudflare验证。<\/p>' +\n      '<\/div>';\n  }\n<\/script>\n<\/html>\n",
    "login": true,
    "lastUpdateTime": "1784436737525"
}
广告