From 01d97267a676d0652be5a5f48ad10ba95f04c411 Mon Sep 17 00:00:00 2001 From: Jin Ke <62723933+jinzong53@users.noreply.github.com> Date: Mon, 23 Jun 2025 18:33:04 +0800 Subject: [PATCH] Update comick and add baihehui (#88) * add new source from comick * fix some code * fix gif load and comic list info(none-type/chapter/volume) * add some comick hidden tags * revise coding error in file * info updata time * fix no-EN error * add new function - Multi-language comic selection support - Added comic recommendations - Fixed empty chapter return bug - Resolved tag click issues - Optimized data processing * Optimize network request Remove redundant requests and prevent async deadlocks * Update comick.js * new small comic source from baihehui --- baihehui.js | 673 ++++++++++++++++++++++++++++++++++++++++++++++++++++ comick.js | 563 ++++++++++++++++++++++++++----------------- index.json | 2 +- 3 files changed, 1025 insertions(+), 213 deletions(-) create mode 100644 baihehui.js diff --git a/baihehui.js b/baihehui.js new file mode 100644 index 0000000..71c1b25 --- /dev/null +++ b/baihehui.js @@ -0,0 +1,673 @@ +/** @type {import('./_venera_.js')} */ +class Baihehui extends ComicSource { + // Note: The fields which are marked as [Optional] should be removed if not used + + // name of the source + name = "百合会" + + // unique id of the source + key = "baihehui" + + version = "1.0.0" + + minAppVersion = "1.4.0" + + // update url + url = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@main/baihehui.js" + + settings = { + domains: { + title: "主页源", + type: "select", + options: [ + { value: "yamibo.com" }, + ], + default: "yamibo.com" + }, + } + + get baseUrl() { + return `https://www.${this.loadSetting('domains')}`; + } + + /** + * [Optional] init function + */ + init() { + + } + + account = { + login: async (username, password) => { + Network.deleteCookies("https://www.yamibo.com"); + // 1. GET 登录页,保存 PHPSESSID 和 _csrf-frontend + let resGet = await Network.get("https://www.yamibo.com/user/login", { + headers: { "User-Agent": "Mozilla/5.0" } + }); + if (resGet.status !== 200) throw "无法打开登录页"; + + // 1.1 提取并保存 GET 返回的 Set-Cookie + let sc1 = resGet.headers["set-cookie"] || resGet.headers["Set-Cookie"] || []; + let initialCookies = []; + for (let line of Array.isArray(sc1) ? sc1 : [sc1]) { + let [pair] = line.split(";"); + let [name, value] = pair.split("="); + name = name.trim(); value = value.trim(); + if (name === "PHPSESSID" || name === "_csrf-frontend") { + initialCookies.push(new Cookie({ name, value, domain: "www.yamibo.com" })); + } + } + Network.setCookies("https://www.yamibo.com", initialCookies); + + // 2. 解析 CSRF token + let doc = new HtmlDocument(resGet.body); + let csrf = doc + .querySelector('meta[name="csrf-token"]') + .attributes.content; + doc.dispose(); + + // 3. 构造编码后的表单 + let form = [ + `_csrf-frontend=${encodeURIComponent(csrf)}`, + `LoginForm%5Busername%5D=${encodeURIComponent(username)}`, + `LoginForm%5Bpassword%5D=${encodeURIComponent(password)}`, + 'LoginForm%5BrememberMe%5D=0', + 'LoginForm%5BrememberMe%5D=1', + `login-button=${encodeURIComponent("登录")}` + ].join("&"); + + // 4. POST 登录(会自动带上刚才的 Cookie) + let resPost = await Network.post( + "https://www.yamibo.com/user/login", + { + "Content-Type": "application/x-www-form-urlencoded", + "Referer": "https://www.yamibo.com/user/login", + "User-Agent": "Mozilla/5.0" + }, + form + ); + if (resPost.status === 400) throw "登录失败"; + Network.deleteCookies("https://www.yamibo.com"); + + // …account.login 中 POST 后提取 Cookie 部分… + let raw = resPost.headers["set-cookie"] || resPost.headers["Set-Cookie"]; + if (!raw) throw "未收到任何 Cookie"; + + // 1. 将单条字符串按“逗号+Cookie名=”拆分 + let parts = Array.isArray(raw) + ? raw + : raw.split(/,(?=\s*(?:PHPSESSID|_identity-frontend|_csrf-frontend)=)/); + + // 2. 提取目标 Cookie + const names = ["PHPSESSID", "_identity-frontend", "_csrf-frontend"]; + let cookies = parts.map(line => { + let [pair] = line.split(";"); + let [k, v] = pair.split("="); + k = k.trim(); v = v.trim(); + if (names.includes(k)) return new Cookie({ name: k, value: v, domain: "www.yamibo.com" }); + }).filter(Boolean); + + // 3. 验证并保存 + if (cookies.length !== names.length) { + throw "登录未返回完整 Cookie,实际:" + cookies.map(c => c.name).join(","); + } + Network.setCookies("https://www.yamibo.com", cookies); + + return true; + }, + + logout: () => { + Network.deleteCookies("https://www.yamibo.com"); + }, + + registerWebsite: "https://www.yamibo.com/user/signup" + } + + + static category_types = { + "全部作品": "manga/list@a@?", + "原创": "manga/list?q=4@a@&", + "同人": "manga/list?q=6@a@&", + } + + static article_types = { + "翻页漫画": "search/type?type=3&tag=@b@翻页漫画", + "条漫": "search/type?type=3&tag=@b@条漫", + "四格": "search/type?type=3&tag=@b@四格", + "绘本": "search/type?type=3&tag=@b@绘本", + "杂志": "search/type?type=3&tag=@b@杂志", + "合志": "search/type?type=3&tag=@b@合志", + } + + static relate_types = { + "编辑推荐": "manga/rcmds?type=3012@c@&", + "最近更新": "manga/latest@c@?", + "原创推荐": "manga/rcmds?type=3014@c@&", + "同人推荐": "manga/rcmds?type=3015@c@&", + } + + + + +// explore page list +explore = [ + { + title: "百合会", + type: "singlePageWithMultiPart", + load: async (page) => { + // 1. 拿到 HTML + let res = await Network.get("https://www.yamibo.com/site/manga"); + if (res.status !== 200) { + throw `Invalid status code: ${res.status}`; + } + + // 2. 解析文档 + let doc = new HtmlDocument(res.body); + + // 3. 通用解析单元函数 + function parseItem(el) { + let a = el.querySelector(".media-img") || el.querySelector("a.media-img"); + let href = a.attributes.href; + let id = href.match(/\/manga\/(\d+)/)[1]; + // 从 style 中提取 url + let style = a.attributes.style || ""; + let cover = `https://www.yamibo.com/coverm/000/000/${id}.jpg`; + let title = el.querySelector("h3 a").text.trim(); + return new Comic({ id, title, cover }); + } + + // 4. 抓「编辑推荐」 + let editor = []; + let editorEls = doc.querySelectorAll(".recommend-list .media-cell.horizontal"); + for (let el of editorEls) { + editor.push(parseItem(el)); + } + + // 5. 抓「最近更新」 + let latest = []; + // 找到标题元素,再拿其后面的