mirror of
https://github.com/venera-app/venera-configs.git
synced 2025-09-27 00:27:23 +00:00
Compare commits
2 Commits
7dce35fd5a
...
6e52854782
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6e52854782 | ||
![]() |
b5ba37794a |
@@ -46,7 +46,7 @@
|
||||
"name": "禁漫天堂",
|
||||
"fileName": "jm.js",
|
||||
"key": "jm",
|
||||
"version": "1.1.4",
|
||||
"version": "1.2.0",
|
||||
"description": "禁漫天堂漫畫源, 不能使用時請嘗試切換分流"
|
||||
},
|
||||
{
|
||||
@@ -103,5 +103,10 @@
|
||||
"fileName": "ykmh.js",
|
||||
"key": "ykmh",
|
||||
"version": "1.0.0"
|
||||
},{
|
||||
"name": "漫蛙吧",
|
||||
"fileName": "manwaba.js",
|
||||
"key": "manwaba",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
]
|
||||
|
117
jm.js
117
jm.js
@@ -7,25 +7,31 @@ class JM extends ComicSource {
|
||||
// unique id of the source
|
||||
key = "jm"
|
||||
|
||||
version = "1.1.4"
|
||||
version = "1.2.0"
|
||||
|
||||
minAppVersion = "1.2.5"
|
||||
|
||||
static jmVersion = "2.0.1"
|
||||
|
||||
static jmPkgName = "com.example.app"
|
||||
|
||||
// update url
|
||||
url = "https://git.nyne.dev/nyne/venera-configs/raw/branch/main/jm.js"
|
||||
|
||||
static apiDomains = [
|
||||
"www.jmapiproxyxxx.vip",
|
||||
"www.cdnblackmyth.club",
|
||||
"www.cdnmhws.cc",
|
||||
"www.cdnmhwscc.org"
|
||||
"www.cdnaspa.vip",
|
||||
"www.cdnaspa.club",
|
||||
"www.cdnplaystation6.vip",
|
||||
"www.cdnplaystation6.cc"
|
||||
];
|
||||
|
||||
static imageUrl = "https://cdn-msp.jmapinodeudzn.net"
|
||||
|
||||
static apiUa = "Mozilla/5.0 (Linux; Android 10; K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.0.0 Mobile Safari/537.36"
|
||||
static ua = "Mozilla/5.0 (Linux; Android 10; K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.0.0 Mobile Safari/537.36"
|
||||
|
||||
static imgUa = "okhttp/3.12.1"
|
||||
get ua() {
|
||||
return JM.ua;
|
||||
}
|
||||
|
||||
get baseUrl() {
|
||||
let index = parseInt(this.loadSetting('apiDomain')) - 1
|
||||
@@ -48,12 +54,49 @@ class JM extends ComicSource {
|
||||
return /^\d+$/.test(str)
|
||||
}
|
||||
|
||||
get apiUa() {
|
||||
return JM.apiUa;
|
||||
get baseHeaders() {
|
||||
return {
|
||||
"Accept": "*/*",
|
||||
"Accept-Encoding": "gzip, deflate, br, zstd",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
|
||||
"Connection": "keep-alive",
|
||||
"Origin": "https://localhost",
|
||||
"Referer": "https://localhost/",
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
"Sec-Fetch-Site": "cross-site",
|
||||
"X-Requested-With": JM.jmPkgName,
|
||||
}
|
||||
}
|
||||
|
||||
get imgUa() {
|
||||
return JM.imgUa;
|
||||
getApiHeaders(time) {
|
||||
const jmAuthKey = "18comicAPPContent"
|
||||
let token = Convert.md5(Convert.encodeUtf8(`${time}${jmAuthKey}`))
|
||||
|
||||
return {
|
||||
...this.baseHeaders,
|
||||
"Authorization": "Bearer",
|
||||
"Sec-Fetch-Storage-Access": "active",
|
||||
"token": Convert.hexEncode(token),
|
||||
"tokenparam": `${time},${JM.jmVersion}`,
|
||||
"User-Agent": this.ua,
|
||||
}
|
||||
}
|
||||
|
||||
getImgHeaders() {
|
||||
return {
|
||||
"Accept": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
|
||||
"Accept-Encoding": "gzip, deflate, br, zstd",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
|
||||
"Connection": "keep-alive",
|
||||
"Referer": "https://localhost/",
|
||||
"Sec-Fetch-Dest": "image",
|
||||
"Sec-Fetch-Mode": "no-cors",
|
||||
"Sec-Fetch-Site": "cross-site",
|
||||
"Sec-Fetch-Storage-Access": "active",
|
||||
"User-Agent": this.ua,
|
||||
"X-Requested-With": JM.jmPkgName,
|
||||
}
|
||||
}
|
||||
|
||||
getCoverUrl(id) {
|
||||
@@ -78,32 +121,33 @@ class JM extends ComicSource {
|
||||
* @param showConfirmDialog {boolean}
|
||||
*/
|
||||
async refreshApiDomains(showConfirmDialog) {
|
||||
let today = new Date();
|
||||
let url = "https://jmappc01-1308024008.cos.ap-guangzhou.myqcloud.com/server-2024.txt"
|
||||
let url = "https://jmapp03-1308024008.cos.ap-jakarta.myqcloud.com/server-2024.txt"
|
||||
let domainSecret = "diosfjckwpqpdfjkvnqQjsik"
|
||||
let title = ""
|
||||
let message = ""
|
||||
let jm3_Server = []
|
||||
let domains = []
|
||||
let res = await fetch(
|
||||
`${url}?time=${today.getFullYear()}${today.getMonth() + 1}${today.getDate()}`,
|
||||
{headers: {"User-Agent": this.imgUa}}
|
||||
url,
|
||||
{headers: this.baseHeaders}
|
||||
)
|
||||
if (res.status === 200) {
|
||||
let data = this.convertData(await res.text(), domainSecret)
|
||||
let json = JSON.parse(data)
|
||||
if (json["Server"]) {
|
||||
if (json["jm3_Server"]) {
|
||||
title = "Update Success"
|
||||
message = "New domains:\n\n"
|
||||
domains = json["Server"]
|
||||
message = "\n"
|
||||
jm3_Server = json["jm3_Server"]
|
||||
}
|
||||
}
|
||||
if (domains.length === 0) {
|
||||
if (jm3_Server.length === 0) {
|
||||
title = "Update Failed"
|
||||
message = `Using built-in domains:\n\n`
|
||||
domains = JM.apiDomains
|
||||
}
|
||||
for (let i = 0; i < domains.length; i++) {
|
||||
message = message + `Stream ${i + 1}: ${domains[i]}\n`
|
||||
for (let [domain, index] of jm3_Server) {
|
||||
message = message + `${index}: ${domain}\n`
|
||||
domains.push(domain)
|
||||
}
|
||||
if (showConfirmDialog) {
|
||||
UI.showDialog(
|
||||
@@ -135,7 +179,7 @@ class JM extends ComicSource {
|
||||
async refreshImgUrl(showMessage) {
|
||||
let index = this.loadSetting('imageStream')
|
||||
let res = await this.get(
|
||||
`${this.baseUrl}/setting?app_img_shunt=${index}`
|
||||
`${this.baseUrl}/setting?app_img_shunt=${index}?express=`
|
||||
)
|
||||
let setting = JSON.parse(res)
|
||||
if (setting["img_host"]) {
|
||||
@@ -174,19 +218,6 @@ class JM extends ComicSource {
|
||||
})
|
||||
}
|
||||
|
||||
getHeaders(time) {
|
||||
const jmVersion = "1.7.6"
|
||||
const jmAuthKey = "18comicAPPContent"
|
||||
let token = Convert.md5(Convert.encodeUtf8(`${time}${jmAuthKey}`))
|
||||
|
||||
return {
|
||||
"token": Convert.hexEncode(token),
|
||||
"tokenparam": `${time},${jmVersion}`,
|
||||
"Accept-Encoding": "gzip",
|
||||
"User-Agent": this.apiUa,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param input {string}
|
||||
@@ -213,7 +244,7 @@ class JM extends ComicSource {
|
||||
async get(url) {
|
||||
let time = Math.floor(Date.now() / 1000)
|
||||
let kJmSecret = "185Hcomic3PAPP7R"
|
||||
let res = await Network.get(url, this.getHeaders(time))
|
||||
let res = await Network.get(url, this.getApiHeaders(time))
|
||||
if(res.status !== 200) {
|
||||
if(res.status === 401) {
|
||||
let json = JSON.parse(res.body)
|
||||
@@ -237,7 +268,7 @@ class JM extends ComicSource {
|
||||
let time = Math.floor(Date.now() / 1000)
|
||||
let kJmSecret = "185Hcomic3PAPP7R"
|
||||
let res = await Network.post(url, {
|
||||
...this.getHeaders(time),
|
||||
...this.getApiHeaders(time),
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}, body)
|
||||
if(res.status !== 200) {
|
||||
@@ -634,7 +665,7 @@ class JM extends ComicSource {
|
||||
if (id.startsWith('jm')) {
|
||||
id = id.substring(2)
|
||||
}
|
||||
let res = await this.get(`${this.baseUrl}/album?comicName=&id=${id}`);
|
||||
let res = await this.get(`${this.baseUrl}/album?id=${id}`);
|
||||
let data = JSON.parse(res)
|
||||
let author = data.author ?? []
|
||||
let chapters = new Map()
|
||||
@@ -735,10 +766,7 @@ class JM extends ComicSource {
|
||||
return {}
|
||||
}
|
||||
return {
|
||||
headers: {
|
||||
"Accept-Encoding": "gzip",
|
||||
"User-Agent": this.imgUa,
|
||||
},
|
||||
headers: this.getImgHeaders(),
|
||||
modifyImage: `
|
||||
let modifyImage = (image) => {
|
||||
const num = ${num}
|
||||
@@ -773,10 +801,7 @@ class JM extends ComicSource {
|
||||
*/
|
||||
onThumbnailLoad: (url) => {
|
||||
return {
|
||||
headers: {
|
||||
"Accept-Encoding": "gzip",
|
||||
"User-Agent": this.imgUa,
|
||||
}
|
||||
headers: this.getImgHeaders()
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
387
manwaba.js
Normal file
387
manwaba.js
Normal file
@@ -0,0 +1,387 @@
|
||||
/** @type {import('./_venera_.js')} */
|
||||
class ManWaBa 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 = "manwaba";
|
||||
|
||||
version = "1.0.0";
|
||||
|
||||
minAppVersion = "1.4.0";
|
||||
|
||||
// update url
|
||||
url = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@main/manwaba.js";
|
||||
|
||||
api = "https://www.manwaba.com/api/v1";
|
||||
|
||||
init() {
|
||||
/**
|
||||
* Sends an HTTP request.
|
||||
* @param {string} url - The URL to send the request to.
|
||||
* @param {string} method - The HTTP method (e.g., GET, POST, PUT, PATCH, DELETE).
|
||||
* @param {Object} params - The query parameters to include in the request.
|
||||
* @param {Object} headers - The headers to include in the request.
|
||||
* @param {string} payload - The payload to include in the request.
|
||||
* @returns {Promise<Object>} The response from the request.
|
||||
*/
|
||||
this.fetchJson = async (
|
||||
url,
|
||||
{ method = "GET", params, headers, payload }
|
||||
) => {
|
||||
if (params) {
|
||||
let params_str = Object.keys(params)
|
||||
.map((key) => `${key}=${params[key]}`)
|
||||
.join("&");
|
||||
url += `?${params_str}`;
|
||||
}
|
||||
let res = await Network.sendRequest(method, url, headers, payload);
|
||||
if (res.status !== 200) {
|
||||
throw `Invalid status code: ${res.status}, body: ${res.body}`;
|
||||
}
|
||||
let json = JSON.parse(res.body);
|
||||
return json;
|
||||
};
|
||||
this.logger = {
|
||||
error: (msg) => {
|
||||
log("error", this.name, msg);
|
||||
},
|
||||
info: (msg) => {
|
||||
log("info", this.name, msg);
|
||||
},
|
||||
warn: (msg) => {
|
||||
log("warning", this.name, msg);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// explore page list
|
||||
explore = [
|
||||
{
|
||||
// title of the page.
|
||||
// title is used to identify the page, it should be unique
|
||||
title: this.name,
|
||||
|
||||
/// multiPartPage or multiPageComicList or mixed
|
||||
type: "singlePageWithMultiPart",
|
||||
|
||||
/**
|
||||
* load function
|
||||
* @param page {number | null} - page number, null for `singlePageWithMultiPart` type
|
||||
* @returns {{}}
|
||||
* - for `multiPartPage` type, return [{title: string, comics: Comic[], viewMore: PageJumpTarget}]
|
||||
* - for `multiPageComicList` type, for each page(1-based), return {comics: Comic[], maxPage: number}
|
||||
* - for `mixed` type, use param `page` as index. for each index(0-based), return {data: [], maxPage: number?}, data is an array contains Comic[] or {title: string, comics: Comic[], viewMore: string?}
|
||||
*/
|
||||
load: async (page) => {
|
||||
let params = {
|
||||
page: 1,
|
||||
pageSize: 6,
|
||||
type: "",
|
||||
flag: false,
|
||||
};
|
||||
const url = `${this.api}/json/home`;
|
||||
const data = await this.fetchJson(url, { params }).then(
|
||||
(res) => res.data
|
||||
);
|
||||
let magnaList = {
|
||||
热门: data.comicList,
|
||||
古风: data.gufengList,
|
||||
玄幻: data.xuanhuanList,
|
||||
校园: data.xiaoyuanList,
|
||||
};
|
||||
function parseComic(comic) {
|
||||
return new Comic({
|
||||
id: comic.id.toString(),
|
||||
title: comic.title,
|
||||
subTitle: comic.author,
|
||||
cover: comic.pic,
|
||||
tags: comic.tags.split(","),
|
||||
});
|
||||
}
|
||||
let result = {};
|
||||
for (let key in magnaList) {
|
||||
result[key] = magnaList[key].map(parseComic);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// categories
|
||||
category = {
|
||||
/// title of the category page, used to identify the page, it should be unique
|
||||
title: this.name,
|
||||
parts: [
|
||||
{
|
||||
// title of the part
|
||||
name: "类型",
|
||||
|
||||
// fixed or random or dynamic
|
||||
// if random, need to provide `randomNumber` field, which indicates the number of comics to display at the same time
|
||||
// if dynamic, need to provide `loader` field, which indicates the function to load comics
|
||||
type: "fixed",
|
||||
|
||||
// Remove this if type is dynamic
|
||||
categories: [
|
||||
"全部",
|
||||
"热血",
|
||||
"玄幻",
|
||||
"恋爱",
|
||||
"冒险",
|
||||
"古风",
|
||||
"都市",
|
||||
"穿越",
|
||||
"奇幻",
|
||||
"其他",
|
||||
"搞笑",
|
||||
"少男",
|
||||
"战斗",
|
||||
"重生",
|
||||
"逆袭",
|
||||
"爆笑",
|
||||
"少年",
|
||||
"后宫",
|
||||
"系统",
|
||||
"BL",
|
||||
"韩漫",
|
||||
"完整版",
|
||||
"19r",
|
||||
"台版",
|
||||
],
|
||||
|
||||
itemType: "category",
|
||||
categoryParams: [
|
||||
"",
|
||||
"热血",
|
||||
"玄幻",
|
||||
"恋爱",
|
||||
"冒险",
|
||||
"古风",
|
||||
"都市",
|
||||
"穿越",
|
||||
"奇幻",
|
||||
"其他",
|
||||
"搞笑",
|
||||
"少男",
|
||||
"战斗",
|
||||
"重生",
|
||||
"逆袭",
|
||||
"爆笑",
|
||||
"少年",
|
||||
"后宫",
|
||||
"系统",
|
||||
"BL",
|
||||
"韩漫",
|
||||
"完整版",
|
||||
"19r",
|
||||
"台版",
|
||||
],
|
||||
},
|
||||
],
|
||||
// enable ranking page
|
||||
enableRankingPage: false,
|
||||
};
|
||||
|
||||
/// category comic loading related
|
||||
categoryComics = {
|
||||
/**
|
||||
* load comics of a category
|
||||
* @param category {string} - category name
|
||||
* @param param {string?} - category param
|
||||
* @param options {string[]} - options from optionList
|
||||
* @param page {number} - page number
|
||||
* @returns {Promise<{comics: Comic[], maxPage: number}>}
|
||||
*/
|
||||
load: async (category, param, options, page) => {
|
||||
let url = `${this.api}/json/cate`;
|
||||
let payload = JSON.stringify({
|
||||
page: {
|
||||
page: page,
|
||||
pageSize: 10,
|
||||
},
|
||||
category: "comic",
|
||||
sort: parseInt(options[2]),
|
||||
comic: {
|
||||
status: parseInt(options[0] == "2" ? -1 : options[0]),
|
||||
day: parseInt(options[1]),
|
||||
tag: param,
|
||||
},
|
||||
video: {
|
||||
year: 0,
|
||||
typeId: 0,
|
||||
typeId1: 0,
|
||||
area: "",
|
||||
lang: "",
|
||||
status: -1,
|
||||
day: 0,
|
||||
},
|
||||
novel: {
|
||||
status: -1,
|
||||
day: 0,
|
||||
sortId: 0,
|
||||
},
|
||||
});
|
||||
|
||||
let data = await this.fetchJson(url, {
|
||||
method: "POST",
|
||||
payload,
|
||||
}).then((res) => res.data);
|
||||
|
||||
function parseComic(comic) {
|
||||
return new Comic({
|
||||
id: comic.url.split("/").pop(),
|
||||
title: comic.title,
|
||||
subTitle: comic.author,
|
||||
cover: comic.pic,
|
||||
tags: comic.tags.split(","),
|
||||
description: comic.intro,
|
||||
status: comic.status == 0 ? "连载中" : "已完结",
|
||||
});
|
||||
}
|
||||
return {
|
||||
comics: data.map(parseComic),
|
||||
maxPage: 100,
|
||||
};
|
||||
},
|
||||
// provide options for category comic loading
|
||||
optionList: [
|
||||
{
|
||||
options: ["2-全部", "0-连载中", "1-已完结"],
|
||||
},
|
||||
{
|
||||
options: [
|
||||
"0-全部",
|
||||
"1-周一",
|
||||
"2-周二",
|
||||
"3-周三",
|
||||
"4-周四",
|
||||
"5-周五",
|
||||
"6-周六",
|
||||
"7-周日",
|
||||
],
|
||||
},
|
||||
{
|
||||
options: ["0-更新", "1-新作", "2-畅销", "3-热门", "4-收藏"],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/// search related
|
||||
search = {
|
||||
/**
|
||||
* load search result
|
||||
* @param keyword {string}
|
||||
* @param options {string[]} - options from optionList
|
||||
* @param page {number}
|
||||
* @returns {Promise<{comics: Comic[], maxPage: number}>}
|
||||
*/
|
||||
load: async (keyword, options, page) => {
|
||||
const pageSize = 20;
|
||||
let url = `${this.api}/json/search`;
|
||||
let params = {
|
||||
keyword,
|
||||
type: "mh",
|
||||
page,
|
||||
pageSize,
|
||||
};
|
||||
let data = await this.fetchJson(url, { params }).then((res) => res.data);
|
||||
let total = data.total;
|
||||
let comics = data.list.map((item) => {
|
||||
return new Comic({
|
||||
id: item.id.toString(),
|
||||
title: item.title,
|
||||
subTitle: item.author,
|
||||
cover: item.cover,
|
||||
tags: item.tags.split(","),
|
||||
description: item.description,
|
||||
status: item.status == 0 ? "连载中" : "已完结",
|
||||
});
|
||||
});
|
||||
let maxPage = Math.ceil(total / pageSize);
|
||||
return {
|
||||
comics,
|
||||
maxPage,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
/// single comic related
|
||||
comic = {
|
||||
/**
|
||||
* load comic info
|
||||
* @param id {string}
|
||||
* @returns {Promise<ComicDetails>}s
|
||||
*/
|
||||
loadInfo: async (id) => {
|
||||
let url = `${this.api}/json/comic/${id}`;
|
||||
let data = await this.fetchJson(url, { payload: undefined }).then(
|
||||
(res) => res.data
|
||||
);
|
||||
this.logger.warn(`loadInfo: ${data}`);
|
||||
let chapterId = data.id;
|
||||
let chapterApi = `${this.api}/json/comic/chapter`;
|
||||
let params = {
|
||||
comicId: chapterId,
|
||||
page: 1,
|
||||
pageSize: 1,
|
||||
};
|
||||
let pageRes = await this.fetchJson(chapterApi, { params });
|
||||
let total = pageRes.pagination.total;
|
||||
|
||||
let chapterRes = await this.fetchJson(chapterApi, {
|
||||
params: {
|
||||
...params,
|
||||
pageSize: total,
|
||||
},
|
||||
});
|
||||
let chapterList = chapterRes.data;
|
||||
let chapters = new Map();
|
||||
chapterList.forEach((item) => {
|
||||
chapters.set(item.id.toString(), item.title.toString());
|
||||
});
|
||||
|
||||
return new ComicDetails({
|
||||
title: data.title.toString(),
|
||||
subTitle: data.author.toString(),
|
||||
cover: data.cover,
|
||||
tags: {
|
||||
类型: data.tags.split(","),
|
||||
状态: data.status == 0 ? "连载中" : "已完结",
|
||||
},
|
||||
chapters,
|
||||
description: data.intro,
|
||||
updateTime: new Date(data.editTime * 1000).toLocaleDateString(),
|
||||
});
|
||||
},
|
||||
/**
|
||||
* load images of a chapter
|
||||
* @param comicId {string}
|
||||
* @param epId {string?}
|
||||
* @returns {Promise<{images: string[]}>}
|
||||
*/
|
||||
loadEp: async (comicId, epId) => {
|
||||
let imgApi = `${this.api}/comic/image/${epId}`;
|
||||
let params = {
|
||||
page: 1,
|
||||
pageSize: 1,
|
||||
imageSource: "https://tu.mhttu.cc",
|
||||
};
|
||||
let pageNum = await this.fetchJson(imgApi, {
|
||||
params,
|
||||
}).then((res) => res.data.pagination.total);
|
||||
let imageRes = await this.fetchJson(imgApi, {
|
||||
params: {
|
||||
...params,
|
||||
pageSize: pageNum,
|
||||
},
|
||||
}).then((res) => res.data.images);
|
||||
let images = imageRes.map((item) => item.url);
|
||||
return {
|
||||
images,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user