mirror of
https://github.com/venera-app/venera-configs.git
synced 2025-09-27 08:27:24 +00:00
jm: Add account, favorites, send comments.
This commit is contained in:
@@ -45,6 +45,6 @@
|
|||||||
"name": "禁漫天堂",
|
"name": "禁漫天堂",
|
||||||
"fileName": "jm.js",
|
"fileName": "jm.js",
|
||||||
"key": "jm",
|
"key": "jm",
|
||||||
"version": "1.0.3"
|
"version": "1.1.0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
189
jm.js
189
jm.js
@@ -7,9 +7,9 @@ class JM extends ComicSource {
|
|||||||
// unique id of the source
|
// unique id of the source
|
||||||
key = "jm"
|
key = "jm"
|
||||||
|
|
||||||
version = "1.0.3"
|
version = "1.1.0"
|
||||||
|
|
||||||
minAppVersion = "1.2.1"
|
minAppVersion = "1.2.5"
|
||||||
|
|
||||||
// update url
|
// update url
|
||||||
url = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@latest/jm.js"
|
url = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@latest/jm.js"
|
||||||
@@ -38,7 +38,7 @@ class JM extends ComicSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
overwriteApiUrls(domains) {
|
overwriteApiUrls(domains) {
|
||||||
if (domains.length != 0) JM.apiDomains = domains
|
if (domains.length !== 0) JM.apiDomains = domains
|
||||||
}
|
}
|
||||||
|
|
||||||
isNum(str) {
|
isNum(str) {
|
||||||
@@ -90,7 +90,7 @@ class JM extends ComicSource {
|
|||||||
`${url}?time=${today.getFullYear()}${today.getMonth() + 1}${today.getDate()}`,
|
`${url}?time=${today.getFullYear()}${today.getMonth() + 1}${today.getDate()}`,
|
||||||
{headers: {"User-Agent": this.imgUa}}
|
{headers: {"User-Agent": this.imgUa}}
|
||||||
)
|
)
|
||||||
if (res.status == 200) {
|
if (res.status === 200) {
|
||||||
let data = this.convertData(await res.text(), domainSecret)
|
let data = this.convertData(await res.text(), domainSecret)
|
||||||
let json = JSON.parse(data)
|
let json = JSON.parse(data)
|
||||||
if (json["Server"]) {
|
if (json["Server"]) {
|
||||||
@@ -99,7 +99,7 @@ class JM extends ComicSource {
|
|||||||
domains = json["Server"]
|
domains = json["Server"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (domains.length == 0) {
|
if (domains.length === 0) {
|
||||||
title = "Update Failed"
|
title = "Update Failed"
|
||||||
message = `Using built-in domains:\n\n`
|
message = `Using built-in domains:\n\n`
|
||||||
domains = JM.apiDomains
|
domains = JM.apiDomains
|
||||||
@@ -113,7 +113,7 @@ class JM extends ComicSource {
|
|||||||
message,
|
message,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: "Cancle",
|
text: "Cancel",
|
||||||
callback: () => {}
|
callback: () => {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -171,7 +171,7 @@ class JM extends ComicSource {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param input {string}
|
* @param input {string}
|
||||||
* @param time {number}
|
* @param secret {string}
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
convertData(input, secret) {
|
convertData(input, secret) {
|
||||||
@@ -214,6 +214,62 @@ class JM extends ComicSource {
|
|||||||
return this.convertData(data, `${time}${kJmSecret}`)
|
return this.convertData(data, `${time}${kJmSecret}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async post(url, body) {
|
||||||
|
let time = Math.floor(Date.now() / 1000)
|
||||||
|
let kJmSecret = "185Hcomic3PAPP7R"
|
||||||
|
let res = await Network.post(url, {
|
||||||
|
...this.getHeaders(time),
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
}, body)
|
||||||
|
if(res.status !== 200) {
|
||||||
|
if(res.status === 401) {
|
||||||
|
let json = JSON.parse(res.body)
|
||||||
|
let message = json.errorMsg
|
||||||
|
if(message === "請先登入會員" && this.isLogged) {
|
||||||
|
throw 'Login expired'
|
||||||
|
}
|
||||||
|
throw message ?? 'Invalid Status Code: ' + res.status
|
||||||
|
}
|
||||||
|
throw 'Invalid Status Code: ' + res.status
|
||||||
|
}
|
||||||
|
let json = JSON.parse(res.body)
|
||||||
|
let data = json.data
|
||||||
|
if(typeof data !== 'string') {
|
||||||
|
throw 'Invalid Data'
|
||||||
|
}
|
||||||
|
return this.convertData(data, `${time}${kJmSecret}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Optional] account related
|
||||||
|
account = {
|
||||||
|
/**
|
||||||
|
* [Optional] login with account and password, return any value to indicate success
|
||||||
|
* @param account {string}
|
||||||
|
* @param pwd {string}
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
login: async (account, pwd) => {
|
||||||
|
let time = Math.floor(Date.now() / 1000)
|
||||||
|
await this.post(
|
||||||
|
`${this.baseUrl}/login`,
|
||||||
|
`username=${encodeURIComponent(account)}&password=${encodeURIComponent(pwd)}`
|
||||||
|
)
|
||||||
|
return "ok"
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* logout function, clear account related data
|
||||||
|
*/
|
||||||
|
logout: () => {
|
||||||
|
for (let url of JM.apiDomains) {
|
||||||
|
Network.deleteCookies(url)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// {string?} - register url
|
||||||
|
registerWebsite: null
|
||||||
|
}
|
||||||
|
|
||||||
// explore page list
|
// explore page list
|
||||||
explore = [
|
explore = [
|
||||||
{
|
{
|
||||||
@@ -469,6 +525,85 @@ class JM extends ComicSource {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// favorite related
|
||||||
|
favorites = {
|
||||||
|
multiFolder: true,
|
||||||
|
/**
|
||||||
|
* add or delete favorite.
|
||||||
|
* throw `Login expired` to indicate login expired, App will automatically re-login and re-add/delete favorite
|
||||||
|
* @param comicId {string}
|
||||||
|
* @param folderId {string}
|
||||||
|
* @param isAdding {boolean} - true for add, false for delete
|
||||||
|
* @param favoriteId {string?} - [Comic.favoriteId]
|
||||||
|
* @returns {Promise<any>} - return any value to indicate success
|
||||||
|
*/
|
||||||
|
addOrDelFavorite: async (comicId, folderId, isAdding, favoriteId) => {
|
||||||
|
if (isAdding) {
|
||||||
|
await this.post(`${this.baseUrl}/favorite`, `aid=${comicId}`)
|
||||||
|
await this.post(`${this.baseUrl}/favorite_folder`, `type=move&folder_id=${folderId}&aid=${comicId}`)
|
||||||
|
} else {
|
||||||
|
await this.post(`${this.baseUrl}/favorite`, `aid=${comicId}`)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* load favorite folders.
|
||||||
|
* throw `Login expired` to indicate login expired, App will automatically re-login retry.
|
||||||
|
* if comicId is not null, return favorite folders which contains the comic.
|
||||||
|
* @param comicId {string?}
|
||||||
|
* @returns {Promise<{folders: {[p: string]: string}, favorited: string[]}>} - `folders` is a map of folder id to folder name, `favorited` is a list of folder id which contains the comic
|
||||||
|
*/
|
||||||
|
loadFolders: async (comicId) => {
|
||||||
|
let res = await this.get(`${this.baseUrl}/favorite`)
|
||||||
|
let folders = {
|
||||||
|
"0": this.translate("All")
|
||||||
|
}
|
||||||
|
let json = JSON.parse(res)
|
||||||
|
for (let e of json.folder_list) {
|
||||||
|
folders[e.FID.toString()] = e.name
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
folders: folders,
|
||||||
|
favorited: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* add a folder
|
||||||
|
* @param name {string}
|
||||||
|
* @returns {Promise<any>} - return any value to indicate success
|
||||||
|
*/
|
||||||
|
addFolder: async (name) => {
|
||||||
|
await this.post(`${this.baseUrl}/favorite_folder`, `type=add&folder_name=${name}`)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* delete a folder
|
||||||
|
* @param folderId {string}
|
||||||
|
* @returns {Promise<void>} - return any value to indicate success
|
||||||
|
*/
|
||||||
|
deleteFolder: async (folderId) => {
|
||||||
|
await this.post(`${this.baseUrl}/favorite_folder`, `type=del&folder_id=${folderId}`)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* load comics in a folder
|
||||||
|
* throw `Login expired` to indicate login expired, App will automatically re-login retry.
|
||||||
|
* @param page {number}
|
||||||
|
* @param folder {string?} - folder id, null for non-multi-folder
|
||||||
|
* @returns {Promise<{comics: Comic[], maxPage: number}>}
|
||||||
|
*/
|
||||||
|
loadComics: async (page, folder) => {
|
||||||
|
let order = this.loadSetting('favoriteOrder')
|
||||||
|
let res = await this.get(`${this.baseUrl}/favorite?folder_id=${folder}&page=${page}&o=${order}`)
|
||||||
|
let json = JSON.parse(res)
|
||||||
|
let total = json.total
|
||||||
|
let maxPage = Math.ceil(total / 80)
|
||||||
|
let comics = json.list.map((e) => this.parseComic(e))
|
||||||
|
return {
|
||||||
|
comics: comics,
|
||||||
|
maxPage: maxPage
|
||||||
|
}
|
||||||
|
},
|
||||||
|
singleFolderForSingleComic: true,
|
||||||
|
}
|
||||||
|
|
||||||
/// single comic related
|
/// single comic related
|
||||||
comic = {
|
comic = {
|
||||||
/**
|
/**
|
||||||
@@ -517,6 +652,7 @@ class JM extends ComicSource {
|
|||||||
"標籤": tags,
|
"標籤": tags,
|
||||||
},
|
},
|
||||||
related: related,
|
related: related,
|
||||||
|
isFavorite: data.is_favorite ?? false,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -641,6 +777,22 @@ class JM extends ComicSource {
|
|||||||
maxPage: Number(json.total.toString())
|
maxPage: Number(json.total.toString())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* [Optional] send a comment, return any value to indicate success
|
||||||
|
* @param comicId {string}
|
||||||
|
* @param subId {string?} - ComicDetails.subId
|
||||||
|
* @param content {string}
|
||||||
|
* @param replyTo {string?} - commentId to reply, not null when reply to a comment
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
sendComment: async (comicId, subId, content, replyTo) => {
|
||||||
|
let res = await this.post(`${this.baseUrl}/comment`, `aid=${comicId}&comment=${encodeURIComponent(content)}&status=undefined`)
|
||||||
|
let json = JSON.parse(res)
|
||||||
|
if (json.status === "fail") {
|
||||||
|
throw json.msg ?? 'Failed to send comment'
|
||||||
|
}
|
||||||
|
return "ok"
|
||||||
|
},
|
||||||
// {string?} - regex string, used to identify comic id from user input
|
// {string?} - regex string, used to identify comic id from user input
|
||||||
idMatch: "^(\\d+|jm\\d+)$",
|
idMatch: "^(\\d+|jm\\d+)$",
|
||||||
/**
|
/**
|
||||||
@@ -715,6 +867,21 @@ class JM extends ComicSource {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
default: "1",
|
default: "1",
|
||||||
|
},
|
||||||
|
favoriteOrder: {
|
||||||
|
title: "Favorite Order",
|
||||||
|
type: "select",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: 'mr',
|
||||||
|
text: 'Add Time',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'mp',
|
||||||
|
text: 'Update Time',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
default: '0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -726,6 +893,10 @@ class JM extends ComicSource {
|
|||||||
'Refresh Domain List on Startup': '启动时刷新域名列表',
|
'Refresh Domain List on Startup': '启动时刷新域名列表',
|
||||||
'Api Domain': 'Api域名',
|
'Api Domain': 'Api域名',
|
||||||
'Image Stream': '图片分流',
|
'Image Stream': '图片分流',
|
||||||
|
'Favorite Order': '收藏夹排序',
|
||||||
|
'Add Time': '添加时间',
|
||||||
|
'Update Time': '更新时间',
|
||||||
|
'All': '全部',
|
||||||
},
|
},
|
||||||
'zh_TW': {
|
'zh_TW': {
|
||||||
'Refresh Domain List': '刷新域名列表',
|
'Refresh Domain List': '刷新域名列表',
|
||||||
@@ -733,6 +904,10 @@ class JM extends ComicSource {
|
|||||||
'Refresh Domain List on Startup': '啟動時刷新域名列表',
|
'Refresh Domain List on Startup': '啟動時刷新域名列表',
|
||||||
'Api Domain': 'Api域名',
|
'Api Domain': 'Api域名',
|
||||||
'Image Stream': '圖片分流',
|
'Image Stream': '圖片分流',
|
||||||
|
'Favorite Order': '收藏夾排序',
|
||||||
|
'Add Time': '添加時間',
|
||||||
|
'Update Time': '更新時間',
|
||||||
|
'All': '全部',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user