樱花动漫

https://www.yinhuadm.xyz

zpccool (13551) 2小时前 下载:72

视频
樱花动漫 - 日漫在线观看
二维码导入(APP尚未完成该功能)
// @name        樱花动漫
// @uuid        yinhua-dm-xyz
// @version     1.1.0
// @author      AI
// @url         https://www.yinhuadm.xyz
// @type        video
// @enabled     true
// @description 樱花动漫 - 日漫在线观看

var BASE = "https://www.yinhuadm.xyz";

var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function base64decode(str) {
  var out = "";
  var i = 0;
  var len = str.length;
  while (i < len) {
    var c1 = B64.indexOf(str.charAt(i++));
    var c2 = B64.indexOf(str.charAt(i++));
    if (c1 === -1 || c2 === -1) break;
    out += String.fromCharCode((c1 << 2) | (c2 >> 4));
    var c3 = B64.indexOf(str.charAt(i++));
    if (c3 === -1) break;
    out += String.fromCharCode(((c2 & 15) << 4) | (c3 >> 2));
    var c4 = B64.indexOf(str.charAt(i++));
    if (c4 === -1) break;
    out += String.fromCharCode(((c3 & 3) << 6) | c4);
  }
  return out;
}

var CATEGORIES = {
  追番周表: "week",
  今日更新: "new",
  热榜: "hot",
  新片上线: "newAnime"
};

var TITLE_FILTER = /^(更新至第?\d+集|已?完结|动漫|[Hh][Dd]中字|[Hh][Dd])$/;

function absUrl(href) {
  if (!href) return "";
  if (href.indexOf("http") === 0) return href;
  if (href.charAt(0) === '/') return BASE + href;
  return BASE + '/' + href;
}

async function search(keyword, page) {
  legado.log("[search] keyword=" + keyword + " page=" + page);
  var searchUrl = BASE + '/vch/' + encodeURIComponent(keyword) + '.html';
  if (page > 1) searchUrl = BASE + '/vch/' + encodeURIComponent(keyword) + '/page/' + page + '.html';

  var id = await legado.browser.create({ visible: false });
  await legado.browser.navigate(id, searchUrl, { waitUntil: "networkidle", timeoutSecs: 30 });

  var data = await legado.browser.eval(id, "return (function(){" +
    "var r=[];" +
    "var seen={};" +
    "var items=document.querySelectorAll('a[href*=\"/v/\"]');" +
    "for(var i=0;i<items.length;i++){" +
    "  var a=items[i];" +
    "  var href=a.href;" +
    "  if(href.indexOf('/v/')===-1)continue;" +
    "  var title=a.title||a.getAttribute('title')||a.innerText.trim()||'';" +
    "  if(!title||title.indexOf('http')===0||title.length>=100)continue;" +
    "  if(" + TITLE_FILTER.toString() + ".test(title))continue;" +
    "  if(seen[href])continue;" +
    "  seen[href]=true;" +
    "  var img=a.querySelector('img')||a.parentNode.querySelector('img');" +
    "  var cover=img?(img.src||img.getAttribute('data-src')||''):'';" +
    "  var nextA=items[i+1];" +
    "  var updateText=nextA?(nextA.innerText.trim()||''):'';" +
    "  r.push({url:href,title:title,cover:cover,update:updateText});" +
    "}" +
    "return JSON.stringify(r);" +
    "})()");

  await legado.browser.close(id);

  var books = [];
  if (data) {
    try {
      var items = JSON.parse(data);
      for (var i = 0; i < items.length; i++) {
        var item = items[i];
        if (item.url && item.title) {
          books.push({
            name: item.title.trim(),
            bookUrl: absUrl(item.url),
            coverUrl: item.cover || "",
            latestChapter: item.update || "",
            kind: ""
          });
        }
      }
    } catch (e) {}
  }
  return books;
}

async function bookInfo(bookUrl) {
  var id = await legado.browser.create({ visible: false });
  await legado.browser.navigate(id, bookUrl, { waitUntil: "networkidle", timeoutSecs: 30 });

  var name = await legado.browser.eval(id, "return (document.querySelector('h1')||{}).innerText||''");
  var coverUrl = await legado.browser.eval(id,
    "var img=document.querySelector('.module-item-pic img')||document.querySelector('.module-item-cover img');" +
    "return img?(img.src||img.getAttribute('data-original')||img.getAttribute('data-src')||''):'';");
  var intro = await legado.browser.eval(id, "return (document.querySelector('.vod_content')||{}).innerText||''");
  var remark = await legado.browser.eval(id, "return (document.querySelector('.update')||{}).innerText||''");

  await legado.browser.close(id);

  return {
    name: name.trim(),
    author: "",
    bookUrl: bookUrl,
    coverUrl: coverUrl || "",
    intro: intro || "",
    latestChapter: remark || "",
    tocUrl: bookUrl
  };
}

async function chapterList(tocUrl) {
  var vidMatch = String(tocUrl).match(/\/v\/(\d+)\.html/);
  var vid = vidMatch ? vidMatch[1] : "";

  var id = await legado.browser.create({ visible: false });
  await legado.browser.navigate(id, tocUrl, { waitUntil: "networkidle", timeoutSecs: 30 });

  var vidFilter = vid ? ("href.indexOf('/p/" + vid + "-')===-1") : "false";
  var data = await legado.browser.eval(id, "return (function(){" +
    "var r=[];" +
    "var seen={};" +
    "var links=document.querySelectorAll('a[href*=\"/p/\"]');" +
    "for(var i=0;i<links.length;i++){" +
    "  var a=links[i];" +
    "  var href=a.href;" +
    "  if(!href||href.indexOf('/p/')===-1)continue;" +
    "  var match=href.match(/\\/p\\/\\d+-(\\d+)-(\\d+)\\.html/);" +
    "  if(!match)continue;" +
    "  if(" + vidFilter + ")continue;" +
    "  if(seen[href])continue;" +
    "  seen[href]=true;" +
    "  var epNum=parseInt(match[2],10);" +
    "  var lineNum=parseInt(match[1],10);" +
    "  var epStr=epNum<10?('0'+epNum):(''+epNum);" +
    "  var name='第'+epStr+'集';" +
    "  var group='线路'+lineNum;" +
    "  r.push({name:name,url:href,ep:epNum,line:lineNum,group:group});" +
    "}" +
    "return JSON.stringify(r);" +
    "})()");

  await legado.browser.close(id);

  var chapters = [];
  if (data) {
    try {
      var items = JSON.parse(data);
      items.sort(function(a, b) {
        if ((a.line || 0) !== (b.line || 0)) return (a.line || 0) - (b.line || 0);
        return (a.ep || 0) - (b.ep || 0);
      });
      for (var i = 0; i < items.length; i++) {
        chapters.push({
          name: items[i].name || "第" + (i + 1) + "集",
          url: absUrl(items[i].url),
          group: items[i].group || ""
        });
      }
    } catch (e) {}
  }
  return chapters;
}

// ── chapterContent ─────────────────────────────────────
// 流程:
//   1) 加载章节页 → 从 player_aaaa 提取 MCZY 链接
//   2) 导航到播放器页 (player.mcue.cc) → 播放器 JS 自动解密并请求 m3u8
//   3) onRequest + captureBody 拦截 m3u8 响应 → 检查 #EXTM3U → 返回真实地址

async function chapterContent(chapterUrl) {
  legado.log("[chapterContent] url=" + chapterUrl);

  function startsWithExtM3u(text) {
    var value = String(text || "");
    if (value.charCodeAt(0) === 0xfeff) value = value.substring(1);
    value = value.replace(/^\s+/, "").toUpperCase();
    return value.indexOf("#EXTM3U") === 0;
  }

  function shouldExclude(url, ct) {
    var lurl = String(url || "").toLowerCase();
    var lct = String(ct || "").toLowerCase();
    if (lurl.indexOf("data:") === 0) return true;
    if (lurl.indexOf("ipc.localhost") !== -1) return true;
    if (lurl.indexOf(".js") !== -1 || lurl.indexOf(".css") !== -1) return true;
    if (lurl.indexOf(".png") !== -1 || lurl.indexOf(".jpg") !== -1 ||
        lurl.indexOf(".jpeg") !== -1 || lurl.indexOf(".gif") !== -1 ||
        lurl.indexOf(".webp") !== -1 || lurl.indexOf(".ico") !== -1 ||
        lurl.indexOf(".svg") !== -1 || lurl.indexOf(".woff") !== -1 ||
        lurl.indexOf(".ttf") !== -1) return true;
    if (lct.indexOf("javascript") !== -1 || lct.indexOf("text/css") !== -1) return true;
    if (lct.indexOf("image/") === 0 || lct.indexOf("font/") === 0) return true;
    return false;
  }

  var id = await legado.browser.create({ visible: false, muted: true });
  var playUrl = "";
  var evtTotal = 0;

  legado.browser.onRequest(id, function(evt) {
    evtTotal++;
    if (playUrl) return;
    if (!evt || evt.type !== "response") return;
    var url = String(evt.url || "");
    var lurl = url.toLowerCase();
    var s = evt.status || 0;

    if (shouldExclude(url, (evt.responseHeaders && evt.responseHeaders["content-type"]) || "")) return;

    if (lurl.indexOf("m3u8") !== -1) {
      var responseBody = evt.responseBody || "";
      legado.log("[chapterContent] m3u8 resp status=" + s + " len=" + responseBody.length + " url=" + url);
      if ((s === 200 || s === 206) && startsWithExtM3u(responseBody)) {
        playUrl = url;
        legado.log("[chapterContent] m3u8 found: " + url);
      }
      return;
    }

    if (s === 200) {
      var body = evt.responseBody || "";
      if (startsWithExtM3u(body)) {
        playUrl = url;
        legado.log("[chapterContent] m3u8 found(body): " + url);
      }
    }
  }, { captureBody: true });

  // 步骤1:加载章节页,提取 MCZY 链接
  await legado.browser.navigate(id, chapterUrl, { waitUntil: "networkidle", timeoutSecs: 30 });
  legado.log("[chapterContent] chapter loaded, events=" + evtTotal);

  var mczyUrl = "";

  // 先看 HTML 里有没有直接的 m3u8
  if (!playUrl) {
    var html = await legado.browser.html(id);
    var htmlStr = String(html || "");
    var m3u8Match = htmlStr.match(/https?:\/\/[^\s"'<>]+\.m3u8[^\s"'<>]*/i);
    if (m3u8Match) { playUrl = m3u8Match[0]; legado.log("[chapterContent] m3u8 in chapter html"); }
  }

  // 没直接 m3u8 就提取 player_aaaa → MCZY
  if (!playUrl && !mczyUrl) {
    try {
      var pRaw = await legado.browser.eval(id,
        "try{var s=JSON.stringify(player_aaaa||{});return s;}catch(e){return'';}");
      if (pRaw && pRaw.length > 5) {
        var pd = JSON.parse(pRaw);
        if (pd && pd.url) {
          var vurl = String(pd.url);
          var enc = String(pd.encrypt || "");
          if (enc === "1") vurl = unescape(vurl);
          else if (enc === "2") vurl = unescape(base64decode(vurl));
          mczyUrl = vurl;
          legado.log("[chapterContent] MCZY=" + mczyUrl);
        }
      }
    } catch(e) {
      legado.log("[chapterContent] player_aaaa parse err: " + e.message);
    }
  }

  // 步骤2:导航到播放器页面,让播放器 JS 解密并请求真实 m3u8
  if (!playUrl && mczyUrl) {
    var playerPageUrl = "https://player.mcue.cc/yinhua/?url=" + encodeURIComponent(mczyUrl);
    legado.log("[chapterContent] navigating to player: " + playerPageUrl);

    await legado.browser.navigate(id, playerPageUrl, { waitUntil: "load", timeoutSecs: 30 });
    legado.log("[chapterContent] player page loaded, events=" + evtTotal);

    // 等待播放器 JS 执行并请求 m3u8(HLS 初始化需要时间)
    await legado.sleep(6000);
    legado.log("[chapterContent] after wait, events=" + evtTotal + " playUrl=" + (playUrl || "NONE"));
  }

  // 步骤3:如果还没抓到,用 eval 从 video 元素 / 全局变量获取
  if (!playUrl) {
    try {
      var evalRes = await legado.browser.eval(id,
        "(function(){" +
        "var v=document.querySelector('video');" +
        "if(v){var s=v.src||v.currentSrc||'';if(s.indexOf('http')===0)return s;}" +
        "if(typeof config!=='undefined'&&config){return JSON.stringify(config.url||'');}" +
        "return'';" +
        "})()");
      if (evalRes && evalRes.length > 10 && evalRes.indexOf("http") === 0) {
        playUrl = evalRes;
        legado.log("[chapterContent] eval video/config: " + playUrl);
      } else if (evalRes) {
        legado.log("[chapterContent] eval raw=" + evalRes);
      }
    } catch(e3) {
      legado.log("[chapterContent] eval err: " + e3.message);
    }
  }

  // 步骤4:如果还是没抓到,从播放器页 HTML 里找
  if (!playUrl) {
    try {
      var pHtml = await legado.browser.html(id);
      var m = pHtml.match(/https?:\/\/[^\s"'<>]+\.m3u8[^\s"'<>]*/i);
      if (m) { playUrl = m[0]; legado.log("[chapterContent] m3u8 from player html"); }
    } catch(e4) {}
  }

  // 清理
  try {
    await legado.browser.eval(id,
      'try{document.querySelectorAll("video,audio").forEach(function(el){' +
      'try{el.pause();el.removeAttribute("src");el.load();}catch(e2){}});}catch(e){}');
  } catch(e) {}
  await legado.browser.navigate(id, BASE, { waitUntil: "load", timeoutSecs: 10 });
  legado.log("[chapterContent] events after backNav=" + evtTotal + " playUrl=" + (playUrl || "NONE"));

  legado.browser.offRequest(id);
  await legado.browser.close(id);

  if (playUrl && playUrl.length > 10) {
    legado.log("[chapterContent] result=" + playUrl);
    return playUrl;
  }
  legado.log("[chapterContent] no m3u8 found");
  return "";
}

// ── explore ─────────────────────────────────────────────
async function explore(page, category) {
  if (category === "GETALL") {
    return Object.keys(CATEGORIES);
  }

  var catKey = CATEGORIES[category] || "new";
  var url;
  if (catKey === "week") url = BASE + '/label/week.html';
  else if (catKey === "new") url = BASE + '/label/new.html';
  else if (catKey === "hot") url = BASE + '/label/hot.html';
  else url = BASE + '/s/1.html';
  if (page > 1) url = url.replace('.html', '/' + page + '.html');

  var id = await legado.browser.create({ visible: false });
  await legado.browser.navigate(id, url, { waitUntil: "networkidle", timeoutSecs: 30 });

  var data = await legado.browser.eval(id, "return (function(){" +
    "var r=[];" +
    "var seen={};" +
    "var items=document.querySelectorAll('a[href*=\"/v/\"]');" +
    "for(var i=0;i<items.length;i++){" +
    "  var a=items[i];" +
    "  var href=a.href;" +
    "  if(href.indexOf('/v/')===-1)continue;" +
    "  var title=a.title||a.getAttribute('title')||a.innerText.trim()||'';" +
    "  if(!title||title.indexOf('http')===0||title.length>=100)continue;" +
    "  if(" + TITLE_FILTER.toString() + ".test(title))continue;" +
    "  if(seen[href])continue;" +
    "  seen[href]=true;" +
    "  var imgNode=a.querySelector('img')||a.parentNode.querySelector('img');" +
    "  var cover=imgNode?(imgNode.src||imgNode.getAttribute('data-src')||''):'';" +
    "  r.push({url:href,title:title,cover:cover});" +
    "}" +
    "return JSON.stringify(r);" +
    "})()");

  await legado.browser.close(id);

  var books = [];
  if (data) {
    try {
      var items = JSON.parse(data);
      for (var i = 0; i < items.length; i++) {
        var item = items[i];
        if (item.url && item.title) {
          books.push({
            name: item.title.trim(),
            bookUrl: absUrl(item.url),
            coverUrl: item.cover || "",
            latestChapter: "",
            kind: category
          });
        }
      }
    } catch (e) {}
  }
  return books;
}
广告