// ==UserScript==
// @name Kikoeru checker for ASMROne UpdateVer
// @namespace http://tampermonkey.net/
// @version 1.01
// @description Check if ASMR elements exist in the library
// @author Your Name
// @match *://asmr-300.com/*
// @match *://asmr-200.com/*
// @match *://asmr-100.com/*
// @match *://www.asmr.one/*
// @grant GM_xmlhttpRequest
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 固定常量用于存储JWT令牌
//if you dont need to login your kikoeru,change next line to //const Token... and delate '&token=${TOKEN}' in function 'kikoeruCheck's first url
const TOKEN = "TOKEN";
const BASE_URL = "http://your url:port";
const processedRJNumbers = new Set();
// 观察DOM变化
const observer = new MutationObserver((mutations, obs) => {
const divs = document.querySelectorAll('div[id^="RJ"]');
divs.forEach(div => {
const rjNumber = div.id;
if (!processedRJNumbers.has(rjNumber)) {
console.log(`检查RJ号: ${rjNumber}`);
processedRJNumbers.add(rjNumber);
getAllRJNumbers(rjNumber).then(rjInfoArray => {
rjInfoArray.forEach(rjInfo => {
kikoeruCheck(rjInfo.rj, rjInfo.language, div);
});
}).catch(error => {
console.error(`获取RJ号信息失败: ${rjNumber}`, error);
// 出错时使用原始RJ号进行检查
kikoeruCheck(rjNumber, rjNumber, div);
});
}
});
});
observer.observe(document, {
childList: true,
subtree: true
});
// 缓存管理功能
const RJ_CACHE_KEY = "dlsite_rj_language_cache";
const CACHE_EXPIRY = 7 * 24 * 60 * 60 * 1000; // 缓存7天
// 获取缓存数据
function getCache() {
try {
const cachedData = localStorage.getItem(RJ_CACHE_KEY);
if (!cachedData) return {};
const parsedCache = JSON.parse(cachedData);
// 清理过期缓存
const now = Date.now();
let hasExpired = false;
Object.keys(parsedCache).forEach(key => {
if (parsedCache[key].timestamp && (now - parsedCache[key].timestamp) > CACHE_EXPIRY) {
delete parsedCache[key];
hasExpired = true;
}
});
if (hasExpired) {
saveCache(parsedCache);
}
return parsedCache;
} catch (error) {
console.error("读取缓存失败:", error);
return {};
}
}
// 保存缓存数据
function saveCache(data) {
try {
localStorage.setItem(RJ_CACHE_KEY, JSON.stringify(data));
return true;
} catch (error) {
console.error("保存缓存失败:", error);
return false;
}
}
// 获取RJ号的缓存信息
function getCachedRJInfo(rjNumber) {
const cache = getCache();
return cache[rjNumber] || null;
}
// 保存RJ号信息到缓存
function saveRJInfoToCache(rjNumber, rjInfoArray) {
const cache = getCache();
cache[rjNumber] = {
data: rjInfoArray,
timestamp: Date.now()
};
return saveCache(cache);
}
function getAllRJNumbers(rjNumber) {
return new Promise((resolve, reject) => {
// 首先检查缓存
const cachedInfo = getCachedRJInfo(rjNumber);
if (cachedInfo && cachedInfo.data) {
console.log(`使用缓存的RJ信息: ${rjNumber}`);
return resolve(cachedInfo.data);
}
// 缓存未命中,请求API
const url = `https://www.dlsite.com/maniax/work/=/product_id/${rjNumber}.html`;
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(response) {
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, 'text/html');
const links = doc.querySelectorAll('.work_edition_linklist.type_trans a');
const rjInfoArray = Array.from(links).map(link => {
const match = link.href.match(/RJ\d{6,8}/);
const rj = match ? match[0] : null;
// 获取语言版本信息
const language = link.textContent.trim();
return rj ? { rj, language } : null;
}).filter(Boolean);
const uniqueRJInfoArray = [...new Map(rjInfoArray.map(item => [item.rj, item])).values()];
if (uniqueRJInfoArray.length === 0) {
console.log(`未找到新的RJ号,使用输入值: ${rjNumber}`);
const result = [{ rj: rjNumber, language: "日文" }];
// 保存到缓存
saveRJInfoToCache(rjNumber, result);
resolve(result);
} else {
console.log(`找到带语言的RJ号:`, uniqueRJInfoArray);
// 保存到缓存
saveRJInfoToCache(rjNumber, uniqueRJInfoArray);
resolve(uniqueRJInfoArray);
}
},
onerror: function(error) {
console.error("请求失败:", error);
reject(error);
}
});
});
}
// 全局变量 - 用于存储已经创建的容器
let buttonContainerCreated = false;
let globalButtonContainer = null;
async function kikoeruCheck(rj, language, item) {
const url = `${BASE_URL}/api/search?page=1&sort=desc&order=created_at&nsfw=0&lyric=&seed=50&isAdvance=0&keyword=${rj}&token=${TOKEN}`;
console.log("检查RJ号:", rj, "语言:", language);
try {
const response = await fetchData(url);
const data = JSON.parse(response.responseText);
// 创建按钮
const button = document.createElement('button');
button.textContent = language || rj; // 使用语言信息作为按钮文本
button.style.margin = '0 5px';
button.style.padding = '4px 10px';
button.style.borderRadius = '4px';
button.style.border = 'none';
button.style.color = 'white';
button.style.fontWeight = 'bold';
button.style.cursor = 'pointer';
button.style.display = 'inline-block'; // 使按钮内联显示
// 设置按钮颜色和点击事件
if (data && data.works) {
const works = data.works;
if (works.length > 1) {
button.style.backgroundColor = 'green';
button.onclick = () => window.open(`${BASE_URL}/works?keyword=${rj}`);
} else if (works.length === 1) {
const asmroneItemId = works[0].id;
const isMatch = ["RJ0", "RJ"].some(prefix => [asmroneItemId + 1, asmroneItemId - 1, asmroneItemId].some(id => `${prefix}${id}` === rj));
if (isMatch) {
button.style.backgroundColor = 'green';
button.onclick = () => window.open(`${BASE_URL}/work/${asmroneItemId}`);
} else {
button.style.backgroundColor = 'red';
button.onclick = () => window.open(`${BASE_URL}/works?keyword=${rj}`);
}
} else {
button.style.backgroundColor = 'red';
button.onclick = () => window.open(`${BASE_URL}/works?keyword=${rj}`);
}
} else {
console.error("无效的响应结构:", data);
button.style.backgroundColor = 'red';
}
// 使用延迟确保DOM已完成渲染
setTimeout(() => {
try {
const titleElement = item.querySelector('.q-mx-sm.text-h6.text-weight-regular.ellipsis-2-lines');
const authorElement = item.querySelector('.q-ml-sm.q-mb-xs.text-subtitle1.text-weight-regular');
if (titleElement && authorElement) {
// 检查是否已经创建了按钮容器
let buttonContainer = item.querySelector('.kikoeru-btn-container');
// 如果没有容器,则创建一个新容器
if (!buttonContainer) {
buttonContainer = document.createElement('div');
buttonContainer.className = 'kikoeru-btn-container';
// 设置容器样式 - 横向排列
buttonContainer.style.display = 'block';
buttonContainer.style.textAlign = 'left';
buttonContainer.style.width = '100%';
buttonContainer.style.margin = '5px 0';
buttonContainer.style.padding = '0 10px';
// 将容器插入到DOM
titleElement.parentNode.insertBefore(buttonContainer, authorElement);
console.log("创建了新的按钮容器");
} else {
console.log("使用已存在的按钮容器");
}
// 将按钮添加到容器中
buttonContainer.appendChild(button);
console.log(`成功将按钮添加到按钮容器`);
} else {
console.error("找不到标题或作者元素");
}
} catch (error) {
console.error("插入按钮时发生错误:", error);
}
}, 200);
} catch (error) {
console.error("获取数据时出错:", error);
}
}
function fetchData(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: (response) => resolve(response),
onerror: (error) => reject(error),
});
});
}
})();