Greasy Fork

pikpak番号重命名助手

自动从AVwiki网站获取信息并填充到mypikpak.com网站上的重命名对话框中,以帮助用户快速重命名文件。脚本在mypikpak.com的对话框触发时自动执行,从而提高用户在管理带番号的文件时的效率和准确性。

// ==UserScript==
// @name         pikpak番号重命名助手
// @name:zh-CN   pikpak番号重命名助手
// @namespace    Cheerchen37_NameScope
// @version      0.5
// @description  自动从AVwiki网站获取信息并填充到mypikpak.com网站上的重命名对话框中,以帮助用户快速重命名文件。脚本在mypikpak.com的对话框触发时自动执行,从而提高用户在管理带番号的文件时的效率和准确性。
// @author       [email protected]
// @match        *://*mypikpak.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_openInTab
// @license           MIT
// ==/UserScript==

(function() {
    'use strict';

    console.log("脚本已加载");

    // 1. 定位到元素的部分
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
                mutation.addedNodes.forEach(node => {
                    if (node.className === "el-dialog") {
                        handleDialog(node);
                    }
                });
            }
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    function handleDialog(node) {
        const input = node.querySelector('input.el-input__inner[type="text"]');
        if (!input) return;

        const cid = input.value;
        const keyword = extractKeyword(cid);
        if (!keyword) {
            console.log("未能提取有效关键字");
            return;
        }

        queryAVwiki(keyword, input);
    }

    // 2. 提取查询元素的部分
    function extractKeyword(text) {
        // 尝试匹配包含字母和数字的模式,忽略后面的字符
        let match = text.match(/([a-zA-Z]+)-(\d+)/);
        if (match) {
//             if (match[2].length == 4){
//                 return `${match[1]}0${match[2]}`;
//             }
//             return `${match[1]}00${match[2]}`;
            return match[0];
        }
        // 如果上面的特殊格式未匹配,尝试更通用的匹配
        match = text.match(/([a-zA-Z]+)0(\d+)/);
        if (match) {
            return match[0];
        }
        match = text.match(/([a-zA-Z]{3,})(\d+)/);

        return match ? `${match[1]}-${match[2]}` : null;
    }

    function extractKeywordDMM(text) {
        // 尝试匹配包含字母和数字的模式,忽略后面的字符
        let match = text.match(/([a-zA-Z]+)-(\d+)/);
        if (match) {
            if (match[2].length == 4){
                return `${match[1]}0${match[2]}`;
            }
            return `${match[1]}00${match[2]}`;
        }
        // 如果上面的特殊格式未匹配,尝试更通用的匹配
        match = text.match(/([a-zA-Z]+)0(\d+)/);
        if (match) {
            return match[0];
        }
        match = text.match(/([a-zA-Z]{3,})(\d+)/);

        return match ? match[0] : null;
    }

    // 4. 使用关键字查询DMM的部分
    function queryDMM(keyword, input) {
        console.log("keyword " + keyword);
        const encodedKeyword = encodeURIComponent(keyword);

        const url = `https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=${encodedKeyword}/?i3_ref=search&i3_ord=1`;
        console.log("url " + url);
        GM_xmlhttpRequest({
            method: "GET",
            url: url,
            onload: function(response) {
                if (response.responseText.includes('404 Not Found')) {
                    fallbackSearch(encodedKeyword, input);
                } else {
                    parseResponseDMM(response.responseText, input);
                }
            },
            onerror: function(error) {
                console.log("请求出错: ", error);
            }
        });
    }

    // 4. 使用关键字查询DMM的部分
    function queryAVwiki(keyword, input) {
        console.log("keyword " + keyword);
        const encodedKeyword = encodeURIComponent(keyword);

        const url = `https://av-wiki.net/?s=${encodedKeyword}&post_type=product`;
        console.log("url " + url);
        GM_xmlhttpRequest({
            method: "GET",
            url: url,
            onload: function(response) {
                const parser = new DOMParser();
                const doc = parser.parseFromString(response.responseText, "text/html");
                const listItems = doc.querySelectorAll('.post .archive-list .read-more a');
                const keywordRegex = new RegExp(keyword.match(/[a-zA-Z]+/)[0], 'i');
                // 查找第一个有效链接
                for (let item of listItems) {
                    if (item.href) {
                        if (!keywordRegex.test(item.href)){
                            continue;
                        }
                        const detailUrl = item.href;
                        console.log("detailUrl "+ detailUrl)
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: detailUrl,
                            onload: function(response) {
                                parseResponseWiki(response.responseText, input);
                            }
                        });
                        return; // 找到有效链接后结束循环
                    }
                }
                // 如果没有找到有效链接,设置输入框显示未找到
                input.value = '未找到有效链接';
            },
            onerror: function(error) {
                console.log("请求出错: ", error);
                input.value = "请求错误,请检查网络";
            }
        });
    }

    // Fallback search on failure
    function fallbackSearch(keyword, input) {
        const searchUrl = `https://www.dmm.co.jp/search/=/searchstr=${encodeURIComponent(keyword)}/limit=30/sort=rankprofile/`;
        console.log("fallbackSearch "+ searchUrl)
        GM_xmlhttpRequest({
            method: "GET",
            url: searchUrl,
            onload: function(response) {
                const parser = new DOMParser();
                const doc = parser.parseFromString(response.responseText, "text/html");
                const listItems = doc.querySelectorAll('#list li .tmb a');

                // 提取输入中的连续字母部分
                const keywordRegex = new RegExp(keyword.match(/[a-zA-Z]+/)[0], 'i');
                const digiRegex = new RegExp("digital", 'i');
                const monoRegex = new RegExp("mono", 'i');

                // 查找第一个有效链接
                for (let item of listItems) {
                    if (item.href) {
                        if (!keywordRegex.test(item.href)){
                            continue;
                        }
                        if (!digiRegex.test(item.href) && !monoRegex.test(item.href)){
                            continue;
                        }
                        const detailUrl = item.href;
                        console.log("detailUrl "+ detailUrl)
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: detailUrl,
                            onload: function(response) {
                                parseResponseDMM(response.responseText, input);
                            }
                        });
                        return; // 找到有效链接后结束循环
                    }
                }
                // 如果没有找到有效链接,设置输入框显示未找到
                input.value = '未找到有效链接';
            },
            onerror: function(error) {
                console.log("请求出错: ", error);
                input.value = "请求错误,请检查网络";
            }
        });
    }

    // Parse response and update input
    function parseResponseDMM(html, input) {
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, "text/html");
        // 尝试从meta标签中提取备选信息
        const ogTitle = doc.querySelector('#title');
        const ogUrl = doc.querySelector('meta[property="og:url"]');
        let name = ogTitle ? ogTitle.textContent : '未找到产品名称';
        let sku = '未找到产品SKU';

        if (ogUrl && ogUrl.content) {
            const match = ogUrl.content.match(/cid=([^\/]+)/);
            if (match) {
                sku = match[1].toLowerCase();
            }
        }

        const script = doc.querySelector('script[type="application/ld+json"]');

        if (script) {
            try {
                const data = JSON.parse(script.textContent);
                name = data.name || name;
                sku = data.sku.toLowerCase() || sku;

            } catch (error) {
                console.error("解析JSON-LD数据时出错: ", error);
            }
        }
        // 清理名称中的特殊字符
        name = name.replace(/[\/:*?"<>|\x00-\x1F]/g, '_');
        input.value = `${sku} ${name} `;
        triggerInputChange(input)
    }

    function parseResponseWiki(html, input) {
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, "text/html");
        // 尝试从meta标签中提取备选信息
        const ogTitle = doc.querySelector('.blockquote-like p');

        let name = ogTitle ? ogTitle.textContent : '未找到产品名称';

        // 清理名称中的特殊字符
        name = name.replace(/[\/:*?"<>|\x00-\x1F]/g, '_');
        input.value = `${name} `;
        triggerInputChange(input)
    }

    function triggerInputChange(element) {
        // 创建一个新的键盘事件
        var event = new Event('input', {
            bubbles: true,
            cancelable: true,
        });

        element.value = element.value.trim(); // 移除空格
        element.dispatchEvent(event); // 再次触发input事件
    }
})();