Greasy Fork

Greasy Fork is available in English.

Manhuagui - Recover Blocked Manga

Recover blocked manga on www.manhuagui.com

当前为 2022-07-09 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Manhuagui - Recover Blocked Manga
// @namespace    https://www.manhuagui.com/
// @version      0.1
// @description  Recover blocked manga on www.manhuagui.com
// @author       DD1969
// @match        https://www.manhuagui.com/comic/*/
// @match        https://www.manhuagui.com/comic/*/*.html
// @require      https://unpkg.com/[email protected]/dist/axios.min.js
// @require      https://unpkg.com/[email protected]/dist/lazyload.min.js
// @icon         https://www.google.com/s2/favicons?sz=64&domain=manhuagui.com
// @grant        none
// ==/UserScript==

(async function(axios, LazyLoad) {
  'use strict';

  try {
    // check if current comic/chapter is blocked
    const isBlocked = await axios.get(window.location.href).then(res => res.data.match(/erroraudit_show/) !== null);
    if (!isBlocked) {
      console.log('No need to recover.');
      return;
    }

    window.location.href.includes('.html') ? loadImages() : loadCatalog();
  } catch (error) {
    console.log(error);
  }

  async function loadCatalog() {
    // setup container
    const container = await getContainer();
    container.classList.add('chapter-list');
    container.innerHTML = '<ul style="display: block;" id="recover-list"></ul>';
    const list = document.getElementById('recover-list');

    // get comic id and latest chapter id
    const latestChapterURL = document.querySelector('.detail-list .status a.blue').href;
    const latestChapterData = await getChapterData(latestChapterURL);
    const comicID = latestChapterData.bid;
    let currentTargetID = latestChapterData.cid;

    // store all collected chapter data
    let chapterData = [];

    // if there is data stored in localStorage before, get them and process
    const storedChapterDataString = window.localStorage.getItem('recovered-chapter-data');
    if (storedChapterDataString) {
      const storedChapterData = JSON.parse(storedChapterDataString);
      chapterData = [].concat(storedChapterData);
      chapterData.forEach(data => {
        const listItem = getListItem(data.url, data.title, data.pageAmount);
        list.appendChild(listItem);
      });

      currentTargetID = chapterData[chapterData.length - 1].prevID;
    }

    // get chapter data with interval
    const timer = setInterval(async () => {
      if (currentTargetID === 0) {
        clearInterval(timer);
        console.log('All chapters are recovered.');
      } else {
        const currentChapterURL = `https://www.manhuagui.com/comic/${comicID}/${currentTargetID}.html`;
        const { cname, len, prevId } = await getChapterData(currentChapterURL);

        const listItem = getListItem(currentChapterURL, cname, len);
        list.appendChild(listItem);

        // update localStorage
        chapterData.push({
          url: currentChapterURL,
          title: cname,
          pageAmount: len,
          prevID: prevId
        });
        window.localStorage.setItem('recovered-chapter-data', JSON.stringify(chapterData));

        currentTargetID = prevId;
      }
    }, 10 * 1000); // 10 seconds per chapter
  }

  async function loadImages() {
    // generate image urls
    const imageURLs = await getChapterData(window.location.href).then(({ files, path, sl }) => {
      const origin = 'https://us.hamreus.com';
      return files.map(fileName => `${origin}${path}${fileName}?e=${sl.e}&m=${sl.m}`)
    });

    // load images
    const container = await getContainer();
    container.innerHTML = `${imageURLs.reduce((acc, cur) => {
      return acc + `<img class="lazy" data-src="${cur}" style="display:block; min-height: 400px; max-width: 80vw;" />`;
    }, '')}`;

    // setup image lazyload
    new LazyLoad({ threshold: 900 });
  }

  // wait for the div element whose id is 'erroraudit_show' appear
  async function getContainer() {
    const container = await new Promise(resolve => {
      const timer = setInterval(() => {
        const errorAudit = document.getElementById('erroraudit_show');
        if (errorAudit) {
          clearInterval(timer);
          resolve(errorAudit);
        }
      }, 100);
    });

    container.classList.remove('warning-bar');
    container.id = 'recover-container';

    return container;
  }

  // generate list item
  function getListItem(href, title, pageAmount) {
    const li = document.createElement('li');
    li.innerHTML = `
      <a href="${href}" title="${title}" class="status0" target="_blank" rel="noopener noreferrer">
        <span style="display: flex; justify-content: center; align-items: center;">
          <span style="max-width: 75%; border: none; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">${title}</span>
          <i>${pageAmount}p</i>
        </span>
      </a>
    `;
    return li;
  }

  // get episode data from <script> tag of the html
  async function getChapterData(url) {
    return await axios
      .get(url)
      .then(res => {
        const script = res.data.match(/window\["\\x65\\x76\\x61\\x6c"\].*\{\}\)\)/gm)[0];
        const func = script.replace(`window["\\x65\\x76\\x61\\x6c"]`, 'episodeDataString = ');
        window.eval(func);
        return JSON.parse(episodeDataString.replace('SMH.imgData(', '').replace(').preInit();', ''));
      });
  }

})(axios, LazyLoad);