Greasy Fork is available in English.
Save Perplexity library/search pages to local files and Notion
当前为
// ==UserScript==
// @name Perplexity to Local/Notion
// @namespace http://tampermonkey.net/
// @version 1.2.3
// @description Save Perplexity library/search pages to local files and Notion
// @author sandleft
// @match https://www.perplexity.ai/*
// @run-at document-end
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// @connect api.notion.com
// ==/UserScript==
!function(){"use strict";let e=!1,t=null,n=!1,i=new Set(Array.isArray(GM_getValue("hiyori_selected_keys",[]))?GM_getValue("hiyori_selected_keys",[]):[]);const r={get token(){return(GM_getValue("notion_token","")||"").trim()},get dbId(){return(GM_getValue("db_id","")||"").trim()},get count(){const e=parseInt(GM_getValue("save_count","12"));return isNaN(e)||e<=0?12:e},get fileType(){const e=GM_getValue("file_type","md");return"md"===e||"txt"===e?e:"md"},get propTitle(){return(GM_getValue("prop_title","Title")||"Title").trim()},get propUrl(){return(GM_getValue("prop_url","URL")||"URL").trim()},get propTags(){return(GM_getValue("prop_tags","Tags")||"Tags").trim()},get propTime(){return(GM_getValue("prop_time","Time")||"Time").trim()},get autoRun(){return GM_getValue("auto_run",!1)},get autoRunDelay(){const e=parseInt(GM_getValue("auto_run_delay","5"));return isNaN(e)||e<0?5:e}};function o(e){return(e||"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function a(){return/^\/library(?:\/|$)/.test(window.location.pathname)}function l(){return/^\/search(?:\/|$)/.test(window.location.pathname)}function c(e){if(!e)return"";const t=String(e).trim().replace(/&/g,"&"),n=s(t);if(n)return n;const i=t.match(/https?:\/\/www\.perplexity\.ai\/search(?:\/[^\s"'<>]*)?(?:\?[^\s"'<>]*)?|(?:^|[\s"'=])((?:\/search(?:\/[^\s"'<>]*)?(?:\?[^\s"'<>]*)?))/);return i?s((i[1]||i[0]).trim()):""}function s(e){if(!e)return"";try{const t=new URL(e,window.location.origin);return t.origin!==window.location.origin?"":/^\/search(?:\/|$)/.test(t.pathname)?(t.hash="",t.href):""}catch(e){return""}}function u(e){if(!e)return"";const t=["href","data-href","data-url","data-link","to"];for(const n of t){const t=c(e.getAttribute&&e.getAttribute(n));if(t)return t}const n=e.querySelector&&e.querySelector('a[href*="/search/"], [href*="/search/"], [data-href*="/search/"], [data-url*="/search/"], [data-link*="/search/"]');if(n)for(const e of t){const t=c(n.getAttribute&&n.getAttribute(e));if(t)return t}if(e.outerHTML&&e.outerHTML.length<6e3){const t=c(e.outerHTML);if(t)return t}return""}function d(e){return(e&&e.innerText||"").replace(/\s+/g," ").trim()}function h(e){return e.url||e.titleKey||`idx:${e.originalIndex}`}function p(){document.querySelectorAll(".hiyori-checkbox").forEach(e=>{e.closest("#hiyori-panel")||e.remove()}),document.querySelectorAll(".hiyori-library-item").forEach(e=>{e.classList.remove("hiyori-library-item")})}function y(e,t,n,i,r){const o=function(e,t=!1){const n=document.querySelector("main")||document.body;let i=e;for(;i&&i!==n&&i!==document.body;){const e=(i.tagName||"").toLowerCase(),n=i.getAttribute&&i.getAttribute("role"),r=i.getBoundingClientRect?i.getBoundingClientRect():null,o=(i.innerText||"").trim();if(("li"===e||"article"===e||"listitem"===n||"link"===n||"button"===n||r&&r.width>=260&&r.height>=24&&r.height<=180&&o.length>0)&&(t||u(i)))return i;i=i.parentElement}return e.parentElement||e}(r,!0),a=u(o)||u(r),l=d(o),c=a?`url:${a}`:`row:${l}`;(function(e,t,n){if(!e||e===document.body||e===t)return!1;if(e.closest&&e.closest("#hiyori-panel, .hiyori-float-btn"))return!1;if(n)return!0;const i=d(e),r=e.getBoundingClientRect?e.getBoundingClientRect():null,o=/(搜索|search|小时前|天前|分钟前|hour|day|minute)/i.test(i);return!(i.length<12&&!o||r&&(r.width<260||r.height<24||r.height>180))})(o,i,a)&&(t.has(c)||n.has(o)||(t.add(c),n.add(o),e.push({url:a,originalIndex:e.length,item:o,titleKey:Array.from(l).slice(0,180).join("")})))}function f(){const e=document.querySelector("main")||document.body,t=Array.from(e.querySelectorAll(["a[href]",'[role="link"]','[role="button"]',"li","article",'[data-testid*="thread"]','[data-testid*="search"]','[data-testid*="library"]','[href*="/search/"]','[data-href*="/search/"]','[data-url*="/search/"]','[data-link*="/search/"]'].join(", "))),n=[],i=new Set,r=new Set;return t.forEach(t=>y(n,i,r,e,t)),n.length<2&&Array.from(e.querySelectorAll("div, button, [tabindex], [aria-label]")).forEach(t=>y(n,i,r,e,t)),n}async function m(e=15e3){const t=Date.now()+e;let n=f();for(;0===n.length&&Date.now()<t;)await $(350),n=f();return n}function g(e=f()){p();const t=document.getElementById("hiyori-pick-list"),n=document.getElementById("hiyori-pick-meta");if(!t)return;if(!a())return t.innerHTML='<div class="hiyori-pick-row"><span class="hiyori-pick-title">请先打开 Library/历史页面</span></div>',void(n&&(n.textContent="可选列表仅在 Library 页面显示"));if(!e.length)return t.innerHTML='<div class="hiyori-pick-row"><span class="hiyori-pick-title">暂未识别到历史文章,请等待页面加载后点刷新</span></div>',void(n&&(n.textContent="识别到 0 条"));const l=e.slice(0,Math.max(r.count,30));t.innerHTML=l.map(e=>{const t=h(e),n=i.has(t)?"checked":"";return`\n <label class="hiyori-pick-row">\n <input type="checkbox" class="hiyori-panel-checkbox"\n data-hiyori-key="${o(t)}" ${n}>\n <span class="hiyori-pick-title">${o(function(e){const t=(e&&e.titleKey||"").replace(/\s+/g," ").trim(),n=t.replace(/^搜索\s*/i,"").trim();return Array.from(n||t||`Library 第 ${e.originalIndex+1} 条`).slice(0,90).join("")}(e))}</span>\n </label>\n `}).join(""),t.querySelectorAll(".hiyori-panel-checkbox").forEach(t=>{t.addEventListener("change",()=>{t.checked?i.add(t.dataset.hiyoriKey):i.delete(t.dataset.hiyoriKey),GM_setValue("hiyori_selected_keys",Array.from(i).slice(0,200)),n&&(n.textContent=`识别到 ${e.length} 条,已勾选 ${i.size} 条`)})}),n&&(n.textContent=`识别到 ${e.length} 条,已勾选 ${i.size} 条`)}function b(e){return{url:e.url||"",libraryIndex:e.originalIndex,titleKey:e.titleKey||"",originalIndex:e.originalIndex}}function x(e,t,n={}){const i=e.getBoundingClientRect?e.getBoundingClientRect():null,r=i?i.left+Math.min(Math.max(i.width/2,8),Math.max(i.width-8,8)):0,o=i?i.top+Math.min(Math.max(i.height/2,8),Math.max(i.height-8,8)):0,a=Object.assign({bubbles:!0,cancelable:!0,view:window,button:0,buttons:t.includes("down")?1:0,clientX:r,clientY:o},n),l=t.startsWith("pointer")&&window.PointerEvent?window.PointerEvent:window.MouseEvent;e.dispatchEvent(new l(t,a))}async function _(e){const t=function(e){if(!e||!e.item)return null;const t=e.item;return t.matches&&t.matches('a[href], [role="link"], [role="button"]')?t:t.querySelector&&t.querySelector('a[href], [role="link"], [role="button"], [tabindex]')||t}(e);if(!t)return!1;const n=window.location.href;t.scrollIntoView({block:"center",inline:"nearest"}),await $(150);const i=function(e){if(!e||!e.getBoundingClientRect||!document.elementFromPoint)return e;const t=e.getBoundingClientRect(),n=t.left+Math.min(Math.max(t.width/2,8),Math.max(t.width-8,8)),i=t.top+Math.min(Math.max(t.height/2,8),Math.max(t.height-8,8)),r=document.elementFromPoint(n,i);return r&&(r===e||e.contains(r))?r:e}(t);try{x(i,"pointerdown",{pointerId:1,pointerType:"mouse",isPrimary:!0}),x(i,"mousedown"),x(i,"pointerup",{pointerId:1,pointerType:"mouse",isPrimary:!0}),x(i,"mouseup"),x(i,"click")}catch(e){console.warn("[妃爱] 模拟鼠标事件失败,改用原生 click:",e),t.click&&t.click()}for(let e=0;e<20;e++){if(window.location.href!==n||l())return!0;await $(200)}t.click&&t.click();for(let e=0;e<15;e++){if(window.location.href!==n||l())return!0;await $(200)}return!!e.url&&(window.location.href=e.url,!0)}async function w(e){const t=await m();g(t);const n=function(e,t){if(!Array.isArray(e)||!t)return null;if(t.url){const n=e.find(e=>e.url===t.url);if(n)return n}if(t.titleKey){const n=e.find(e=>e.titleKey===t.titleKey);if(n)return n}return Number.isInteger(t.libraryIndex)&&e[t.libraryIndex]?e[t.libraryIndex]:null}(t,e);return!!n&&_(n)}function M(){if(!a()||!r.autoRun||GM_getValue("hiyori_running",!1))return;if(t)return;const e=r.autoRunDelay;console.log(`[妃爱] 已开启自动抓取,${e} 秒后启动...`),t=setTimeout(()=>{t=null,a()&&!GM_getValue("hiyori_running",!1)&&(console.log("[妃爱] 自动抓取已启动!"),I(!1))},1e3*e)}function k(){t&&(clearTimeout(t),t=null)}function v(){if(document.getElementById("hiyori-panel"))return;const e=document.createElement("div");e.id="hiyori-panel",e.style.display=GM_getValue("panel_show","none"),e.innerHTML=`\n <div class="hiyori-title">🌸 P2L/N 🌸</div>\n\n <label class="hiyori-label">Notion 密钥 (Token)</label>\n <input id="h-token" class="hiyori-input" type="password"\n placeholder="secret_..." value="${o(r.token)}">\n\n <label class="hiyori-label">数据库 ID</label>\n <input id="h-dbid" class="hiyori-input"\n placeholder="输入数据库ID..." value="${o(r.dbId)}">\n\n <details style="margin: 6px 0;">\n <summary>▸ Notion 字段名设置(默认通常不用改)</summary>\n <label class="hiyori-label">标题字段名(Notion 默认库为 Name)</label>\n <input id="h-prop-title" class="hiyori-input"\n placeholder="Title" value="${o(r.propTitle)}">\n <label class="hiyori-label">链接字段名</label>\n <input id="h-prop-url" class="hiyori-input"\n placeholder="URL" value="${o(r.propUrl)}">\n <label class="hiyori-label">标签字段名</label>\n <input id="h-prop-tags" class="hiyori-input"\n placeholder="Tags" value="${o(r.propTags)}">\n <label class="hiyori-label">日期字段名</label>\n <input id="h-prop-time" class="hiyori-input"\n placeholder="Time" value="${o(r.propTime)}">\n </details>\n\n <label class="hiyori-label">自动保存数量</label>\n <input id="h-count" class="hiyori-input" type="number"\n min="1" value="${r.count}">\n\n <label class="hiyori-label">本地保存格式</label>\n <select id="h-filetype" class="hiyori-select">\n <option value="md" ${"md"===r.fileType?"selected":""}>Markdown (.md)</option>\n <option value="txt" ${"txt"===r.fileType?"selected":""}>纯文本</option>\n </select>\n\n <label class="hiyori-label">\n <input type="checkbox" id="h-auto-run" ${r.autoRun?"checked":""}\n style="margin-right: 5px; vertical-align: middle; accent-color: #ff69b4;">\n 进入 Library 自动开始抓取\n </label>\n <div style="display: flex; align-items: center; gap: 8px; margin-top: 5px;">\n <label class="hiyori-label" style="margin: 0;">延时</label>\n <input id="h-auto-delay" class="hiyori-input" type="number" min="0" max="300"\n value="${r.autoRunDelay}" style="width: 70px;">\n <span style="font-size: 12px; color: #ff69b4;">秒后启动</span>\n </div>\n\n <button id="h-save-config" class="hiyori-btn">保存设置 ✨</button>\n <hr style="border: 0.5px solid #ffb6c1; margin: 10px 0;">\n <button id="h-batch-auto" class="hiyori-btn">自动倒序抓取最新文章 🚀</button>\n <button id="h-refresh-list" class="hiyori-btn">刷新面板可选列表 🔄</button>\n <div id="hiyori-pick-meta" class="hiyori-pick-meta">可选列表加载中...</div>\n <div id="hiyori-pick-list"></div>\n <button id="h-batch-selected" class="hiyori-btn">保存面板勾选文章 🎯</button>\n <button id="h-stop" class="hiyori-btn"\n style="background:#ff9999; display:none;">紧急停止 🛑</button>\n `,document.body.appendChild(e);const t=document.createElement("div");t.className="hiyori-float-btn",t.innerHTML="🌸",t.onclick=()=>{const t="none"===e.style.display?"block":"none";e.style.display=t,GM_setValue("panel_show",t)},document.body.appendChild(t),document.getElementById("h-save-config").onclick=()=>{const e=parseInt(document.getElementById("h-count").value),t=parseInt(document.getElementById("h-auto-delay").value);GM_setValue("notion_token",document.getElementById("h-token").value.trim()),GM_setValue("db_id",document.getElementById("h-dbid").value.trim()),GM_setValue("prop_title",document.getElementById("h-prop-title").value.trim()||"Title"),GM_setValue("prop_url",document.getElementById("h-prop-url").value.trim()||"URL"),GM_setValue("prop_tags",document.getElementById("h-prop-tags").value.trim()||"Tags"),GM_setValue("prop_time",document.getElementById("h-prop-time").value.trim()||"Time"),GM_setValue("save_count",String(isNaN(e)||e<=0?12:e)),GM_setValue("file_type",document.getElementById("h-filetype").value),GM_setValue("auto_run",document.getElementById("h-auto-run").checked),GM_setValue("auto_run_delay",String(isNaN(t)||t<0?5:t)),alert("宝宝!设置已经牢牢记住辣!"),k(),M()},document.getElementById("h-batch-auto").onclick=()=>I(!1),document.getElementById("h-batch-selected").onclick=()=>I(!0),document.getElementById("h-refresh-list").onclick=()=>g(),document.getElementById("h-stop").onclick=()=>T(!0),GM_getValue("hiyori_running",!1)&&(document.getElementById("h-stop").style.display="block"),G(),g(),M()}function G(){if(!l())return;if(document.getElementById("hiyori-single-btn"))return;const e=document.createElement("button");e.id="hiyori-single-btn",e.className="hiyori-btn",e.innerHTML="🌸 保存当前页",e.onclick=()=>B(!0).catch(e=>console.error("[妃爱] 单篇保存出错:",e)),document.body.appendChild(e)}GM_addStyle("\n #hiyori-panel {\n position: fixed; top: 5%; right: 20px; width: 290px;\n max-height: 88vh; overflow-y: auto;\n background: #fff0f5; border: 2px solid #ffb6c1;\n border-radius: 15px; z-index: 10000; padding: 15px;\n font-family: 'Microsoft YaHei', sans-serif;\n box-shadow: 0 4px 15px rgba(255,182,193,0.4);\n scrollbar-width: thin; scrollbar-color: #ffb6c1 #fff0f5;\n }\n .hiyori-title { color: #ff69b4; font-weight: bold; text-align: center; margin-bottom: 10px; font-size: 16px; }\n .hiyori-label { font-size: 12px; color: #ff69b4; font-weight: bold; margin-top: 5px; display: block; }\n .hiyori-input, .hiyori-select {\n width: 100%; padding: 6px; margin: 3px 0 8px 0;\n border: 1px solid #ffb6c1; border-radius: 5px;\n font-size: 12px; box-sizing: border-box;\n }\n .hiyori-btn {\n width: 100%; padding: 8px; margin-top: 5px;\n background: #ffb6c1; color: white; border: none;\n border-radius: 20px; cursor: pointer; font-weight: bold; transition: 0.3s;\n }\n .hiyori-btn:hover { background: #ff69b4; transform: scale(1.02); }\n .hiyori-float-btn {\n position: fixed; bottom: 30px; right: 30px;\n width: 60px; height: 60px; background: #ffb6c1; color: white;\n border-radius: 50%; border: 4px solid #fff; cursor: pointer;\n z-index: 9999; font-size: 30px;\n display: flex; align-items: center; justify-content: center;\n box-shadow: 0 4px 10px rgba(0,0,0,0.2);\n }\n #hiyori-pick-list { max-height: 180px; overflow-y: auto; margin-top: 6px; border: 1px solid #ffb6c1; border-radius: 8px; background: rgba(255,255,255,0.55); }\n .hiyori-pick-row { display: flex; gap: 6px; align-items: flex-start; padding: 6px; border-bottom: 1px solid rgba(255,182,193,0.45); font-size: 11px; color: #7a2b52; cursor: pointer; }\n .hiyori-pick-row:last-child { border-bottom: none; }\n .hiyori-pick-row input { margin-top: 2px; accent-color: #ff69b4; flex: 0 0 auto; }\n .hiyori-pick-title { line-height: 1.35; overflow-wrap: anywhere; }\n .hiyori-pick-meta { font-size: 11px; color: #b5477a; margin-top: 6px; }\n #hiyori-single-btn {\n position: fixed; bottom: 100px; right: 30px; width: 120px;\n z-index: 9998; box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n }\n #hiyori-panel details > summary {\n color: #ff69b4; font-size: 12px; cursor: pointer; font-weight: bold;\n }\n ");let V=location.href;function T(e=!1){if(GM_setValue("hiyori_running",!1),GM_setValue("hiyori_queue",[]),e){const e=GM_getValue("hiyori_failures",[]);Array.isArray(e)&&e.length>0?alert(`🛑 已停止!以下文章处理失败或写入 Notion 失败:\n${e.join("\n")}`):alert("🛑 已经乖乖停下啦!")}GM_setValue("hiyori_failures",[]);const t=document.getElementById("h-stop");t&&(t.style.display="none")}async function I(e){if(!a())return void alert("宝宝,请先打开 Perplexity 的 Library/历史页面再批量抓取哦!");if(GM_getValue("hiyori_running",!1)&&!confirm("检测到已有批量任务运行中,是否强制覆盖?"))return;const t=await m();g(t);const n=[],o=new Set;if(e?t.forEach(e=>{const t=h(e);i.has(t)&&!o.has(t)&&(o.add(t),n.push(b(e)))}):t.slice(0,r.count).forEach(e=>{const t=h(e);o.has(t)||(o.add(t),n.push(b(e)))}),0===n.length)return void alert(e?"宝宝,面板列表里还没有勾选文章哦!请点“刷新面板可选列表”后在面板内勾选。":"宝宝,没有找到文章呀,请确认 Library/历史页面已经加载完毕哦!");n.reverse(),GM_setValue("hiyori_queue",n),GM_setValue("hiyori_running",!0),GM_setValue("hiyori_failures",[]);const l=document.getElementById("h-stop");l&&(l.style.display="block"),E()}async function E(){if(!GM_getValue("hiyori_running",!1))return;if(n)return;const e=GM_getValue("hiyori_queue",[]);if(!Array.isArray(e))return console.error("[妃爱] 队列数据损坏,已静默重置"),T(!1),void alert("⚠️ 队列数据异常,已自动重置,请重新开始。");if(e.length>0){const t=e.shift();if(GM_setValue("hiyori_current_tag_index",t.originalIndex),GM_setValue("hiyori_queue",e),Number.isInteger(t.libraryIndex)){if(!a())return e.unshift(t),GM_setValue("hiyori_queue",e),void(window.location.href="https://www.perplexity.ai/library");n=!0;const i=await w(t);return n=!1,void(i||(console.error("[妃爱] 无法通过模拟点按打开 Library 条目:",t),S(t.titleKey||`Library 第 ${t.originalIndex+1} 条`),setTimeout(()=>E(),700)))}t.url&&t.url===window.location.href?window.location.reload():t.url?window.location.href=t.url:(console.error("[妃爱] 队列条目缺少可打开的信息,已跳过:",t),S(t.titleKey||`Library 第 ${t.originalIndex+1} 条`),setTimeout(()=>E(),700))}else{GM_setValue("hiyori_running",!1);const e=GM_getValue("hiyori_failures",[]);GM_setValue("hiyori_failures",[]),Array.isArray(e)&&e.length>0?alert(`🌸 批量完成!但以下文章处理失败或写入 Notion 失败:\n${e.join("\n")}`):alert("🌸 宝宝!所有的素材都已经完美归档啦!"),window.location.href="https://www.perplexity.ai/library"}}function $(e){return new Promise(t=>setTimeout(t,e))}function A(e,t){return Array.from(e).slice(0,t).join("")}function S(e){const t=GM_getValue("hiyori_failures",[]);Array.isArray(t)&&(t.push(e),GM_setValue("hiyori_failures",t))}async function B(t=!1){if(e)console.warn("[妃爱] 已在处理中,跳过重复调用");else{e=!0;try{const e=await async function(e=15e3,t=1500){const n=Date.now()+e;let i=-1,r=0;for(;Date.now()<n;){const e=document.querySelector("main")||document.body,n=(e.innerText||"").length;if(n>200)if(n===i){if(0===r&&(r=Date.now()),Date.now()-r>=t)return e}else r=0,i=n;await $(400)}return document.querySelector("main")||document.body}();if(!t&&!GM_getValue("hiyori_running",!1))return;const n=await async function(e=8e3){const t=new Set(["","Perplexity","Perplexity AI","New Thread","Ask anything","Untitled","新建对话","新线程","新しいスレッド","新しい質問","새 스레드"]),n=Date.now()+e;for(;Date.now()<n;){const e=document.title.replace(/ - Perplexity/g,"").trim();if(e&&!t.has(e))return e;await $(300)}return document.title.replace(/ - Perplexity/g,"").trim()||"未命名对话"}();if(!t&&!GM_getValue("hiyori_running",!1))return;const i=window.location.href,o=new Set;e.querySelectorAll('a[href^="http"]').forEach(e=>{e.href&&!e.href.includes("perplexity.ai")&&o.add(e.href)});const a=Array.from(e.querySelectorAll("img")).filter(e=>(e.currentSrc||e.dataset.src||e.src||"").startsWith("http")&&(e.naturalWidth>50||!!e.dataset.src)),l=(e.innerText||"").trim();if(!l)return console.warn("[妃爱] 页面内容为空,跳过:",n),t&&alert("宝宝,页面内容还没加载出来哦,请稍后再试!"),void(t||E());const c=o.size>0?"\n\n---\n### 🌸 引用来源 (Sources)\n"+Array.from(o).map((e,t)=>`[${t+1}] ${e}`).join("\n"):"",s=l+c+(a.length>0?"\n\n---\n### 🌸 提取的附图资源\n"+a.map(e=>{const t=e.currentSrc||e.dataset.src||e.src;return"md"===r.fileType?``:`[图片链接]: ${t}`}).join("\n\n"):"");let u="综合";if(!t){const e=GM_getValue("hiyori_current_tag_index",0);u=e<4?"经济":e<10?"政治军事":"综合"}!function(e,t,n){const i=A(e.replace(/[/\\:*?"<>|]/g,"_"),40),r="md"===n?"text/markdown":"text/plain",o=URL.createObjectURL(new Blob([t],{type:r+";charset=utf-8"})),a=document.createElement("a");a.href=o,a.download=`${i}.${n}`,document.body.appendChild(a),a.click(),document.body.removeChild(a),setTimeout(()=>URL.revokeObjectURL(o),1e4)}(n,s,r.fileType),r.token&&r.dbId?await L(n,i,s,u,t):t?alert("宝宝,只帮您保存了本地文件哦!Notion 配置未填写。"):E()}catch(e){console.error("[妃爱] processCurrentPage 出错:",e),!t&&GM_getValue("hiyori_running",!1)&&E()}finally{e=!1}}}function L(e,t,n,i,o,a=0){return new Promise(l=>{const c=Array.from(n).length>188100,s=function(e,t){const n=Array.from(e),i=[];for(let e=0;e<n.length;e+=t)i.push(n.slice(e,e+t).join(""));return i}(n,1900).slice(0,99).map(e=>({object:"block",type:"paragraph",paragraph:{rich_text:[{type:"text",text:{content:e}}]}})),u=new Date,d=[u.getFullYear(),String(u.getMonth()+1).padStart(2,"0"),String(u.getDate()).padStart(2,"0")].join("-"),h={};h[r.propTitle]={title:[{type:"text",text:{content:A(e,100)}}]},h[r.propUrl]={url:t},h[r.propTags]={multi_select:[{name:i}]},h[r.propTime]={date:{start:d}},GM_xmlhttpRequest({method:"POST",url:"https://api.notion.com/v1/pages",timeout:2e4,headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json","Notion-Version":"2022-06-28"},data:JSON.stringify({parent:{database_id:r.dbId},properties:h,children:s}),onload(r){if(429===r.status&&a<3){const r=8e3*(a+1);return console.warn(`[妃爱] Notion 限流,${r/1e3}s 后重试(第 ${a+1} 次)`),void setTimeout(()=>L(e,t,n,i,o,a+1).then(l),r)}r.status<200||r.status>=300?(console.error("[妃爱] Notion 写入失败:",r.status,r.responseText),S(e)):c&&console.warn("[妃爱] 内容超限,已截断至约 18.6 万字符:",e),l(),!o&&GM_getValue("hiyori_running",!1)&&E()},onerror(t){console.error("[妃爱] Notion 网络错误:",t),S(e),l(),!o&&GM_getValue("hiyori_running",!1)&&E()},ontimeout(){console.error("[妃爱] Notion 请求超时,已跳过:",e),S(e),l(),!o&&GM_getValue("hiyori_running",!1)&&E()}})})}new MutationObserver(()=>{if(location.href===V)return;V=location.href,n=!1;const e=document.getElementById("hiyori-single-btn");e&&e.remove(),G(),a()?(g(),M(),GM_getValue("hiyori_running",!1)&&setTimeout(()=>E(),700)):k(),l()&&GM_getValue("hiyori_running",!1)&&B().catch(e=>{console.error("[妃爱] 自动处理入口出错:",e),GM_getValue("hiyori_running",!1)&&E()})}).observe(document.body,{childList:!0,subtree:!0}),"complete"===document.readyState?v():window.addEventListener("load",v),setInterval(()=>{p(),a()&&g()},4e3),a()&&(M(),GM_getValue("hiyori_running",!1)&&setTimeout(()=>E(),700)),l()&&GM_getValue("hiyori_running",!1)&&B().catch(e=>{console.error("[妃爱] 自动处理入口出错:",e),GM_getValue("hiyori_running",!1)&&E()})}();