Files
kodjodevf-mangayomi-extensions/javascript/manga/src/zh/copymanga.js
kodjomoustapha 18ec609307 fix
2024-05-09 17:48:53 +01:00

597 lines
17 KiB
JavaScript

const mangayomiSources = [{
"name": "拷贝漫画",
"lang": "zh",
"baseUrl": "https://www.mangacopy.com",
"apiUrl": "https://api.mangacopy.com",
"iconUrl": "https://hi77-overseas.mangafuna.xyz/static/free.ico",
"typeSource": "single",
"isManga": true,
"isNsfw": false,
"version": "0.0.2",
"dateFormat": "",
"dateFormatLocale": "",
"pkgPath": "manga/src/zh/copymanga.js"
}];
class DefaultExtension extends MProvider {
stringUTF8(text) {
var bytes = [];
for (var i = 0; i < text.length; i++) {
bytes.push(text.charCodeAt(i));
}
var charCodes = [];
var i = 0;
while (i < bytes.length) {
var byte1 = bytes[i];
var charCode;
if (byte1 < 0x80) {
charCode = byte1;
i += 1;
} else if (byte1 < 0xE0) {
var byte2 = bytes[i + 1];
charCode = ((byte1 & 0x1F) << 6) | (byte2 & 0x3F);
i += 2;
} else if (byte1 < 0xF0) {
var byte2 = bytes[i + 1];
var byte3 = bytes[i + 2];
charCode = ((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F);
i += 3;
} else {
var byte2 = bytes[i + 1];
var byte3 = bytes[i + 2];
var byte4 = bytes[i + 3];
charCode = ((byte1 & 0x07) << 18) | ((byte2 & 0x3F) << 12) | ((byte3 & 0x3F) << 6) | (byte4 & 0x3F);
i += 4;
}
charCodes.push(charCode);
}
return String.fromCharCode.apply(null, charCodes);
}
base64encode(str) {
const base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var out, i, len;
var c1, c2, c3;
len = str.length;
i = 0;
out = "";
while (i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if (i == len) {
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if (i == len) {
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
c3 = str.charCodeAt(i++);
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
out += base64EncodeChars.charAt(c3 & 0x3F);
}
return out;
}
decode(result) {
var iv = result.substring(0, 16);
result = result.replace(iv, "");
const bytes = [];
for (var i = 0; i < result.length; i = i + 2) {
bytes.push(parseInt(result.substr(i, 2), 16));
}
var charString = String.fromCharCode.apply(null, bytes);
const data = this.base64encode(charString);
const text = cryptoHandler(data, iv, "xxxmanga.woo.key", false);
return text;
}
getHeaders(url) {
return {
Referer: this.source.baseUrl
};
}
async getManga(url) {
const res = await new Client().get(this.source.apiUrl + url);
const datas = JSON.parse(res.body);
const manga = [];
for (const data of datas["results"]["list"]) {
manga.push({
name: this.stringUTF8(data["name"]),
imageUrl: data["cover"],
link: data["path_word"]
});
}
return {
list: manga,
hasNextPage: true
};
}
async getPopular(page) {
return await this.getManga(`/api/v3/comics?free_type=1&limit=16&offset=${(page-1)*16}&ordering=-popular&_update=true`);
}
async getLatestUpdates(page) {
return await this.getManga(`/api/v3/comics?free_type=1&limit=16&offset=${(page-1)*16}&ordering=-datetime_updated&_update=true`);
}
async search(query, page, filters) {
if (query != "") {
const res = await new Client().get(this.source.apiUrl + `/api/v3/search/comic?platform=1&q=${query}&limit=16&offset=${(page -1)*16}&q_type=&_update=true`, {
"webp": '1',
"region": '1',
"platform": '1',
"version": '2022.10.20',
"accept": 'application/json',
'content-encoding': 'gzip, compress, br'
});
const datas = JSON.parse(res.body)["results"]["list"];
const manga = [];
for (const data of datas) {
manga.push({
name: this.stringUTF8(data["name"]),
imageUrl: data["cover"],
link: data["path_word"]
});
}
return {
list: manga,
hasNextPage: true
};
}
var type, region, sort;
for (const filter of filters) {
if (filter["type"] == "type") {
type = filter["values"][filter["state"]]["value"];
}
if (filter["type"] == "region") {
region = filter["values"][filter["state"]]["value"];
}
if (filter["type"] == "sort") {
sort = filter["values"][filter["state"]]["value"];
}
}
return await this.getManga(`/api/v3/comics?free_type=1&limit=16&offset=${(page-1)*16}&theme=${type}&top=${region}&ordering=${sort}&_update=true`);
}
async getDetail(url) {
url = url.substringAfter("/comic/");
const res = await new Client().get(this.source.apiUrl + `/api/v3/comic2/${url}`);
const data = JSON.parse(res.body)["results"]["comic"];
const title = this.stringUTF8(data["name"]);
const cover = data["cover"];
const desc = this.stringUTF8(data["brief"]);
const author_ = [];
for (const a of data["author"]) {
author_.push(this.stringUTF8(a["name"]));
}
const author = author_.join(",");
const status = data["status"]["value"];
const genres = data["theme"].map(e => this.stringUTF8(e["name"]));
const chapters = [];
const res_ = await new Client().get(this.source.baseUrl + `/comicdetail/${url}/chapters`, {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
});
const ch_text = JSON.parse(res_.body)["results"];
const chapter_datas = JSON.parse(this.decode(ch_text));
for (const ch of chapter_datas["groups"]["default"]["chapters"]) {
chapters.push({
name: ch["name"],
url: url + "|" + ch["id"]
});
}
chapters.reverse();
return {
name: title,
imageUrl: cover,
description: desc,
author: author,
status: status,
genre: genres,
episodes: chapters,
link: "/comic/" + url
}
}
async getPageList(url) {
const urls = url.split("|");
const res = await new Client().get(this.source.baseUrl + `/comic/${urls[0]}/chapter/${urls[1]}`, {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
});
const img_text = res.body.match(/contentKey="(.*)"/)[1];
const results = JSON.parse(this.decode(img_text));
return results.map(e => e["url"]);
}
getFilterList() {
return [{
type: "type",
name: "分类",
type_name: "SelectFilter",
values: [{
type_name: "SelectOption",
name: "全部",
value: ""
},
{
type_name: "SelectOption",
name: "愛情",
value: "aiqing"
},
{
type_name: "SelectOption",
name: "歡樂向",
value: "huanlexiang"
},
{
type_name: "SelectOption",
name: "冒险",
value: "maoxian"
},
{
type_name: "SelectOption",
name: "奇幻",
value: "qihuan"
},
{
type_name: "SelectOption",
name: "百合",
value: "baihe"
},
{
type_name: "SelectOption",
name: "校园",
value: "xiaoyuan"
},
{
type_name: "SelectOption",
name: "科幻",
value: "kehuan"
},
{
type_name: "SelectOption",
name: "東方",
value: "dongfang"
},
{
type_name: "SelectOption",
name: "生活",
value: "shenghuo"
},
{
type_name: "SelectOption",
name: "轻小说",
value: "qingxiaoshuo"
},
{
type_name: "SelectOption",
name: "格鬥",
value: "gedou"
},
{
type_name: "SelectOption",
name: "耽美",
value: "danmei"
},
{
type_name: "SelectOption",
name: "悬疑",
value: "xuanyi"
},
{
type_name: "SelectOption",
name: "神鬼",
value: "shengui"
},
{
type_name: "SelectOption",
name: "其他",
value: "qita"
},
{
type_name: "SelectOption",
name: "职场",
value: "zhichang"
},
{
type_name: "SelectOption",
name: "萌系",
value: "mengxi"
},
{
type_name: "SelectOption",
name: "治愈",
value: "zhiyu"
},
{
type_name: "SelectOption",
name: "長條",
value: "changtiao"
},
{
type_name: "SelectOption",
name: "四格",
value: "sige"
},
{
type_name: "SelectOption",
name: "舰娘",
value: "jianniang"
},
{
type_name: "SelectOption",
name: "节操",
value: "jiecao"
},
{
type_name: "SelectOption",
name: "TL",
value: "teenslove"
},
{
type_name: "SelectOption",
name: "竞技",
value: "jingji"
},
{
type_name: "SelectOption",
name: "搞笑",
value: "gaoxiao"
},
{
type_name: "SelectOption",
name: "伪娘",
value: "weiniang"
},
{
type_name: "SelectOption",
name: "热血",
value: "rexue"
},
{
type_name: "SelectOption",
name: "後宮",
value: "hougong"
},
{
type_name: "SelectOption",
name: "美食",
value: "meishi"
},
{
type_name: "SelectOption",
name: "性转换",
value: "xingzhuanhuan"
},
{
type_name: "SelectOption",
name: "侦探",
value: "zhentan"
},
{
type_name: "SelectOption",
name: "励志",
value: "lizhi"
},
{
type_name: "SelectOption",
name: "AA",
value: "aa"
},
{
type_name: "SelectOption",
name: "彩色",
value: "COLOR"
},
{
type_name: "SelectOption",
name: "音乐舞蹈",
value: "yinyuewudao"
},
{
type_name: "SelectOption",
name: "异世界",
value: "yishijie"
},
{
type_name: "SelectOption",
name: "战争",
value: "zhanzheng"
},
{
type_name: "SelectOption",
name: "历史",
value: "lishi"
},
{
type_name: "SelectOption",
name: "机战",
value: "jizhan"
},
{
type_name: "SelectOption",
name: "惊悚",
value: "jingsong"
},
{
type_name: "SelectOption",
name: "C99",
value: "comiket99"
},
{
type_name: "SelectOption",
name: "恐怖",
value: "恐怖"
},
{
type_name: "SelectOption",
name: "都市",
value: "dushi"
},
{
type_name: "SelectOption",
name: "C97",
value: "comiket97"
},
{
type_name: "SelectOption",
name: "穿越",
value: "chuanyue"
},
{
type_name: "SelectOption",
name: "C96",
value: "comiket96"
},
{
type_name: "SelectOption",
name: "重生",
value: "chongsheng"
},
{
type_name: "SelectOption",
name: "魔幻",
value: "mohuan"
},
{
type_name: "SelectOption",
name: "宅系",
value: "zhaixi"
},
{
type_name: "SelectOption",
name: "武侠",
value: "wuxia"
},
{
type_name: "SelectOption",
name: "C98",
value: "C98"
},
{
type_name: "SelectOption",
name: "生存",
value: "shengcun"
},
{
type_name: "SelectOption",
name: "C95",
value: "comiket95"
},
{
type_name: "SelectOption",
name: "FATE",
value: "fate"
},
{
type_name: "SelectOption",
name: "無修正",
value: "Uncensored"
},
{
type_name: "SelectOption",
name: "转生",
value: "zhuansheng"
},
{
type_name: "SelectOption",
name: "LoveLive",
value: "loveLive"
},
{
type_name: "SelectOption",
name: "男同",
value: "nantong"
},
{
type_name: "SelectOption",
name: "仙侠",
value: "xianxia"
},
{
type_name: "SelectOption",
name: "玄幻",
value: "xuanhuan"
},
{
type_name: "SelectOption",
name: "真人",
value: "zhenren"
},
],
},
{
type: "region",
name: "地区",
type_name: "SelectFilter",
values: [{
type_name: "SelectOption",
name: "全部",
value: ""
},
{
type_name: "SelectOption",
name: "日本",
value: "japan"
},
{
type_name: "SelectOption",
name: "韩国",
value: "korea"
},
{
type_name: "SelectOption",
name: "欧美",
value: "west"
},
{
type_name: "SelectOption",
name: "完结",
value: "finish"
},
],
},
{
type: "sort",
name: "排序",
type_name: "SelectFilter",
values: [{
type_name: "SelectOption",
name: "更新时间⬇️",
value: "-datetime_updated"
},
{
type_name: "SelectOption",
name: "更新时间⬆️",
value: "datetime_updated"
},
{
type_name: "SelectOption",
name: "热度⬇️",
value: "-popular"
},
{
type_name: "SelectOption",
name: "热度⬆️",
value: "popular"
},
],
},
];
}
getSourcePreferences() {
throw new Error("getSourcePreferences not implemented");
}
}