Update baozi.js (#66)

新增简繁、域名切换
修复只有最新章节时地址错误
#55 
#56
This commit is contained in:
lost one
2025-05-08 22:53:33 +08:00
committed by GitHub
parent 6760e8a41f
commit 54e1494020

146
baozi.js
View File

@@ -5,15 +5,45 @@ class Baozi extends ComicSource {
// 唯一标识符 // 唯一标识符
key = "baozi" key = "baozi"
version = "1.0.3" version = "1.0.4"
minAppVersion = "1.0.0" minAppVersion = "1.0.0"
// 更新链接 // 更新链接
url = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@main/baozi.js" url = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@main/baozi.js"
/// APP启动时或者添加/更新漫画源时执行此函数 settings = {
init() {} language: {
title: "简繁切换",
type: "select",
options: [
{ value: "cn", text: "简体" },
{ value: "tw", text: "繁體" }
],
default: "cn"
},
domains: {
title: "主域名",
type: "select",
options: [
{ value: "baozimhcn.com" },
{ value: "webmota.com" },
{ value: "kukuc.co" },
{ value: "twmanga.com" },
{ value: "dinnerku.com" }
],
default: "baozimhcn.com"
}
}
// 动态生成完整域名
get lang() {
return this.loadSetting('language') || this.settings.language.default;
}
get baseUrl() {
let domain = this.loadSetting('domains') || this.settings.domains.default;
return `https://${this.lang}.${domain}`;
}
/// 账号 /// 账号
/// 设置为null禁用账号功能 /// 设置为null禁用账号功能
@@ -24,29 +54,32 @@ class Baozi extends ComicSource {
let res = await Network.post(`${this.baseUrl}/api/bui/signin`, { let res = await Network.post(`${this.baseUrl}/api/bui/signin`, {
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryFUNUxpOwyUaDop8s' 'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryFUNUxpOwyUaDop8s'
}, "------WebKitFormBoundaryFUNUxpOwyUaDop8s\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\n" + account + "\r\n------WebKitFormBoundaryFUNUxpOwyUaDop8s\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n" + pwd + "\r\n------WebKitFormBoundaryFUNUxpOwyUaDop8s--\r\n") }, "------WebKitFormBoundaryFUNUxpOwyUaDop8s\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\n" + account + "\r\n------WebKitFormBoundaryFUNUxpOwyUaDop8s\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n" + pwd + "\r\n------WebKitFormBoundaryFUNUxpOwyUaDop8s--\r\n")
if(res.status !== 200) { if (res.status !== 200) {
throw "Invalid status code: " + res.status throw "Invalid status code: " + res.status
} }
let json = JSON.parse(res.body) let json = JSON.parse(res.body)
let token = json.data let token = json.data
Network.setCookies(this.baseUrl, [ Network.setCookies(this.baseUrl, [
new Cookie({name: 'TSID', value: token, domain: '.baozimhcn.com'}), new Cookie({
name: 'TSID',
value: token,
domain: this.loadSetting('domains') || this.settings.domains.default
}),
]) ])
return 'ok' return 'ok'
}, },
// 退出登录时将会调用此函数 // 退出登录时将会调用此函数
logout: () => { logout: function() {
Network.deleteCookies('.baozimhcn.com') Network.deleteCookies(this.loadSetting('domains') || this.settings.domains.default)
}, },
registerWebsite: `https://cn.baozimhcn.com/user/signup` get registerWebsite() {
} return `${this.baseUrl}/user/signup`
}
get baseUrl(){
return `https://cn.baozimhcn.com`
} }
/// 解析漫画列表
parseComic(e) { parseComic(e) {
let url = e.querySelector("a").attributes['href'] let url = e.querySelector("a").attributes['href']
let id = url.split("/").pop() let id = url.split("/").pop()
@@ -68,15 +101,14 @@ class Baozi extends ComicSource {
id: e.comic_id, id: e.comic_id,
title: e.name, title: e.name,
subTitle: e.author, subTitle: e.author,
cover: `https://static-tw.baozimhcn.com/cover/${e.topic_img}?w=285&h=375&q=100`, cover: `https://static-tw.baozimh.com/cover/${e.topic_img}?w=285&h=375&q=100`,
tags: e.type_names, tags: e.type_names,
} }
} }
/// 探索页面 /// 探索页面
/// 一个漫画源可以有多个探索页面 /// 一个漫画源可以有多个探索页面
explore = [ explore = [{
{
/// 标题 /// 标题
/// 标题同时用作标识符, 不能重复 /// 标题同时用作标识符, 不能重复
title: "包子漫画", title: "包子漫画",
@@ -95,7 +127,7 @@ class Baozi extends ComicSource {
for (let part of parts) { for (let part of parts) {
let title = part.querySelector("div.catalog-title").text.trim() let title = part.querySelector("div.catalog-title").text.trim()
let comics = part.querySelectorAll("div.comics-card").map(e => this.parseComic(e)) let comics = part.querySelectorAll("div.comics-card").map(e => this.parseComic(e))
if(comics.length > 0) { if (comics.length > 0) {
result[title] = comics result[title] = comics
} }
} }
@@ -109,8 +141,7 @@ class Baozi extends ComicSource {
category = { category = {
/// 标题, 同时为标识符, 不能与其他漫画源的分类页面重复 /// 标题, 同时为标识符, 不能与其他漫画源的分类页面重复
title: "包子漫画", title: "包子漫画",
parts: [ parts: [{
{
name: "类型", name: "类型",
// fixed 或者 random // fixed 或者 random
@@ -137,13 +168,13 @@ class Baozi extends ComicSource {
/// 分类漫画页面, 即点击分类标签后进入的页面 /// 分类漫画页面, 即点击分类标签后进入的页面
categoryComics = { categoryComics = {
load: async (category, param, options, page) => { load: async (category, param, options, page) => {
let res = await Network.get(`${this.baseUrl}/api/bzmhq/amp_comic_list?type=${param}&region=${options[0]}&state=${options[1]}&filter=%2a&page=${page}&limit=36&language=${this.lang}&__amp_source_origin=https%3A%2F%2F${this.lang}.baozimhcn.com`) let res = await Network.get(`${this.baseUrl}/api/bzmhq/amp_comic_list?type=${param}&region=${options[0]}&state=${options[1]}&filter=%2a&page=${page}&limit=36&language=${this.lang}&__amp_source_origin=${this.baseUrl}`)
if (res.status !== 200) { if (res.status !== 200) {
throw "Invalid status code: " + res.status throw "Invalid status code: " + res.status
} }
let maxPage = null let maxPage = null
let json = JSON.parse(res.body) let json = JSON.parse(res.body)
if(!json.next) { if (!json.next) {
maxPage = page maxPage = page
} }
return { return {
@@ -152,8 +183,7 @@ class Baozi extends ComicSource {
} }
}, },
// 提供选项 // 提供选项
optionList: [ optionList: [{
{
options: [ options: [
"all-全部", "all-全部",
"cn-国漫", "cn-国漫",
@@ -161,8 +191,7 @@ class Baozi extends ComicSource {
"kr-韩国", "kr-韩国",
"en-欧美", "en-欧美",
], ],
}, }, {
{
options: [ options: [
"all-全部", "all-全部",
"serial-连载中", "serial-连载中",
@@ -197,7 +226,7 @@ class Baozi extends ComicSource {
multiFolder: false, multiFolder: false,
/// 添加或者删除收藏 /// 添加或者删除收藏
addOrDelFavorite: async (comicId, folderId, isAdding) => { addOrDelFavorite: async (comicId, folderId, isAdding) => {
if(!isAdding) { if (!isAdding) {
let res = await Network.post(`${this.baseUrl}/user/operation_v2?op=del_bookmark&comic_id=${comicId}`) let res = await Network.post(`${this.baseUrl}/user/operation_v2?op=del_bookmark&comic_id=${comicId}`)
if (!res.status || res.status >= 400) { if (!res.status || res.status >= 400) {
throw "Invalid status code: " + res.status throw "Invalid status code: " + res.status
@@ -260,26 +289,44 @@ class Baozi extends ComicSource {
let tags = document.querySelectorAll("div.tag-list > span").map(e => e.text.trim()) let tags = document.querySelectorAll("div.tag-list > span").map(e => e.text.trim())
tags = [...tags.filter(e => e !== "")] tags = [...tags.filter(e => e !== "")]
let updateTime = document.querySelector("div.supporting-text > div > span > em")?.text.trim().replace('(', '').replace(')', '') let updateTime = document.querySelector("div.supporting-text > div > span > em")?.text.trim().replace('(', '').replace(')', '')
if (!updateTime) {
const getLastChapterText = () => {
// 合并所有章节容器(处理可能存在多个列表的情况)
const containers = [
...document.querySelectorAll("#chapter-items, #chapters_other_list")
];
let allChapters = [];
containers.forEach(container => {
const chapters = container.querySelectorAll(".comics-chapters > a");
allChapters.push(...Array.from(chapters));
});
const lastChapter = allChapters[allChapters.length - 1];
return lastChapter?.querySelector("div > span")?.text.trim() || "暂无更新信息";
};
updateTime = getLastChapterText();
}
let description = document.querySelector("p.comics-detail__desc").text.trim() let description = document.querySelector("p.comics-detail__desc").text.trim()
let chapters = new Map() let chapters = new Map()
let i = 0 let i = 0
for(let c of document.querySelectorAll("div#chapter-items > div.comics-chapters > a > div > span")) { for (let c of document.querySelectorAll("div#chapter-items > div.comics-chapters > a > div > span")) {
chapters.set(i.toString(), c.text.trim()) chapters.set(i.toString(), c.text.trim())
i++ i++
} }
for(let c of document.querySelectorAll("div#chapters_other_list > div.comics-chapters > a > div > span")) { for (let c of document.querySelectorAll("div#chapters_other_list > div.comics-chapters > a > div > span")) {
chapters.set(i.toString(), c.text.trim()) chapters.set(i.toString(), c.text.trim())
i++ i++
} }
if (i === 0) { if (i === 0) {
for(let c of document.querySelectorAll("div.comics-chapters > a > div > span")) { // 将倒序的最新章节反转
chapters.set(i.toString(), c.text.trim()) const spans = Array.from(document.querySelectorAll("div.comics-chapters > a > div > span")).reverse();
i++ for (let c of spans) {
chapters.set(i.toString(), c.text.trim());
i++;
} }
} }
let recommend = [] let recommend = []
for(let c of document.querySelectorAll("div.recommend--item")) { for (let c of document.querySelectorAll("div.recommend--item")) {
if(c.querySelectorAll("div.tag-comic").length > 0) { if (c.querySelectorAll("div.tag-comic").length > 0) {
let title = c.querySelector("span").text.trim() let title = c.querySelector("span").text.trim()
let cover = c.querySelector("amp-img").attributes['src'] let cover = c.querySelector("amp-img").attributes['src']
let url = c.querySelector("a").attributes['href'] let url = c.querySelector("a").attributes['href']
@@ -305,18 +352,33 @@ class Baozi extends ComicSource {
recommend: recommend recommend: recommend
} }
}, },
// 获取章节图片
loadEp: async (comicId, epId) => { loadEp: async (comicId, epId) => {
let res = await Network.get(`https://www.czmanga.com/comic/chapter/${comicId}/0_${epId}.html`) const images = [];
if (res.status !== 200) { let currentPageUrl = `${this.baseUrl}/comic/chapter/${comicId}/0_${epId}.html`;
throw "Invalid status code: " + res.status let maxAttempts = 100;
while (maxAttempts > 0) {
const res = await Network.get(currentPageUrl);
if (res.status !== 200) break;
// 解析当前页图片
const doc = new HtmlDocument(res.body);
doc.querySelectorAll("ul.comic-contain > div > amp-img").forEach(img => {
const src = img?.attributes?.['src'];
if (typeof src === 'string') images.push(src);
});
// 查找下一页链接
const nextLink = doc.querySelector("a#next-chapter");
if (nextLink?.text?.match(/下一页|下一頁/)) {
currentPageUrl = nextLink.attributes['href'];
} else {
break;
} }
let document = new HtmlDocument(res.body) maxAttempts--;
let images = document.querySelectorAll("ul.comic-contain > div > amp-img").map(e => e.attributes['src']) }
console.log(images) // 代理后图片水印更少
return { return { images };
images: images
} }
},
} }
} }