feat: 四类站点默认脚本+无自定义脚本时按siteType自动加载默认模板
This commit is contained in:
107
par-core/src/main/resources/scripts/default-unit3d.groovy
Normal file
107
par-core/src/main/resources/scripts/default-unit3d.groovy
Normal file
@@ -0,0 +1,107 @@
|
||||
// UNIT3D 站点默认脚本
|
||||
// 适用: BLU / TL / ACM 等 UNIT3D 架构站点(HTML + 可选 API)
|
||||
// 覆盖: 搜索 / 种子详情 / 首页
|
||||
|
||||
Map parse(String content, String url) {
|
||||
def doc = jsoup.parse(content)
|
||||
|
||||
if (url.contains('/torrents') && !url.contains('/torrents/')) return parseSearch(doc)
|
||||
if (url.contains('/torrents/') && url.contains('/')) return parseDetail(doc)
|
||||
|
||||
// 尝试 JSON API
|
||||
if (content.trim().startsWith('{') || content.trim().startsWith('[')) {
|
||||
try {
|
||||
def root = json.readValue(content, Map)
|
||||
if (root?.data) return parseApiData(root?.data, url)
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return [pageName: '未知页面', message: "未配置: ${url}"]
|
||||
}
|
||||
|
||||
private Map parseApiData(d, url) {
|
||||
if (url.contains('/user') || url.contains('/profile'))
|
||||
return [pageName: '用户', fields: [username: d?.username, uploaded: d?.uploaded?.toString(), downloaded: d?.downloaded?.toString()]]
|
||||
return [pageName: 'API数据', fields: d?.subMap(d.keySet().take(10))]
|
||||
}
|
||||
|
||||
private Map parseSearch(doc) {
|
||||
def rows = []
|
||||
doc.select('table.table tbody tr, .torrent-row, div.torrent').each { row ->
|
||||
def titleEl = utils.selectFirst(row, 'a[href*=torrents]')
|
||||
def tds = row.select('td')
|
||||
def size = ''
|
||||
for (int i = 0; i < tds.size(); i++) {
|
||||
def t = utils.text(tds.get(i))
|
||||
if (t =~ /[\d.]+\s*(GB|MB|TB)/) { size = t; break }
|
||||
}
|
||||
rows << [
|
||||
title: utils.text(titleEl),
|
||||
detailUrl: utils.attr(titleEl, 'href'),
|
||||
size: size,
|
||||
seeders: utils.text(utils.selectFirst(row, 'td:nth-child(5), td:has(.text-success)')),
|
||||
leechers: utils.text(utils.selectFirst(row, 'td:nth-child(6), td:has(.text-danger)')),
|
||||
uploadDate: utils.text(utils.selectFirst(row, 'td:nth-child(4), time')),
|
||||
]
|
||||
}
|
||||
return [pageName: '搜索', extracted: rows, message: "共 ${rows.size()} 条"]
|
||||
}
|
||||
|
||||
private Map parseDetail(doc) {
|
||||
return [pageName: '种子详情', fields: [
|
||||
title: utils.text(utils.selectFirst(doc, 'h1, .torrent-title, .meta-title')),
|
||||
size: utils.text(utils.selectFirst(doc, 'td:contains(Size) + td, .torrent-size')),
|
||||
seeders: utils.text(utils.selectFirst(doc, 'td:contains(Seeders) + td, .seeders-count')),
|
||||
leechers: utils.text(utils.selectFirst(doc, 'td:contains(Leechers) + td, .leechers-count')),
|
||||
description:utils.text(utils.selectFirst(doc, '.torrent-description, #description')).take(200),
|
||||
]]
|
||||
}
|
||||
|
||||
Map sync(PluginContext ctx) {
|
||||
if (!ctx.site.auth) return [message: "未配置认证", loginRequired: true]
|
||||
try {
|
||||
def conn = ctx.httpGet('/')
|
||||
def doc = jsoup.parse(conn.body())
|
||||
def upEl = utils.selectFirst(doc, '.user-uploaded, span:contains(Upload), dt:contains(Upload) + dd')
|
||||
def dlEl = utils.selectFirst(doc, '.user-downloaded, span:contains(Download), dt:contains(Download) + dd')
|
||||
def ratioEl = utils.selectFirst(doc, '.user-ratio, span:contains(Ratio), dt:contains(Ratio) + dd')
|
||||
def result = [:]
|
||||
if (upEl) result.upload = parseHtmlSize(utils.text(upEl))
|
||||
if (dlEl) result.download = parseHtmlSize(utils.text(dlEl))
|
||||
if (ratioEl) result.shareRate = (utils.text(ratioEl) =~ /([\d.]+)/)[0][1] as double
|
||||
return result
|
||||
} catch (e) { return [message: "同步失败: ${e.message}"] }
|
||||
}
|
||||
|
||||
Map sign(PluginContext ctx) {
|
||||
return [message: "UNIT3D 不支持签到"]
|
||||
}
|
||||
|
||||
List search(PluginContext ctx, Map params) {
|
||||
if (!ctx.site.auth) return []
|
||||
try {
|
||||
def keyword = params.keyword ?: ''
|
||||
def conn = ctx.httpGet("/torrents?search=${URLEncoder.encode(keyword,'UTF-8')}")
|
||||
def doc = jsoup.parse(conn.body())
|
||||
def rows = []
|
||||
doc.select('table.table tbody tr, .torrent-row').each { row ->
|
||||
def titleEl = utils.selectFirst(row, 'a[href*=torrents]')
|
||||
rows << [
|
||||
title: utils.text(titleEl),
|
||||
detailUrl: "${ctx.siteUrl}${utils.attr(titleEl,'href')}",
|
||||
size: parseHtmlSize(utils.text(utils.selectFirst(row, 'td:nth-child(4)'))) ?: 0,
|
||||
seeders: utils.toInt(utils.text(utils.selectFirst(row, 'td:nth-child(5)'))) ?: 0,
|
||||
leechers: utils.toInt(utils.text(utils.selectFirst(row, 'td:nth-child(6)'))) ?: 0,
|
||||
]
|
||||
}
|
||||
return rows
|
||||
} catch (e) { return [] }
|
||||
}
|
||||
|
||||
private long parseHtmlSize(String s) {
|
||||
if (!s) return 0
|
||||
def m = s =~ /([\d.]+)\s*(TB|GB|MB|KB|B)?/
|
||||
if (!m) return 0
|
||||
def m2 = [B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776]
|
||||
return ((m[0][1] as double) * (m2[m[0][2]?.toUpperCase()] ?: 1)) as long
|
||||
}
|
||||
Reference in New Issue
Block a user