Compare commits

..

4 Commits

Author SHA1 Message Date
六记
8bfb3fdf2e feat: 添加 API 地址自定义功能 (#110)
Co-authored-by: liuji <1183417329@qq.com>
2025-07-25 17:12:33 +08:00
Gandum2077
b8a7966aa7 [hitomi]Add custom tag suggestion handler (#109)
* fix bug in hitomi.js

* [hitomi]Add custom tag suggestion handler

* [hitomi]Change version to 1.1.0
2025-07-25 17:09:32 +08:00
LiuliFox
215e539def [shonen_jump_plus] remove special_content in seriesDetailEpisodeList and update User-Agent and rename to shonen_jump_plus (#111) 2025-07-25 17:07:18 +08:00
Zion
499180b6ea Update comick chapter api. (#112)
* 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

* Fixed some bugs and added some sorting methods

* Fixed some bugs and added some sorting methods

* Add a new resource from ykmh

* Remove invalid request

* fixed chapter api

* Update index.json

* Update index.json

* Update comick.js
2025-07-25 17:06:52 +08:00
5 changed files with 107 additions and 39 deletions

View File

@@ -1,7 +1,7 @@
class Comick extends ComicSource {
name = "comick"
key = "comick"
version = "1.1.0"
version = "1.1.1"
minAppVersion = "1.4.0"
// update url
url = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@main/comick.js"
@@ -340,6 +340,23 @@ class Comick extends ComicSource {
'拉脱维亚文': 'lv'
}
static getRandomHeaders() {
const userAgents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
];
return {
"User-Agent": userAgents[Math.floor(Math.random() * userAgents.length)],
"Accept": "application/json, text/plain, */*",
"Accept-Language": "en-US,en;q=0.9",
"Connection": "keep-alive"
};
}
transReformBookList(bookList, descriptionPrefix = "更新至:") {
return bookList.map(book => ({
id: `${book.relates?.slug || 'unknown'}//${book.relates?.title || '未知标题'}`,
@@ -482,12 +499,15 @@ class Comick extends ComicSource {
buildId: null,
loadInfo: async (id) => {
let headers = Comick.getRandomHeaders();
const [cId, cTitle] = id.split("//");
if (!cId) {
throw "ID error: ";
}
let res = await Network.get(`${this.baseUrl}/comic/${cId}`)
let res = await Network.get(`${this.baseUrl}/comic/${cId}`, { headers });
if (res.status !== 200) {
throw "Invalid status code: " + res.status
}
@@ -518,7 +538,13 @@ class Comick extends ComicSource {
const result = {};
let updateTime = "";
let i = 1;
for (const lang of langs) {
// 随机生成请求头
let headers = Comick.getRandomHeaders();
let first = langMap[lang];
if (first.vol == null && first.chap == null) {
const chapters = new Map();
@@ -533,9 +559,17 @@ class Comick extends ComicSource {
(first.chap != null
? `-chapter-${first.chap}`
: `-volume-${first.vol}`) +
`-${lang}.json`;
`-${lang}.json?slug=${id}&` +
(first.chap != null
? `chapter=${first.hid || 'unknown'}`
: `volume=${first.hid || 'unknown'}`)
+
(first.chap != null
? `-chapter-${first.chap}`
: `-volume-${first.vol}`) + `-${lang}`
;
const res = await Network.get(url);
const res = await Network.get(url, { headers });
if (res.status !== 200) {
throw `Invalid status code: ${res.status}`;
}

View File

@@ -995,9 +995,9 @@ class Hitomi extends ComicSource {
// unique id of the source
key = "hitomi";
version = "1.0.0";
version = "1.1.0";
minAppVersion = "1.4.0";
minAppVersion = "1.4.6";
// update url
url = "https://git.nyne.dev/nyne/venera-configs/raw/branch/main/hitomi.js";
@@ -1482,6 +1482,34 @@ class Hitomi extends ComicSource {
// enable tags suggestions
enableTagsSuggestions: true,
onTagSuggestionSelected: (namespace, tag) => {
let fixedNamespace = undefined;
switch (namespace) {
case "reclass":
fixedNamespace = "type";
break;
case "parody":
fixedNamespace = "series";
break;
case "other":
fixedNamespace = "tag";
break;
case "mixed":
fixedNamespace = "tag";
break;
case "temp":
fixedNamespace = "tag";
break;
case "cosplayer":
fixedNamespace = "tag";
break;
default:
fixedNamespace = namespace;
break;
}
// return the text to insert into search box
return `${fixedNamespace}:${tag.replaceAll(" ", "_")}`;
},
};
/// single comic related

View File

@@ -64,21 +64,21 @@
},
{
"name": "少年ジャンプ+",
"fileName": "shonenjumpplus.js",
"fileName": "shonen_jump_plus.js",
"key": "shonen_jump_plus",
"version": "1.0.1"
"version": "1.0.2"
},
{
"name": "hitomi.la",
"fileName": "hitomi.js",
"key": "hitomi",
"version": "1.0.0"
"version": "1.1.0"
},
{
"name": "comick",
"fileName": "comick.js",
"key": "comick",
"version": "1.1.0"
"version": "1.1.1"
},
{
"name": "优酷漫画",

View File

@@ -3,13 +3,13 @@ class Picacg extends ComicSource {
key = "picacg"
version = "1.0.3"
version = "1.0.4"
minAppVersion = "1.0.0"
url = "https://git.nyne.dev/nyne/venera-configs/raw/branch/main/picacg.js"
api = "https://picaapi.picacomic.com"
static defaultApiUrl = "https://picaapi.picacomic.com"
apiKey = "C69BAF41DA5ABD1FFEDC6D2FEA56B";
@@ -61,7 +61,7 @@ class Picacg extends ComicSource {
},
login: async (account, pwd) => {
let res = await Network.post(
`${this.api}/auth/sign-in`,
`${this.loadSetting('base_url')}/auth/sign-in`,
this.buildHeaders('POST', 'auth/sign-in'),
{
email: account,
@@ -111,13 +111,13 @@ class Picacg extends ComicSource {
throw 'Not logged in'
}
let res = await Network.get(
`${this.api}/comics/random`,
`${this.loadSetting('base_url')}/comics/random`,
this.buildHeaders('GET', 'comics/random', this.loadData('token'))
)
if(res.status === 401) {
await this.account.reLogin()
res = await Network.get(
`${this.api}/comics/random`,
`${this.loadSetting('base_url')}/comics/random`,
this.buildHeaders('GET', 'comics/random', this.loadData('token'))
)
}
@@ -142,13 +142,13 @@ class Picacg extends ComicSource {
throw 'Not logged in'
}
let res = await Network.get(
`${this.api}/comics?page=${page}&s=dd`,
`${this.loadSetting('base_url')}/comics?page=${page}&s=dd`,
this.buildHeaders('GET', `comics?page=${page}&s=dd`, this.loadData('token'))
)
if(res.status === 401) {
await this.account.reLogin()
res = await Network.get(
`${this.api}/comics?page=${page}&s=dd`,
`${this.loadSetting('base_url')}/comics?page=${page}&s=dd`,
this.buildHeaders('GET', `comics?page=${page}&s=dd`, this.loadData('token'))
)
}
@@ -229,13 +229,13 @@ class Picacg extends ComicSource {
load: async (category, param, options, page) => {
let type = param ?? 'c'
let res = await Network.get(
`${this.api}/comics?page=${page}&${type}=${encodeURIComponent(category)}&s=${options[0]}`,
`${this.loadSetting('base_url')}/comics?page=${page}&${type}=${encodeURIComponent(category)}&s=${options[0]}`,
this.buildHeaders('GET', `comics?page=${page}&${type}=${encodeURIComponent(category)}&s=${options[0]}`, this.loadData('token'))
)
if(res.status === 401) {
await this.account.reLogin()
res = await Network.get(
`${this.api}/comics?page=${page}&${type}=${encodeURIComponent(category)}&s=${options[0]}`,
`${this.loadSetting('base_url')}/comics?page=${page}&${type}=${encodeURIComponent(category)}&s=${options[0]}`,
this.buildHeaders('GET', `comics?page=${page}&${type}=${encodeURIComponent(category)}&s=${options[0]}`, this.loadData('token'))
)
}
@@ -271,13 +271,13 @@ class Picacg extends ComicSource {
],
load: async (option, page) => {
let res = await Network.get(
`${this.api}/comics/leaderboard?tt=${option}&ct=VC`,
`${this.loadSetting('base_url')}/comics/leaderboard?tt=${option}&ct=VC`,
this.buildHeaders('GET', `comics/leaderboard?tt=${option}&ct=VC`, this.loadData('token'))
)
if(res.status === 401) {
await this.account.reLogin()
res = await Network.get(
`${this.api}/comics/leaderboard?tt=${option}&ct=VC`,
`${this.loadSetting('base_url')}/comics/leaderboard?tt=${option}&ct=VC`,
this.buildHeaders('GET', `comics/leaderboard?tt=${option}&ct=VC`, this.loadData('token'))
)
}
@@ -301,7 +301,7 @@ class Picacg extends ComicSource {
search = {
load: async (keyword, options, page) => {
let res = await Network.post(
`${this.api}/comics/advanced-search?page=${page}`,
`${this.loadSetting('base_url')}/comics/advanced-search?page=${page}`,
this.buildHeaders('POST', `comics/advanced-search?page=${page}`, this.loadData('token')),
JSON.stringify({
keyword: keyword,
@@ -311,7 +311,7 @@ class Picacg extends ComicSource {
if(res.status === 401) {
await this.account.reLogin()
res = await Network.post(
`${this.api}/comics/advanced-search?page=${page}`,
`${this.loadSetting('base_url')}/comics/advanced-search?page=${page}`,
this.buildHeaders('POST', `comics/advanced-search?page=${page}`, this.loadData('token')),
JSON.stringify({
keyword: keyword,
@@ -351,7 +351,7 @@ class Picacg extends ComicSource {
/// 添加或者删除收藏
addOrDelFavorite: async (comicId, folderId, isAdding) => {
let res = await Network.post(
`${this.api}/comics/${comicId}/favourite`,
`${this.loadSetting('base_url')}/comics/${comicId}/favourite`,
this.buildHeaders('POST', `comics/${comicId}/favourite`, this.loadData('token')),
'{}'
)
@@ -367,7 +367,7 @@ class Picacg extends ComicSource {
loadComics: async (page, folder) => {
let sort = this.loadSetting('favoriteSort')
let res = await Network.get(
`${this.api}/users/favourite?page=${page}&s=${sort}`,
`${this.loadSetting('base_url')}/users/favourite?page=${page}&s=${sort}`,
this.buildHeaders('GET', `users/favourite?page=${page}&s=${sort}`, this.loadData('token'))
)
if(res.status === 401) {
@@ -394,7 +394,7 @@ class Picacg extends ComicSource {
loadInfo: async (id) => {
let infoLoader = async () => {
let res = await Network.get(
`${this.api}/comics/${id}`,
`${this.loadSetting('base_url')}/comics/${id}`,
this.buildHeaders('GET', `comics/${id}`, this.loadData('token'))
)
if (res.status !== 200) {
@@ -410,7 +410,7 @@ class Picacg extends ComicSource {
let allEps = [];
while (true) {
let res = await Network.get(
`${this.api}/comics/${id}/eps?page=${i}`,
`${this.loadSetting('base_url')}/comics/${id}/eps?page=${i}`,
this.buildHeaders('GET', `comics/${id}/eps?page=${i}`, this.loadData('token'))
);
if (res.status !== 200) {
@@ -432,7 +432,7 @@ class Picacg extends ComicSource {
}
let relatedLoader = async () => {
let res = await Network.get(
`${this.api}/comics/${id}/recommendation`,
`${this.loadSetting('base_url')}/comics/${id}/recommendation`,
this.buildHeaders('GET', `comics/${id}/recommendation`, this.loadData('token'))
)
if (res.status !== 200) {
@@ -491,7 +491,7 @@ class Picacg extends ComicSource {
let i = 1
while(true) {
let res = await Network.get(
`${this.api}/comics/${comicId}/order/${epId}/pages?page=${i}`,
`${this.loadSetting('base_url')}/comics/${comicId}/order/${epId}/pages?page=${i}`,
this.buildHeaders('GET', `comics/${comicId}/order/${epId}/pages?page=${i}`, this.loadData('token'))
)
if (res.status !== 200) {
@@ -512,7 +512,7 @@ class Picacg extends ComicSource {
},
likeComic: async (id, isLike) => {
var res = await Network.post(
`${this.api}/comics/${id}/like`,
`${this.loadSetting('base_url')}/comics/${id}/like`,
this.buildHeaders('POST', `comics/${id}/like`, this.loadData('token')),
{}
);
@@ -541,7 +541,7 @@ class Picacg extends ComicSource {
if(replyTo) {
let res = await Network.get(
`${this.api}/comments/${replyTo}/childrens?page=${page}`,
`${this.loadSetting('base_url')}/comments/${replyTo}/childrens?page=${page}`,
this.buildHeaders('GET', `comments/${replyTo}/childrens?page=${page}`, this.loadData('token'))
)
if (res.status !== 200) {
@@ -554,7 +554,7 @@ class Picacg extends ComicSource {
maxPage = data.data.comments.pages
} else {
let res = await Network.get(
`${this.api}/comics/${comicId}/comments?page=${page}`,
`${this.loadSetting('base_url')}/comics/${comicId}/comments?page=${page}`,
this.buildHeaders('GET', `comics/${comicId}/comments?page=${page}`, this.loadData('token'))
)
if (res.status !== 200) {
@@ -575,7 +575,7 @@ class Picacg extends ComicSource {
sendComment: async (comicId, subId, content, replyTo) => {
if(replyTo) {
let res = await Network.post(
`${this.api}/comments/${replyTo}`,
`${this.loadSetting('base_url')}/comments/${replyTo}`,
this.buildHeaders('POST', `/comments/${replyTo}`, this.loadData('token')),
JSON.stringify({
content: content
@@ -586,7 +586,7 @@ class Picacg extends ComicSource {
}
} else {
let res = await Network.post(
`${this.api}/comics/${comicId}/comments`,
`${this.loadSetting('base_url')}/comics/${comicId}/comments`,
this.buildHeaders('POST', `/comics/${comicId}/comments`, this.loadData('token')),
JSON.stringify({
content: content
@@ -600,7 +600,7 @@ class Picacg extends ComicSource {
},
likeComment: async (comicId, subId, commentId, isLike) => {
let res = await Network.post(
`${this.api}/comments/${commentId}/like`,
`${this.loadSetting('base_url')}/comments/${commentId}/like`,
this.buildHeaders('POST', `/comments/${commentId}/like`, this.loadData('token')),
'{}'
)
@@ -632,6 +632,12 @@ class Picacg extends ComicSource {
}
settings = {
base_url: {
title: "API地址(地址末尾不要添加斜杠)",
type: "input",
validator: null,
default: Picacg.defaultApiUrl,
},
'imageQuality': {
type: 'select',
title: 'Image quality',

View File

@@ -1,7 +1,7 @@
class ShonenJumpPlus extends ComicSource {
name = "少年ジャンプ+";
key = "shonen_jump_plus";
version = "1.0.1";
version = "1.0.2";
minAppVersion = "1.2.1";
url =
"https://git.nyne.dev/nyne/venera-configs/raw/branch/main/shonen_jump_plus.js";
@@ -16,7 +16,7 @@ class ShonenJumpPlus extends ComicSource {
"Origin": "https://shonenjumpplus.com",
"Referer": "https://shonenjumpplus.com/",
"X-Giga-Device-Id": this.deviceId,
"User-Agent": "ShonenJumpPlus-Android/4.0.19",
"User-Agent": "ShonenJumpPlus-Android/4.0.21",
};
}
@@ -368,7 +368,7 @@ const GraphQLQueries = {
"SeriesDetailEpisodeList":
`query SeriesDetailEpisodeList($id: String!, $episodeOffset: Int, $episodeFirst: Int, $episodeSort: ReadableProductSorting) {
series(databaseId: $id) {
episodes: readableProducts(types: [EPISODE,SPECIAL_CONTENT], first: $episodeFirst, offset: $episodeOffset, sort: $episodeSort) {
episodes: readableProducts(types: [EPISODE], first: $episodeFirst, offset: $episodeOffset, sort: $episodeSort) {
edges { node { databaseId title } }
}
}