ehentai显示已下载 提取页面元数据

exhentai-manga-manager的附加浏览器脚本

ของเมื่อวันที่ 22-10-2023 ดู เวอร์ชันล่าสุด

// ==UserScript==
// @name         ehentai显示已下载 提取页面元数据
// @namespace    http://tampermonkey.net/
// @version      1.4
// @license      MIT
// @description  exhentai-manga-manager的附加浏览器脚本
// @author       You
// @match        *exhentai.org/*
// @match        *e-hentai.org/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=exhentai.org
// @grant        GM_addStyle
// @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
// ==/UserScript==

(function() {
    GM_addStyle(`

.mark {
  cursor:pointer;
  position: relative;
  background:rgba(0, 0, 0, 0.1);
}

.mark::before {
text-align: center;
  content: "点击录入元数据";
  position: absolute;
  width:100px;
  top: -5px;
  left: 50%;
  transform: translate(-50%,0);
  padding: 5px;
  background-color: #444;
  color: #fff;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
  border-radius: 5px;
}

.mark:hover::before {
  opacity: 1;
  visibility: visible;
}
.copyed{
    font-size:30px;
    position:fixed;
    left: 50%;
    top:100px;
    transform: translate(-50%,0);
    z-index:99;
    padding:10px;
    background-color: #444;
    border-radius: 10px;
    display:none;
    color:#fff;

}
.showDialog{
      white-space: nowrap;
      position:fixed;
      background-color: #444;
      border-radius: 10px;
      padding:18.7px;
      z-index:99;
      color:#fff;
      left: 50%;
      transform: translate(-50%,0);
      vertical-align: middle;
      display:none;
  }
  .showDialog div
  .right{

  }
  .inputtext{
    width: 400px;
  }
  .pointer{
cursor: pointer;
  }
    `);

    'use strict';
    $("body").prepend("<div class='showDialog'><div><label>端口号<input type='text' class='right inputtext port'></label></div> <br> <div> <label> <span title='点击选择文件路径' class='pointer'>database路径</span> <input type='file' style='display: none;' id='database' name='file'> <input type='text' class='right inputtext databasepath' name=''> </label> </div> <br> <div> <label> <span title='点击选择文件路径' class='pointer'>metabase路径</span> <input type='file' style='display: none;' id='metabase' name='file'> <input type='text' class='right inputtext metadatapath' > </label> </div> <br> <div class='right'> <button class='confim'>保存</button> <button class='close'>关闭</button> </div> </div>");

    $("body").prepend("<a class='setting'></a>");
    $("body").prepend("<div class='copyed'></div>");
    $(".showDialog .close").click(function(){
        $(".showDialog").hide();
    });
    $(".showDialog .confim").click(function(){
        if( ($(".showDialog .databasepath").val()!='')&&($(".showDialog .port").val()!='')&&($(".showDialog .metadatapath").val()!='')){
            if(confirm("要保存当前配置吗?")){
                   setting("del");
                   setting("add");
            }
        }else{
            alert("配置不完整");
        }

    });
    $('#database').change(function() {
        $(".showDialog .databasepath").val(this.value);
    });
    $('#metabase').change(function() {
        $(".showDialog .metadatapath").val(this.value);
    });
    var ehid;
    var url=window.location.href;
    var result_port;
    var result_appAppDatapath;
    var result_metadatapath;
    var metadatapath;
    const request = indexedDB.open('ex1', 1);
    request.onupgradeneeded = function(event) {
        const db = event.target.result;
        //  检查对象存储空间是否存在
        if (!db.objectStoreNames.contains('setting')) {

            // 创建对象存储空间
            const objectStore = db.createObjectStore('setting', { keyPath: 'name' });
        }
    };
    request.onsuccess = function(event) {
        const db = event.target.result;

        // 开始事务(读写模式)
        const transaction = db.transaction(['setting'], 'readwrite');

        // 获取对象存储空间
        const store = transaction.objectStore('setting');
        // 获取数据
        store.get("appAppDatapath").onsuccess = function(event) {
            result_appAppDatapath = event.target.result;

        };

        store.get("port").onsuccess = function(event) {
            result_port = event.target.result;
        

        };
        store.get("metadatapath").onsuccess = function(event) {
            result_metadatapath = event.target.result;

        };

        transaction.oncomplete = function() {
            //端口路径为空时
            if((result_appAppDatapath==undefined)||(result_port==undefined)||(result_metadatapath==undefined)){
                $(".setting").html("没有设置端口或数据库文件路径,点击设置");
                $(".setting").click(function(){
                    $(".showDialog").show(50);

                });
            }else{
               
                $(".setting").html("已设置端口和数据库路径");

                //删除indexdb
                $(".setting").click(function(){
                    $(".showDialog .databasepath").val(result_appAppDatapath['val']);
                    $(".showDialog .port").val(result_port['val']);
                    $(".showDialog .metadatapath").val(result_metadatapath['val']);
                    $(".showDialog").show();
//                     if(confirm("是否要清空端口和路径")){
//                         setting('del');

//                     }

                });
                //主功能开始
                //漫画详细页
                if(url.indexOf("hentai.org/g/")!=-1){
                    //详情页显示
                    $("#taglist").append("<div class='mark'><div style='color:#999;text-align: center;'>未连接</div></div>");
                    //获取当前uid
                    ehid='["/'+url.split("/")[4]+'/"]';
                    //显示有没有下载
                    $.ajax({
                        url: "http://localhost:"+result_port['val']+"/data.php",  // 请求的URL
                        method: "POST",  // 请求方法,可选项包括 "GET", "POST", "PUT", "DELETE" 等.
                        data:{
                            appAppDatapath:result_appAppDatapath['val'],
                            metadatapath:result_metadatapath['val'],
                            ehid:ehid,
                            fun:'showDownload'
                        },  // 请求参数,如果不需要传递参数可以省略
                        success: function(response) {
                            response = eval(response)[0];
                            if(ehid.indexOf(response)!=-1){
                                $(".mark").html("<div style='color:#1b1;text-align: center;'>已下载</div>");

                            }else{
                                $(".mark").html("<div style='color:#999;text-align: center;'>未下载</div>");
                            }
                        },
                        error: function(xhr, status, error) {
                            console.log("请求错误:", error);
                        }
                    });
                    //点击后添加到数据库
                    $(".mark").click(function(){
                        updateSqlite(url,result_appAppDatapath['val'],result_port['val'],result_metadatapath['val'])
                    });
                }
                //e站搜索页面
                if(url.indexOf("hentai.org")!=-1&&$("#toppane").length==1){

                    ehid=[];
                    $("#f_search").contextmenu(function(){
                        $("#f_search").val("");
                    });
                    //格式化搜索框内的内容
                    $("#f_search").change(function(){
                        var kw=$("#f_search").val();
                        kw=kw.replace(/\(.*?\)/g,'');
                        kw=kw.replaceAll('~','');
                        kw=kw.replace('.zip','');
                        if(!isNaN(kw.substring(0,kw.indexOf("-")))){
                            kw=kw.substring(kw.indexOf("-")+1,kw.length);
                        }
                        $("#f_search").val(kw);
                        $("#f_search").next().trigger("click");
                    });
                    $(".gl1t").append("<div class='mark'><div style='color:#999;text-align: center;'>未连接</div></div>");
                    $(".mark").click(function(){
                        updateSqlite($(this).parent().find("a").attr("href"),result_appAppDatapath['val'],result_port['val'],result_metadatapath['val'])
                    });
                    $(".gl1t").each(function(){
                        var ehurl=$(this).find("a").attr("href");
                        ehurl=ehurl.split("/");
                        ehid.push("/"+ehurl[4]+"/");
                    });
                    $.ajax({
                        url: "http://localhost:"+result_port['val']+"/data.php",  // 请求的URL
                        method: "POST",  // 请求方法,可选项包括 "GET", "POST", "PUT", "DELETE" 等.
                        data: {
                            appAppDatapath:result_appAppDatapath['val'],
                            result_metadatapath:result_metadatapath['val'],
                            ehid:JSON.stringify(ehid),
                            fun:'showDownload'
                        },  // 请求参数,如果不需要传递参数可以省略
                        success: function(response){
                            //转为对象
                            var back_obj = eval(response);
                            $(".mark").html("<div style='color:#999;text-align: center;'>未下载</div>");

                            //遍历网址
                            $(".gl1t").each(function(){
                                //遍历返回的对象
                                for(let i=0;i<back_obj.length;i++){
                                    if($(this).find("a").attr("href").indexOf(back_obj[i])!=-1){
                                        $(this).find(".mark").html("<div style='color:#1c1;text-align: center;'>已下载</div>");
                                        break;
                                    }
                                }
                                //当前页面只有一个搜素结果时自动提取meta
                                if($(".gl1t").length==1&& $(".mark").text()=="未下载"){
                                    $(".mark").focus();
                                    $(".mark").trigger("click");
                                }
                            });
                        },
                        error: function(xhr, status, error) {
                            // 请求失败时的回调函数
                            console.log("请求错误:", error);
                        }
                    });
                    
                }
            }


            console.log('事务已完成');

            // 关闭数据库连接
            db.close();
        };
    };

    //更新数据库
    function updateSqlite(url,appAppDatapath,port,metadatapath){
        //获取元数据
        let match = /(\d+)\/([a-z0-9]+)/.exec(url)
        fetch('https://api.e-hentai.org/api.php', {
            method: "POST",
            body: JSON.stringify({
                'method': 'gdata',
                'gidlist': [
                    [+match[1], match[2]]
                ],
                'namespace': 1
            })
        })
            .then(async res => {
            let metaobj = {}
            let gmetadata = await res.json()
            gmetadata = gmetadata.gmetadata[0]
            let tags = {}
            gmetadata.tags.forEach(tagString => {
                let match = /^(.+):(.+)$/.exec(tagString)
                if (tags[match[1]]) {
                    tags[match[1]].push(match[2])
                } else {
                    tags[match[1]] = [match[2]]
                }
            })
            metaobj.tags = tags
            metaobj.url = url
            metaobj.title = gmetadata.title
            metaobj.title_jpn = gmetadata.title_jpn
            metaobj.rating = +gmetadata.rating
            metaobj.posted = +gmetadata.posted
            metaobj.filecount = +gmetadata.filecount
            metaobj.category = gmetadata.category
            metaobj.filesize = gmetadata.filesize
            metaobj.status = 'tagged'
            var gid=gmetadata.gid
            //连接data.php
            //三次搜索,用gid搜索文件夹名,主要用于ehviewer下载的文件中所带的gid号,用日文搜索文件名,用英文搜索文件名
            $.ajax({
                url: "http://localhost:"+port+"/data.php",  // 请求的URL
                method: "POST",
                data:{
                    appAppDatapath:appAppDatapath,
                    metadatapath:metadatapath,
                    gid:gid,
                    metaobj:JSON.stringify(metaobj),
                    fun:'updateDatabase'
                },  // 请求参数,如果不需要传递参数可以省略
                success: function(response) {
                    //无搜索结果时使用手动输入
                    if(response.indexOf("notfind")!=-1){
                       //复制
                        navigator.clipboard.writeText(JSON.stringify(metaobj));
                        $(".copyed").text("录入失败,请手动录入元数据,元数据已复制到剪切版");
                    }
                    if(response.indexOf("success")!=-1){
                        $(".copyed").text("录入成功");
                    }
                    $('.copyed').fadeIn(); // 元素开始时显示
                    setTimeout(function() {
                        $('.copyed').fadeOut(); // 5秒后元素消失
                    }, 2000);
                },
                error: function(xhr, status, error) {
                    console.log("请求错误:", error);
                }
            });

        })



    }
    //设置端口和文件路径
    function setting(type){
        const request = indexedDB.open('ex1', 1);
        request.onupgradeneeded = function(event) {
            const db = event.target.result;
            //  检查对象存储空间是否存在
            if (!db.objectStoreNames.contains('setting')) {
                // 创建对象存储空间
                const objectStore = db.createObjectStore('setting', { keyPath: 'name' });
            }
        };
        request.onsuccess = function(event) {
            const db = event.target.result;

            // 开始事务(读写模式)
            const transaction = db.transaction(['setting'], 'readwrite');

            // 获取对象存储空间
            const store = transaction.objectStore('setting');
            if(type=='add'){
                var port = $(".showDialog .port").val();
                var appAppDatapath= $(".showDialog .databasepath").val();
                var metadatapath=$(".showDialog .metadatapath").val();
                const data_port = { name:'port', val: port };
                store.add(data_port);
                const data_appAppDatapath = { name:'appAppDatapath', val: appAppDatapath };
                store.add(data_appAppDatapath);
                const data_metadatapath = { name:'metadatapath', val: metadatapath };
                store.add(data_metadatapath);
            }else if(type=='del'){
                store.delete('port');
                store.delete('appAppDatapath');
                store.delete('metadatapath');
            }
            transaction.oncomplete = function() {
                // 关闭数据库连接

                db.close();
                location.reload();
            };

        }


    }

})();