docs: PTTIME完整脚本(无import+直接Jsoup+ctx.auth+四个入口)

This commit is contained in:
mediabot-pt
2026-07-01 22:56:40 +08:00
parent c9a78568b0
commit 2c220cd829

View File

@@ -1,4 +1,8 @@
// PTTIME 适配脚本
// 内置变量: content, url, jsoup(Jsoup), json(Jackson), utils, http(httpHelper)
// 导入: groovy.json.*, java.net.http.*, com.par.core.adapter.*, com.mediabot.site.*
// ==================== PAR 校验入口 ====================
Map parse(String content, String url) {
def doc = Jsoup.parse(content)
@@ -8,9 +12,11 @@ Map parse(String content, String url) {
if (url.contains('/attendance.php')) return parseSign(doc)
if (url.contains('/index.php') && !url.contains('?')) return parseIndex(doc)
return [pageName: '未知页面', message: "未配置: ${url}"]
return [pageName: '未知页面', message: "未配置解析: ${url}"]
}
// ── 首页 / 用户信息 ──
private Map parseIndex(doc) {
def infoEl = doc.selectFirst('#info_block')
if (!infoEl) return [pageName: '首页', message: '未找到用户信息']
@@ -22,23 +28,25 @@ private Map parseIndex(doc) {
def bm = t =~ /魔力值\([^)]*\)[^0-9]*([\d.,]+)/
def sm = t =~ /⬆\s*(\d+)/
def lm = t =~ /⬇\s*(\d+)/
if (um) fields.upload = um[0][1] + (um[0][2] ?: '')
if (um) fields.upload = um[0][1] + (um[0][2] ?: '')
if (dm) fields.download = dm[0][1] + (dm[0][2] ?: '')
if (rm) fields.ratio = rm[0][1]
if (bm) fields.bonus = bm[0][1]
if (sm) fields.seeding = sm[0][1]
if (rm) fields.ratio = rm[0][1]
if (bm) fields.bonus = bm[0][1]
if (sm) fields.seeding = sm[0][1]
if (lm) fields.leeching = lm[0][1]
return [pageName: '用户信息', fields: fields, message: fields.isEmpty() ? '未提取' : '解析成功']
return [pageName: '用户信息', fields: fields, message: fields.isEmpty() ? '未提取到数据' : '解析成功']
}
// ── 搜索(无 tbody, 列索引方式)──
private Map parseSearch(doc) {
def rows = []
doc.select('table.torrents tr:has(td.rowfollow):not(:has(.colhead))').each { row ->
def titleEl = row.selectFirst('td.embedded a.torrentname_title')
if (!titleEl) return
def catEl = row.selectFirst('td.rowfollow span.category')
def catEl = row.selectFirst('td.rowfollow span.category')
def freeEl = row.selectFirst('font.promotion')
def tds = row.select('td.rowfollow')
def tds = row.select('td.rowfollow')
rows << [
title: titleEl.text(),
detailUrl: titleEl.attr('href'),
@@ -54,15 +62,19 @@ private Map parseSearch(doc) {
return [pageName: '搜索', extracted: rows, message: "共 ${rows.size()} 条"]
}
// ── 种子详情 ──
private Map parseDetail(doc) {
def titleEl = doc.selectFirst('a.torrentname_title b, #top h1')
def descEl = doc.selectFirst('td.embedded font[title], #kdescr')
def descEl = doc.selectFirst('td.embedded font[title], #kdescr')
return [pageName: '种子详情', fields: [
title: titleEl?.text(),
title: titleEl?.text(),
description: descEl?.text()?.take(200)
]]
}
// ── 签到 ──
private Map parseSign(doc) {
def t = doc.body().text()
def matched = t ==~ /.*(签到成功|已签到|重复签到|获得.*魔力值).*/
@@ -86,7 +98,7 @@ Map sync(PluginContext ctx) {
def body = httpGet(ctx, '/index.php')
def doc = Jsoup.parse(body)
def infoEl = doc.selectFirst('#info_block')
if (!infoEl) { ctx.incomplete = true; return [message: '未找到用户信息'] }
if (!infoEl) { ctx.incomplete = true; return [message: '未找到用户信息区域'] }
def t = infoEl.text()
def result = [:]
def um = t =~ /上传[::]\s*([0-9.,]+)\s*(TB|GB|MB|KB|B)?/
@@ -94,11 +106,11 @@ Map sync(PluginContext ctx) {
def rm = t =~ /分享率[::]\s*([\d.,]+)/
def bm = t =~ /魔力值\([^)]*\)[^0-9]*([\d.,]+)/
def sm = t =~ /⬆\s*(\d+)/
if (um) result.upload = parseTraffic(um[0][1].replace(',','') as double, um[0][2])
if (dm) result.download = parseTraffic(dm[0][1].replace(',','') as double, dm[0][2])
if (um) result.upload = parseTraffic(um[0][1].replace(',','') as double, um[0][2])
if (dm) result.download = parseTraffic(dm[0][1].replace(',','') as double, dm[0][2])
if (rm) result.shareRatio = rm[0][1].replace(',','') as double
if (bm) result.bonus = bm[0][1].replace(',','') as double
if (sm) result.seeding = sm[0][1] as int
if (bm) result.bonus = bm[0][1].replace(',','') as double
if (sm) result.seeding = sm[0][1] as int
if (!result.upload || !result.download) ctx.incomplete = true
return result
} catch (e) { ctx.incomplete = true; return [message: "同步失败: ${e.message}"] }
@@ -133,21 +145,24 @@ List search(PluginContext ctx, Map params) {
private String httpGet(PluginContext ctx, String path) {
def url = ctx.siteUrl.replaceAll('/+\$', '') + '/' + path.replaceAll('^/+', '')
def req = HttpRequest.newBuilder().uri(java.net.URI.create(url))
.timeout(Duration.ofSeconds(15)).header('User-Agent', 'MediaBot/1.0')
if (ctx.auth) req.header('Cookie', ctx.auth)
req.GET()
def resp = ctx.httpClient.send(req.build(), HttpResponse.BodyHandlers.ofString())
ctx.capturedUrl = url; ctx.capturedBody = resp.body()
def builder = HttpRequest.newBuilder().uri(java.net.URI.create(url))
.timeout(Duration.ofSeconds(15))
.header('User-Agent', 'MediaBot/1.0')
.GET()
if (ctx.auth) builder.header('Cookie', ctx.auth)
def resp = ctx.httpClient.send(builder.build(), HttpResponse.BodyHandlers.ofString())
ctx.capturedUrl = url
ctx.capturedBody = resp.body()
return resp.body()
}
// ==================== 工具 ====================
// ==================== 数字工具 ====================
private long parseTraffic(double val, String unit) {
def m = [B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776]
def m = [B:1, KB:1024, MB:1048576, GB:1073741824, TB:1099511627776]
return (val * (m[unit?.toUpperCase()] ?: 1)) as long
}
private long parseHtmlSize(String s) {
def m = s =~ /([\d.,]+)\s*(TB|GB|MB|KB|B)?/
if (!m) return 0