书源仓库
https://www.yckceo.com/
rogueadmin (13751) 05/27 20:24 下载:4052
网页 免费 书源仓库
书源仓库、一键导入
// @uuid 019e6965-2172-7f6d-8f18-6368c69d9671
// @name 书源仓库
// @version 1.0.1
// @author 流氓丶R
// @url https://www.yckceo.com/
// @type webpage
// @logo default
// @enabled true
// @tags 免费,书源仓库
// @description 书源仓库、一键导入
const BASE_URL = 'https://www.yckceo.com/legadotauri/shuyuan/index.html';
const PAGE_TPL = BASE_URL + '?page={{page}}';
// 解析分类(单分类)
function parseExploreCategories() {
return [{
name: "全部书源",
url: PAGE_TPL
}];
}
// 解析书源+总页数
function parseItemsAndTotalPage(html, currentPage) {
const items = [];
// 1. 解析书源数据
const bookSourcePattern = /<h2><a href="\/legadotauri\/shuyuan\/content\/id\/(\d+).html">(.+)<\/a>\s+<p[^>]+>([^<]+)<\/p>\s+<p[^>]+><span[^>]+>([^<]+)<\/span><\/p>\s+<\/h2>\s+<span[^>]+>([^<]+)<\/span>\s+<span[^>]+>([^<]+)<\/span>\s+<span[^>]+>下载:([^<]+)<\/span>/g;
let match;
while ((match = bookSourcePattern.exec(html))) {
const id = match[1];
const name = match[2];
const time = match[3];
const category = match[4];
const version = match[5];
const sharer = match[6];
const downloadCount = match[7];
const importLink = `legado://?url=https://www.yckceo.com/legadotauri/shuyuan/json/id/${id}`;
items.push({
id,
name,
category,
version,
downloadCount,
importLink,
time,
sharer
});
}
// 2. 提取总页数并修正
const pagePattern = /<a href="\/legadotauri\/shuyuan\/index\.html\?page=(\d+)">/g;
const pages = [];
let pageMatch;
while ((pageMatch = pagePattern.exec(html))) {
pages.push(Number(pageMatch[1]));
}
let totalPage = pages.length > 0? Math.max(...pages) : 1;
if (totalPage < currentPage) {
totalPage = currentPage;
}
return { items, totalPage };
}
// 构建带分页的HTML页面
function buildHtmlWithPagination(items, currentPage, totalPage) {
// 1. 书源卡片区域
let html = `<div style="display: flex; flex-wrap: wrap; gap: 20px; padding: 15px;">`;
items.forEach((item) => {
html += `<div style="
background: var(--card-bg, #fff);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
padding: 16px;
width: 240px;
transition: transform 0.2s;
display: flex;
flex-direction: column;
justify-content: space-between;
" onmouseover="this.style.transform='translateY(-3px)'" onmouseout="this.style.transform='translateY(0)'">
<div>
<p style="font-weight: 600; margin: 0 0 8px; word-break: break-all; font-size: 14px; color: var(--text-color, #000);">
名称: ${item.name}
</p>
<p style="margin: 0 0 6px; font-size: 13px; color: var(--text-color, #000);">
<span style="background: var(--category-bg, #e1f5fe); padding: 2px 8px; border-radius: 4px;">${item.category}</span>
</p>
<p style="margin: 0 0 10px; font-size: 13px; color: var(--secondary-text-color, #666);">
版本: ${item.version}
下载: <span style="color: var(--accent-color, #0078d4);">${item.downloadCount}</span>
</p>
<p style="margin: 0 0 12px; font-size: 12px; color: var(--secondary-text-color, #999); display: flex; justify-content: space-between;">
<span>时间: ${item.time}</span>
<span>分享: ${item.sharer}</span>
</p>
</div>
<a href="${item.importLink}" style="
display: block;
width: 100%;
padding: 8px 0;
background: var(--accent-color, #0078d4);
color: #fff;
border-radius: 4px;
text-decoration: none;
font-size: 13px;
text-align: center;
">导入</a>
</div>`;
});
html += '</div>';
// 2. 分页导航区域
let prevButton = '';
let nextButton = '';
if (currentPage === 1) {
prevButton = `<a href="#" onclick="loadPage(${currentPage - 1})" style="margin: 0 10px; color: var(--disabled-color, #999); pointer-events: none;" disabled>上一页</a>`;
} else {
prevButton = `<a href="#" onclick="loadPage(${currentPage - 1})" style="margin: 0 10px; color: var(--accent-color, #0078d4);">上一页</a>`;
}
if (currentPage === totalPage) {
nextButton = `<a href="#" onclick="loadPage(${currentPage + 1})" style="margin: 0 10px; color: var(--disabled-color, #999); pointer-events: none;" disabled>下一页</a>`;
} else {
nextButton = `<a href="#" onclick="loadPage(${currentPage + 1})" style="margin: 0 10px; color: var(--accent-color, #0078d4);">下一页</a>`;
}
html += `<div style="text-align: center; padding: 20px; font-size: 14px; color: var(--text-color, #000);">
<span>第 ${currentPage}/${totalPage} 页</span>
${prevButton}
${nextButton}
</div>`;
return html;
}
// 渲染模板
function renderTemplate(tpl, data) {
return tpl.replace(/{{(\w+)}}/g, (_, key) => data[key] || '');
}
async function explore(page, category) {
page = page || 1;
// 1. 处理分类请求(返回分类列表)
if (category === "GETALL" ||!category) {
const cats = parseExploreCategories();
return cats.map(cat => cat.name);
}
// 2. 处理分页请求(返回自定义HTML)
const url = renderTemplate(PAGE_TPL, { page: page });
const html = await legado.http.get(url);
const { items, totalPage } = parseItemsAndTotalPage(html, page);
// 构建带分页的自定义HTML页面
const customHtml = buildHtmlWithPagination(items, page, totalPage);
legado.log(`[探索] 第${page}/${totalPage}页 找到${items.length}个书源`);
// 返回Legado支持的自定义HTML格式,并注入JavaScript函数
return {
type: 'html',
html: `
<html>
<head>
<style>
:root {
--text-color: #000;
--secondary-text-color: #666;
--accent-color: #0078d4;
--category-bg: #e1f5fe;
--card-bg: #fff;
--disabled-color: #999;
}
@media (prefers - color - scheme: dark) {
:root {
--text-color: #fff;
--secondary-text-color: #ccc;
--accent-color: #0078d4;
--category-bg: #1976d2;
--card-bg: #222;
--disabled-color: #666;
}
}
</style>
<script>
async function loadPage(newPage) {
await window.legado.explore('全部书源', newPage);
}
</script>
</head>
<body>
<div id="exploreResult">${customHtml}</div>
</body>
</html>
`
};
}