deai prompt generator

with.isとpairs.lvとmarrish.comのユーザーページにコピーボタンを追加し、AI対話プロンプトを生成します。marrish.comのチャットページでメッセージをコピーできます。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         deai prompt generator
// @namespace    http://tampermonkey.net/
// @version      1.0.8
// @description  with.isとpairs.lvとmarrish.comのユーザーページにコピーボタンを追加し、AI対話プロンプトを生成します。marrish.comのチャットページでメッセージをコピーできます。
// @author       Your Name
// @match        https://with.is/users/*
// @match        https://pairs.lv/*
// @match        https://marrish.com/profile/detail/partner/*
// @match        https://marrish.com/message/index/*
// @grant        GM_setClipboard
// @license      MIT
// @supportURL   https://github.com/thelastfantasy/with-profile-copy/issues
// ==/UserScript==

"use strict";
(function () {
    "use strict";
    let lastUrl = window.location.href;
    let pairsObserver = null;
    let isAddingPairsButton = false;
    const CONFIG = {
        MESSAGE_DISPLAY_TIME: 3000,
        PAIRS_MODAL_TIMEOUT: 10000,
    };
    const COMMON_FOOTER = "以上情報常に忘れず、相手と会話で送るメッセージを提案してみてください。提案するメッセージには非常用の絵文字を使わず、あまり堅苦しくなく、失礼にならない程度のカジュアルな表現でお願いします。\n生成されたメッセージ内容はなるべくAIぽくない、相手のメッセージ内容を重複しない、自然な日本語で、emojiはよく使うやつに限定、「」などの記号を控えるようにお願いします。";
    const TEMPLATES = {
        WITH_IS: {
            header: "with.isで以下ユーザーとマッチしました。相手の情報は以下になります",
            nickname: "ユーザー名",
            age: "年齢",
            location: "居住地",
            introduction: "自己紹介文",
            additional: "俺との共通点",
            basicInfo: "相手の基本情報",
            footer: COMMON_FOOTER,
        },
        PAIRS: {
            header: "pairs.lvで以下ユーザーとマッチしました。相手の情報は以下になります",
            nickname: "ユーザー名",
            age: "年齢",
            location: "居住地",
            introduction: "自己紹介",
            additional: "マイタグ",
            pairsQuestions: "ペアーズクエスチョン",
            basicInfo: "相手の基本情報",
            footer: COMMON_FOOTER,
        },
        MARRISH: {
            header: "marrish.comで以下ユーザーとマッチしました。相手の情報は以下になります",
            nickname: "ユーザー名",
            age: "年齢",
            location: "居住地",
            introduction: "自己PR",
            additional: "参加グループ",
            basicInfo: "相手の基本情報",
            footer: COMMON_FOOTER,
        },
    };
    const CSS_SELECTORS = {
        WITH_IS: {
            NICKNAME: ".profile_main-nickname",
            AGE_ADDRESS: ".profile_main-age-address",
            INTRODUCTION: ".profile-introduction",
            COMMON_POINTS: ".profile-affinities_list.on-user-detail li",
            BASIC_INFO_TABLE: ".profile-detail table",
            BASIC_INFO_ROW: "tr",
            BASIC_INFO_HEADER: "th",
            BASIC_INFO_DATA: "td",
        },
        PAIRS: {
            ROOT: "#dialog-root",
            BUTTON_INSERT: "#dialog-root > div > div > div > div:nth-child(2) > div > div > div:nth-child(3) > div:nth-child(1) > div > div:nth-child(1) > div:nth-child(3) > p",
        },
        MARRISH: {
            BASE_INFO: ".as-profile__baseinfo-pc",
            NAME: ".as-profile__name",
            AGE: ".as-profile__age",
            AREA: ".as-profile__area",
            GROUP_LIST: ".as-prof-group-list",
            GROUP_ITEMS: ".as-prof-group-list__item",
            GROUP_TITLE: ".as-prof-group-list__title",
            GROUP_MEMBER: ".as-prof-group-list__member",
            SELF_PR: ".as-profile-text-contents",
            DETAIL_WRAP: ".as-profile-detail-wrap",
            DETAIL_GROUP: ".as-profile-detail-item-group",
            DETAIL_SUB_TITLE: ".as-profile-detail-sub-title",
            DETAIL_ITEM: ".as-profile-detail-item",
            DETAIL_ITEM_TITLE: ".as-profile-detail-item-title",
            DETAIL_ITEM_DATE: ".as-profile-detail-item-date",
            MOBILE_ONLINE_INFO: ".as-prof-info__online",
            MOBILE_LIKE_COUNT: ".as-prof-like-count",
            MOBILE_BASE_INFO: ".as-prof-info__base",
            MOBILE_NAME: ".as-prof-info__name",
            MOBILE_AGE: ".as-prof-info__age",
            MOBILE_AREA: ".as-prof-info__area",
            MESSAGE_BUBBLE: ".yi-message-form-text-body-bg1, .yi-message-form-text-body-bg1-me",
            MESSAGE_CONTENT: "p",
            SPEAKER_NAME: ".yi-message-form-phone_head_name_textover",
        },
    };
    if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", init);
    }
    else {
        init();
    }
    window.addEventListener("hashchange", handleRouteChange);
    window.addEventListener("popstate", handleRouteChange);
    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;
    history.pushState = function (...args) {
        originalPushState.apply(this, args);
        handleRouteChange();
    };
    history.replaceState = function (...args) {
        originalReplaceState.apply(this, args);
        handleRouteChange();
    };
    function isPairsUserPage(url = window.location.href) {
        return url.includes("pairs.lv/message/detail/");
    }
    function handleRouteChange() {
        const currentUrl = window.location.href;
        if (currentUrl !== lastUrl) {
            lastUrl = currentUrl;
            console.log("URL changed, checking for all supported pages...");
            if (currentUrl.includes("with.is/users/")) {
                addCopyButton("WITH_IS");
            }
            else if (isPairsUserPage(currentUrl)) {
                if (pairsObserver) {
                    pairsObserver.disconnect();
                    pairsObserver = null;
                }
                waitForPairsModal();
            }
            else if (currentUrl.includes("marrish.com/profile/detail/partner/")) {
                waitForMarrishBaseInfo();
            }
            else if (currentUrl.includes("marrish.com/message/index/")) {
                waitForMarrishMessages();
            }
        }
    }
    function init() {
        console.log("脚本初始化,当前URL:", window.location.href);
        console.log("isPairsUserPage() 结果:", isPairsUserPage());
        if (window.location.href.includes("with.is/users/")) {
            console.log("检测到with.is页面");
            addCopyButton("WITH_IS");
        }
        else if (isPairsUserPage()) {
            console.log("检测到pairs.lv页面,执行pairs.lv逻辑");
            waitForPairsModal();
        }
        else if (window.location.href.includes("marrish.com/profile/detail/partner/")) {
            console.log("检测到marrish.com页面,执行marrish.com逻辑");
            waitForMarrishBaseInfo();
        }
        else if (window.location.href.includes("marrish.com/message/index/")) {
            console.log("检测到marrish.com聊天页面,执行聊天逻辑");
            waitForMarrishMessages();
        }
        else {
            console.log("未匹配到支持的页面类型");
            return;
        }
    }
    function waitForPairsModal() {
        console.log("等待pairs.lv模态框加载...");
        if (tryAddPairsButton()) {
            return;
        }
        if (pairsObserver) {
            pairsObserver.disconnect();
            pairsObserver = null;
        }
        pairsObserver = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                if (mutation.type === "childList") {
                    const dialogRoot = document.querySelector(CSS_SELECTORS.PAIRS.ROOT);
                    if (dialogRoot && tryAddPairsButton()) {
                        console.log("pairs.lv模态框已加载,按钮已添加");
                        if (pairsObserver) {
                            pairsObserver.disconnect();
                            pairsObserver = null;
                        }
                        return;
                    }
                }
            }
        });
        pairsObserver.observe(document.body, {
            childList: true,
            subtree: true,
        });
        setTimeout(() => {
            if (pairsObserver) {
                pairsObserver.disconnect();
                pairsObserver = null;
                console.log("pairs.lv模态框加载超时");
            }
        }, CONFIG.PAIRS_MODAL_TIMEOUT);
    }
    function tryAddPairsButton() {
        if (isAddingPairsButton) {
            return false;
        }
        isAddingPairsButton = true;
        try {
            const buttonContainer = document.querySelector(CSS_SELECTORS.PAIRS.BUTTON_INSERT);
            if (buttonContainer) {
                const existingButton = buttonContainer.parentNode?.querySelector('button[style*="background: #007bff"]');
                if (!existingButton) {
                    addCopyButton("PAIRS");
                    return true;
                }
                else {
                    console.log("按钮已存在,跳过重复添加");
                    return true;
                }
            }
            return false;
        }
        finally {
            isAddingPairsButton = false;
        }
    }
    function waitForMarrishBaseInfo() {
        console.log("等待marrish.com基本信息区域加载...");
        if (tryAddMarrishButton()) {
            return;
        }
        const observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                if (mutation.type === "childList") {
                    if (tryAddMarrishButton()) {
                        observer.disconnect();
                        console.log("marrish.com基本信息区域已加载,按钮已添加");
                        return;
                    }
                }
            }
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true,
        });
        setTimeout(() => {
            observer.disconnect();
            console.log("marrish.com基本信息区域加载超时");
        }, CONFIG.PAIRS_MODAL_TIMEOUT);
    }
    function tryAddMarrishButton() {
        const pcButtonContainer = document.querySelector(CSS_SELECTORS.MARRISH.AREA);
        if (pcButtonContainer) {
            console.log("检测到PC版marrish.com,在居住地后面添加按钮");
            addCopyButton("MARRISH");
            return true;
        }
        const mobileLikeCount = document.querySelector(CSS_SELECTORS.MARRISH.MOBILE_LIKE_COUNT);
        if (mobileLikeCount) {
            console.log("检测到手机版marrish.com,在点赞数元素后面添加按钮");
            addCopyButton("MARRISH");
            return true;
        }
        return false;
    }
    function waitForMarrishMessages() {
        console.log("等待marrish.com聊天消息加载...");
        if (tryAddMessageButtons()) {
            addCopyAllChatButton();
            return;
        }
        const observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                if (mutation.type === "childList") {
                    if (tryAddMessageButtons()) {
                        console.log("marrish.com聊天消息已加载,按钮已添加");
                        addCopyAllChatButton();
                    }
                }
            }
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true,
        });
    }
    function tryAddMessageButtons() {
        const messageBubbles = document.querySelectorAll(CSS_SELECTORS.MARRISH.MESSAGE_BUBBLE);
        let addedButtons = false;
        messageBubbles.forEach((bubble) => {
            if (!bubble.querySelector(".message-copy-button")) {
                addMessageCopyButton(bubble);
                addedButtons = true;
            }
        });
        return addedButtons;
    }
    function addMessageCopyButton(bubble) {
        const copyButton = document.createElement("button");
        copyButton.textContent = "📋";
        copyButton.className = "message-copy-button";
        copyButton.style.cssText = `
            position: absolute;
            top: 5px;
            left: 5px;
            padding: 2px 6px;
            background: rgba(0, 123, 255, 0.8);
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
            font-size: 10px;
            z-index: 10;
            opacity: 0.7;
            transition: opacity 0.2s;
        `;
        copyButton.addEventListener("mouseenter", () => {
            copyButton.style.opacity = "1";
        });
        copyButton.addEventListener("mouseleave", () => {
            copyButton.style.opacity = "0.7";
        });
        copyButton.addEventListener("click", (e) => {
            e.stopPropagation();
            copyMessageContent(bubble);
        });
        if (getComputedStyle(bubble).position === "static") {
            bubble.style.position = "relative";
        }
        bubble.appendChild(copyButton);
    }
    function copyMessageContent(bubble) {
        try {
            const messageContent = bubble.querySelector(CSS_SELECTORS.MARRISH.MESSAGE_CONTENT);
            if (messageContent) {
                const htmlContent = messageContent.innerHTML;
                const textContent = htmlContent
                    .replace(/<br\s*\/?>/gi, "\n")
                    .replace(/<[^>]*>/g, "")
                    .replace(/\n{3,}/g, "\n\n")
                    .trim();
                const speakerNameElement = document.querySelector(CSS_SELECTORS.MARRISH.SPEAKER_NAME);
                let speakerName = "見つかりません";
                if (speakerNameElement) {
                    speakerName =
                        speakerNameElement.textContent?.trim() || "見つかりません";
                }
                const isMyMessage = bubble.classList.contains("yi-message-form-text-body-bg1-me");
                const speakerPrefix = isMyMessage ? "俺" : speakerName;
                const formattedContent = `${speakerPrefix}:\n${textContent}`;
                GM_setClipboard(formattedContent, "text");
                showMessage("✅ メッセージをコピーしました!", "success");
            }
            else {
                showMessage("❌ メッセージ内容が見つかりません", "error");
            }
        }
        catch (error) {
            console.error("メッセージコピーに失敗しました:", error);
            showMessage("❌ コピーに失敗しました", "error");
        }
    }
    function addCopyAllChatButton() {
        const readUnreadButton = document.getElementById("read_unread_func_off");
        if (!readUnreadButton) {
            console.log("既読機能OFF按钮が見つかりません");
            return;
        }
        if (readUnreadButton.parentNode?.querySelector(".copy-all-chat-button")) {
            return;
        }
        const copyAllButton = document.createElement("button");
        copyAllButton.textContent = "📋 チャット履歴をコピー";
        copyAllButton.className = "copy-all-chat-button";
        copyAllButton.style.cssText = `
            margin-right: 10px;
            padding: 6px 12px;
            background: #28a745;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
        `;
        copyAllButton.addEventListener("click", copyAllChatHistory);
        readUnreadButton.parentNode?.insertBefore(copyAllButton, readUnreadButton);
    }
    function copyAllChatHistory() {
        try {
            const messageBubbles = document.querySelectorAll(CSS_SELECTORS.MARRISH.MESSAGE_BUBBLE);
            if (messageBubbles.length === 0) {
                showMessage("❌ チャット履歴が見つかりません", "error");
                return;
            }
            const speakerNameElement = document.querySelector(CSS_SELECTORS.MARRISH.SPEAKER_NAME);
            const speakerName = speakerNameElement?.textContent?.trim() || "相手";
            const messages = [];
            messages.push("チャット履歴");
            messageBubbles.forEach((bubble) => {
                const messageContent = bubble.querySelector(CSS_SELECTORS.MARRISH.MESSAGE_CONTENT);
                if (messageContent) {
                    const htmlContent = messageContent.innerHTML;
                    const textContent = htmlContent
                        .replace(/<br\s*\/?>/gi, "\n")
                        .replace(/<[^>]*>/g, "")
                        .replace(/\n{3,}/g, "\n\n")
                        .trim();
                    const isMyMessage = bubble.classList.contains("yi-message-form-text-body-bg1-me");
                    const speakerPrefix = isMyMessage ? "俺" : speakerName;
                    messages.push(`${speakerPrefix}:`);
                    messages.push(textContent);
                    messages.push("");
                }
            });
            const fullChatHistory = messages.join("\n").trim();
            GM_setClipboard(fullChatHistory, "text");
            showMessage("✅ チャット履歴をコピーしました!", "success");
        }
        catch (error) {
            console.error("チャット履歴コピーに失敗しました:", error);
            showMessage("❌ チャット履歴のコピーに失敗しました", "error");
        }
    }
    function addCopyButton(site) {
        let buttonContainer = null;
        let buttonText = "📋 ユーザー情報をコピー";
        if (site === "WITH_IS") {
            buttonContainer = document.querySelector(CSS_SELECTORS.WITH_IS.NICKNAME);
        }
        else if (site === "PAIRS") {
            buttonContainer = document.querySelector(CSS_SELECTORS.PAIRS.BUTTON_INSERT);
            buttonText = "📋 プロフィールをコピー";
        }
        else if (site === "MARRISH") {
            buttonContainer = document.querySelector(CSS_SELECTORS.MARRISH.AREA);
            if (!buttonContainer) {
                buttonContainer = document.querySelector(CSS_SELECTORS.MARRISH.MOBILE_LIKE_COUNT);
            }
            buttonText = "📋 プロフィールをコピー";
        }
        if (!buttonContainer) {
            console.log("ボタン追加位置が見つかりません:", site, "selector:", site === "WITH_IS"
                ? CSS_SELECTORS.WITH_IS.NICKNAME
                : site === "PAIRS"
                    ? CSS_SELECTORS.PAIRS.BUTTON_INSERT
                    : CSS_SELECTORS.MARRISH.AREA);
            return;
        }
        createCopyButton(buttonContainer, buttonText);
    }
    function createCopyButton(container, buttonText) {
        const copyButton = document.createElement("button");
        copyButton.textContent = buttonText;
        copyButton.style.cssText = `
            margin-left: 10px;
            padding: 4px 8px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
        `;
        copyButton.addEventListener("click", handleCopy);
        container.parentNode?.insertBefore(copyButton, container.nextSibling);
    }
    function handleCopy() {
        try {
            const userData = extractUserData();
            const promptText = generatePrompt(userData);
            GM_setClipboard(promptText, "text");
            showMessage("✅ ユーザー情報をクリップボードにコピーしました!", "success");
        }
        catch (error) {
            console.error("コピーに失敗しました:", error);
            showMessage("❌ コピーに失敗しました。コンソールを確認してください", "error");
        }
    }
    function extractUserData() {
        let selectors;
        let site = "WITH_IS";
        if (window.location.href.includes("with.is/users/")) {
            selectors = CSS_SELECTORS.WITH_IS;
            site = "WITH_IS";
        }
        else if (isPairsUserPage()) {
            selectors = CSS_SELECTORS.PAIRS;
            site = "PAIRS";
        }
        else if (window.location.href.includes("marrish.com/profile/detail/partner/")) {
            selectors = CSS_SELECTORS.MARRISH;
            site = "MARRISH";
            const mobileBaseInfo = document.querySelector(CSS_SELECTORS.MARRISH.MOBILE_BASE_INFO);
            if (mobileBaseInfo) {
                console.log("检测到移动版marrish.com,使用移动版数据提取");
                return extractMarrishMobileData(selectors);
            }
            else {
                console.log("检测到PC版marrish.com,使用PC版数据提取");
                return extractMarrishData(selectors);
            }
        }
        else {
            throw new Error("サポートされていないサイトです");
        }
        if (site === "WITH_IS") {
            return extractWithIsData(selectors);
        }
        else if (site === "PAIRS") {
            return extractPairsData(selectors);
        }
        else {
            return extractMarrishData(selectors);
        }
    }
    function extractWithIsData(selectors) {
        const nickname = document.querySelector(selectors.NICKNAME)?.textContent?.trim() ||
            "見つかりません";
        const ageAddressElement = document.querySelector(selectors.AGE_ADDRESS);
        let age = "見つかりません";
        let location = "見つかりません";
        if (ageAddressElement) {
            const text = ageAddressElement.textContent?.trim() || "";
            const parts = text.split("\n").filter((part) => part.trim());
            if (parts.length >= 1)
                age = parts[0].trim();
            if (parts.length >= 2)
                location = parts[1].trim();
        }
        let introduction = document.querySelector(selectors.INTRODUCTION)?.textContent?.trim() ||
            "見つかりません";
        if (introduction.startsWith("自己紹介文")) {
            introduction = introduction.replace(/^自己紹介文\s*/, "");
        }
        const commonPoints = [];
        const commonPointElements = document.querySelectorAll(selectors.COMMON_POINTS);
        commonPointElements.forEach((el) => {
            const text = el.textContent?.trim();
            if (text)
                commonPoints.push(text);
        });
        const basicInfo = {};
        const basicInfoTable = document.querySelector(selectors.BASIC_INFO_TABLE);
        if (basicInfoTable) {
            const rows = basicInfoTable.querySelectorAll(selectors.BASIC_INFO_ROW);
            rows.forEach((row) => {
                const th = row
                    .querySelector(selectors.BASIC_INFO_HEADER)
                    ?.textContent?.trim();
                const td = row
                    .querySelector(selectors.BASIC_INFO_DATA)
                    ?.textContent?.trim();
                if (th && td) {
                    basicInfo[th] = td;
                }
            });
        }
        return {
            nickname,
            age,
            location,
            introduction,
            commonPoints,
            basicInfo,
            site: "WITH_IS",
        };
    }
    function extractBasicInfoFromProfile(dialogRoot) {
        const basicInfo = {};
        const profileH2 = Array.from(dialogRoot.querySelectorAll("h2")).find((h2) => h2.textContent?.includes("プロフィール"));
        if (profileH2) {
            let profileContainer = profileH2.parentElement;
            if (profileContainer) {
                const allDlElements = profileContainer.querySelectorAll("dl");
                if (allDlElements.length > 0) {
                    allDlElements.forEach((dl) => {
                        const dtElements = dl.querySelectorAll("dt");
                        const ddElements = dl.querySelectorAll("dd");
                        dtElements.forEach((dt, index) => {
                            const key = dt.textContent?.trim();
                            const value = ddElements[index]?.textContent?.trim();
                            if (key && value) {
                                basicInfo[key] = value;
                            }
                        });
                    });
                }
            }
        }
        return basicInfo;
    }
    function extractPairsData(selectors) {
        const dialogRoot = document.querySelector(selectors.ROOT);
        if (!dialogRoot) {
            console.log("未找到#dialog-root容器");
            return {
                nickname: "見つかりません",
                age: "見つかりません",
                location: "見つかりません",
                introduction: "見つかりません",
                myTags: [],
                pairsQuestions: [],
                basicInfo: {},
                site: "PAIRS",
            };
        }
        let nickname = "見つかりません";
        const nameElements = dialogRoot.querySelectorAll("p, span, h1, h2, h3, div");
        for (const element of nameElements) {
            const text = element.textContent?.trim();
            if (text &&
                text.length > 0 &&
                text.length < 30 &&
                !text.includes("歳") &&
                !text.includes("自己紹介") &&
                !text.includes("マイタグ") &&
                !text.includes("プロフィール") &&
                !text.includes("新着のお相手") &&
                !text.includes("お相手詳細") &&
                !text.includes("本人確認済み") &&
                !text.includes("プロフィールをコピー") &&
                !text.includes("前の写真") &&
                !text.includes("次の写真") &&
                !text.includes("いいね!")) {
                nickname = text;
                break;
            }
        }
        if (nickname === "見つかりません") {
            const marinaElements = dialogRoot.querySelectorAll("*");
            for (const element of marinaElements) {
                const text = element.textContent?.trim();
                if (text && text.includes("marina")) {
                    nickname = "marina";
                    break;
                }
            }
        }
        if (nickname === "見つかりません") {
            const profileBasicInfo = extractBasicInfoFromProfile(dialogRoot);
            if (profileBasicInfo["ニックネーム"]) {
                nickname = profileBasicInfo["ニックネーム"];
            }
        }
        let age = "見つかりません";
        let location = "見つかりません";
        const profileBasicInfo = extractBasicInfoFromProfile(dialogRoot);
        if (profileBasicInfo["年齢"])
            age = profileBasicInfo["年齢"];
        if (profileBasicInfo["居住地"])
            location = profileBasicInfo["居住地"];
        if (age === "見つかりません" || location === "見つかりません") {
            const allElements = dialogRoot.querySelectorAll("*");
            for (const element of allElements) {
                const text = element.textContent?.trim();
                if (text && text.includes("歳")) {
                    const cleanText = text
                        .replace(/[\n\r]/g, " ")
                        .replace(/\s+/g, " ")
                        .trim();
                    const parts = cleanText
                        .split(" ")
                        .filter((part) => part.trim());
                    const agePart = parts.find((part) => part.includes("歳"));
                    if (agePart) {
                        age = agePart.trim();
                        const ageIndex = parts.indexOf(agePart);
                        if (ageIndex >= 0 && ageIndex + 1 < parts.length) {
                            location = parts[ageIndex + 1].trim();
                        }
                        break;
                    }
                }
            }
        }
        if (age === "見つかりません") {
            const verifiedElements = dialogRoot.querySelectorAll("*");
            for (const element of verifiedElements) {
                const text = element.textContent?.trim();
                if (text && text.includes("本人確認済み")) {
                    const parentText = element.parentElement?.textContent?.trim();
                    if (parentText && parentText.includes("歳")) {
                        const cleanText = parentText
                            .replace(/[\n\r]/g, " ")
                            .replace(/\s+/g, " ")
                            .trim();
                        const parts = cleanText
                            .split(" ")
                            .filter((part) => part.trim());
                        const agePart = parts.find((part) => part.includes("歳"));
                        if (agePart) {
                            age = agePart.trim();
                            break;
                        }
                    }
                }
            }
        }
        let introduction = "見つかりません";
        const introH2 = Array.from(dialogRoot.querySelectorAll("h2")).find((h2) => h2.textContent?.includes("自己紹介"));
        console.log("自己紹介h2找到:", !!introH2);
        if (introH2) {
            let currentElement = introH2.nextElementSibling;
            while (currentElement) {
                const introP = currentElement.querySelector("p");
                if (introP && introP.textContent?.trim()) {
                    introduction = introP.textContent.trim();
                    console.log("找到自己紹介内容");
                    break;
                }
                const elementText = currentElement.textContent?.trim();
                if (elementText &&
                    elementText.length > 50 &&
                    !elementText.includes("プロフィール")) {
                    introduction = elementText;
                    console.log("通过文本找到自己紹介内容");
                    break;
                }
                currentElement = currentElement.nextElementSibling;
            }
        }
        if (introduction === "見つかりません") {
            const allElements = dialogRoot.querySelectorAll("p, div");
            for (const element of allElements) {
                const text = element.textContent?.trim();
                if (text &&
                    text.length > 100 &&
                    (text.includes("初めまして") ||
                        text.includes("よろしくお願いします") ||
                        text.includes("プロフィールを見ていただき"))) {
                    const cleanText = text
                        .replace(/お相手詳細を閉じるメニュー前の写真次の写真新着のお相手.*?プロフィールをコピー/g, "")
                        .replace(/30歳 大阪.*?本人確認済み/g, "")
                        .replace(/ペアーズクエスチョン.*?マイタグ/g, "")
                        .replace(/自己紹介/g, "")
                        .replace(/プロフィール.*/g, "")
                        .replace(/真面目に真剣に出会いを探してます.*?趣味全般/g, "")
                        .replace(/恋愛・結婚/g, "")
                        .replace(/Netflix観てます/g, "")
                        .replace(/自然のあるところが好き/g, "")
                        .replace(/旅行/g, "")
                        .replace(/Pickup/g, "")
                        .replace(/一緒に夜カフェでまったりしよう/g, "")
                        .replace(/\s+/g, " ")
                        .trim();
                    if (cleanText.length > 50) {
                        introduction = cleanText;
                        console.log("通过关键词找到自己紹介内容");
                        break;
                    }
                }
            }
        }
        const myTags = [];
        const tagsH2 = Array.from(dialogRoot.querySelectorAll("h2")).find((h2) => h2.textContent?.includes("マイタグ"));
        if (tagsH2?.nextElementSibling) {
            const tagLinks = tagsH2.nextElementSibling.querySelectorAll("ul > li > a");
            tagLinks.forEach((a) => {
                const title = a.getAttribute("title");
                if (title)
                    myTags.push(title);
            });
        }
        const pairsQuestions = [];
        const questionsH2 = Array.from(dialogRoot.querySelectorAll("h2")).find((h2) => h2.textContent?.includes("ペアーズクエスチョン"));
        console.log("ペアーズクエスチョンh2找到:", !!questionsH2);
        if (questionsH2) {
            let questionsContainer = questionsH2.nextElementSibling;
            while (questionsContainer) {
                const questionElements = questionsContainer.querySelectorAll("div, p, span");
                console.log("找到的问题元素数量:", questionElements.length);
                for (let i = 0; i < questionElements.length; i++) {
                    const element = questionElements[i];
                    const text = element.textContent?.trim();
                    if (text &&
                        (text.includes("毎日しちゃうルーティンは?") ||
                            text.includes("居心地のいい場所は?") ||
                            text.includes("最高に幸せ!") ||
                            text.includes("デートプランどうやって決める?") ||
                            text.includes("急に1日だけ休みをもらえたら何する?"))) {
                        const question = text;
                        if (i + 1 < questionElements.length) {
                            const answerElement = questionElements[i + 1];
                            const answer = answerElement.textContent?.trim();
                            if (answer && !answer.includes("?") && !answer.includes("!")) {
                                pairsQuestions.push({ question, answer });
                                console.log("找到ペアーズクエスチョン:", question, "=>", answer);
                            }
                        }
                    }
                }
                if (pairsQuestions.length > 0) {
                    console.log("找到ペアーズクエスチョン数量:", pairsQuestions.length);
                    break;
                }
                questionsContainer = questionsContainer.nextElementSibling;
            }
        }
        const basicInfo = extractBasicInfoFromProfile(dialogRoot);
        console.log("提取的基本信息数量:", Object.keys(basicInfo).length);
        console.log("提取的键:", Object.keys(basicInfo));
        return {
            nickname,
            age,
            location,
            introduction,
            myTags,
            pairsQuestions,
            basicInfo,
            site: "PAIRS",
        };
    }
    function extractMarrishData(selectors) {
        const name = document.querySelector(selectors.NAME)?.textContent?.trim() ||
            "見つかりません";
        const age = document.querySelector(selectors.AGE)?.textContent?.trim() ||
            "見つかりません";
        const location = document.querySelector(selectors.AREA)?.textContent?.trim() ||
            "見つかりません";
        const groups = [];
        const groupElements = document.querySelectorAll(selectors.GROUP_ITEMS);
        groupElements.forEach((el) => {
            const title = el
                .querySelector(selectors.GROUP_TITLE)
                ?.textContent?.trim();
            const member = el
                .querySelector(selectors.GROUP_MEMBER)
                ?.textContent?.trim();
            if (title) {
                groups.push({
                    title,
                    member: member || "不明",
                });
            }
        });
        const selfPrElement = document.querySelector(selectors.SELF_PR);
        let selfPr = "見つかりません";
        if (selfPrElement) {
            const htmlContent = selfPrElement.innerHTML;
            selfPr = htmlContent
                .replace(/<br\s*\/?>/gi, "\n")
                .replace(/<[^>]*>/g, "")
                .replace(/\n{3,}/g, "\n\n")
                .trim();
        }
        const basicInfo = {};
        const detailGroups = document.querySelectorAll(selectors.DETAIL_GROUP);
        detailGroups.forEach((group) => {
            const subTitle = group
                .querySelector(selectors.DETAIL_SUB_TITLE)
                ?.textContent?.trim();
            const detailItems = group.querySelectorAll(selectors.DETAIL_ITEM);
            detailItems.forEach((item) => {
                const title = item
                    .querySelector(selectors.DETAIL_ITEM_TITLE)
                    ?.textContent?.trim();
                const dateElement = item.querySelector(selectors.DETAIL_ITEM_DATE);
                if (title && dateElement) {
                    let date = title === "活動エリア"
                        ? dateElement.innerHTML
                            .replace(/<br\s*\/?>/gi, ",")
                            .replace(/<[^>]*>/g, "")
                            .trim()
                            .replace(/,\s*,/g, ",")
                            .replace(/,$/, "")
                        : dateElement.textContent?.trim();
                    if (title && date) {
                        const key = title;
                        basicInfo[key] = {
                            value: date,
                            group: subTitle || "その他",
                        };
                    }
                }
            });
        });
        return {
            nickname: name,
            age,
            location,
            groups,
            selfPr,
            basicInfo,
            site: "MARRISH",
        };
    }
    function extractMarrishMobileData(selectors) {
        const name = document.querySelector(selectors.MOBILE_NAME)?.textContent?.trim() ||
            "見つかりません";
        const age = document.querySelector(selectors.MOBILE_AGE)?.textContent?.trim() ||
            "見つかりません";
        const location = document.querySelector(selectors.MOBILE_AREA)?.textContent?.trim() ||
            "見つかりません";
        const groups = [];
        const groupElements = document.querySelectorAll(selectors.GROUP_ITEMS);
        groupElements.forEach((el) => {
            const title = el
                .querySelector(selectors.GROUP_TITLE)
                ?.textContent?.trim();
            const member = el
                .querySelector(selectors.GROUP_MEMBER)
                ?.textContent?.trim();
            if (title) {
                groups.push({
                    title,
                    member: member || "不明",
                });
            }
        });
        const selfPrElement = document.querySelector(selectors.SELF_PR);
        let selfPr = "見つかりません";
        if (selfPrElement) {
            const htmlContent = selfPrElement.innerHTML;
            selfPr = htmlContent
                .replace(/<br\s*\/?>/gi, "\n")
                .replace(/<[^>]*>/g, "")
                .replace(/\n{3,}/g, "\n\n")
                .trim();
        }
        const basicInfo = {};
        const detailGroups = document.querySelectorAll(selectors.DETAIL_GROUP);
        detailGroups.forEach((group) => {
            const subTitle = group
                .querySelector(selectors.DETAIL_SUB_TITLE)
                ?.textContent?.trim();
            const detailItems = group.querySelectorAll(selectors.DETAIL_ITEM);
            detailItems.forEach((item) => {
                const title = item
                    .querySelector(selectors.DETAIL_ITEM_TITLE)
                    ?.textContent?.trim();
                const dateElement = item.querySelector(selectors.DETAIL_ITEM_DATE);
                if (title && dateElement) {
                    let date = title === "活動エリア"
                        ? dateElement.innerHTML
                            .replace(/<br\s*\/?>/gi, ",")
                            .replace(/<[^>]*>/g, "")
                            .trim()
                            .replace(/,\s*,/g, ",")
                            .replace(/,$/, "")
                        : dateElement.textContent?.trim();
                    if (title && date) {
                        const key = title;
                        basicInfo[key] = {
                            value: date,
                            group: subTitle || "その他",
                        };
                    }
                }
            });
        });
        return {
            nickname: name,
            age,
            location,
            groups,
            selfPr,
            basicInfo,
            site: "MARRISH",
        };
    }
    function generatePrompt(data) {
        const template = TEMPLATES[data.site];
        if (!template) {
            throw new Error(`未知的网站类型: ${data.site}`);
        }
        let basicInfoText;
        if (data.site === "MARRISH") {
            basicInfoText = formatMarrishBasicInfo(data.basicInfo);
        }
        else {
            basicInfoText = formatBasicInfo(data.basicInfo);
        }
        const additionalText = formatAdditionalData(data);
        return buildPrompt(template, data, basicInfoText, additionalText);
    }
    function formatBasicInfo(basicInfo) {
        if (Object.entries(basicInfo).length === 0) {
            return "なし";
        }
        return Object.entries(basicInfo)
            .map(([key, value]) => `${key}: ${value}`)
            .join("\n");
    }
    function formatMarrishBasicInfo(basicInfo) {
        if (Object.entries(basicInfo).length === 0) {
            return "なし";
        }
        const groupedData = {};
        Object.entries(basicInfo).forEach(([key, data]) => {
            const group = data.group;
            if (!groupedData[group]) {
                groupedData[group] = [];
            }
            groupedData[group].push({ key, value: data.value });
        });
        const sections = [];
        Object.entries(groupedData).forEach(([group, items]) => {
            sections.push(group);
            items.forEach((item) => {
                sections.push(`  ${item.key}: ${item.value}`);
            });
            sections.push("");
        });
        return sections.join("\n").trim();
    }
    function formatAdditionalData(data) {
        switch (data.site) {
            case "WITH_IS":
                return data.commonPoints.length > 0
                    ? data.commonPoints.map((point) => `- ${point}`).join("\n")
                    : "なし";
            case "PAIRS":
                const parts = [];
                if (data.myTags.length > 0) {
                    parts.push(...data.myTags.map((tag) => `- ${tag}`));
                }
                if (data.pairsQuestions.length > 0) {
                    if (parts.length > 0)
                        parts.push("");
                    parts.push("ペアーズクエスチョン:");
                    data.pairsQuestions.forEach((q) => {
                        parts.push(`- ${q.question}`);
                        parts.push(`  ${q.answer}`);
                    });
                }
                return parts.length > 0 ? parts.join("\n") : "なし";
            case "MARRISH":
                return data.groups.length > 0
                    ? data.groups
                        .map((group) => `- ${group.title} (${group.member})`)
                        .join("\n")
                    : "なし";
            default:
                return "なし";
        }
    }
    function buildPrompt(template, data, basicInfoText, additionalText) {
        const introductionField = data.site === "MARRISH" ? "selfPr" : "introduction";
        return `${template.header}

${template.nickname}:${data.nickname}
${template.age}:${data.age}
${template.location}:${data.location}

${template.introduction}:
${data[introductionField]}

${template.additional}:
${additionalText}

${template.basicInfo}:
${basicInfoText}

${template.footer}`;
    }
    function showMessage(message, type) {
        const messageDiv = document.createElement("div");
        messageDiv.textContent = message;
        messageDiv.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 10px 15px;
            background: ${type === "success" ? "#28a745" : "#dc3545"};
            color: white;
            border-radius: 4px;
            z-index: 10000;
            font-size: 14px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
        `;
        document.body.appendChild(messageDiv);
        setTimeout(() => {
            if (messageDiv.parentNode) {
                messageDiv.parentNode.removeChild(messageDiv);
            }
        }, CONFIG.MESSAGE_DISPLAY_TIME);
    }
})();