wd23 commited on
Commit
b4c5ab5
·
verified ·
1 Parent(s): 087aee8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -9
app.py CHANGED
@@ -921,6 +921,8 @@ HTML_TEMPLATE = r"""<!DOCTYPE html>
921
  .unlock-result { background: #0f0f0f; border-radius: 12px; padding: 12px; margin-top: 12px; font-size: 13px; word-break: break-all; border-left: 3px solid #e50914; }
922
  .unlock-result a { color: #e50914; text-decoration: none; }
923
  .copy-result-btn { background: #555; border: none; border-radius: 16px; padding: 4px 12px; color: #fff; cursor: pointer; font-size: 11px; margin-left: 10px; }
 
 
924
  .two-columns { display: flex; gap: 20px; flex-wrap: wrap; }
925
  .left-panel, .right-panel { flex: 1; min-width: 280px; background: #141414; border-radius: 16px; border: 1px solid #2a2a2a; overflow: visible; }
926
  .panel-header { padding: 14px 18px; border-bottom: 1px solid #2a2a2a; display: flex; justify-content: space-between; align-items: baseline; }
@@ -1192,6 +1194,17 @@ HTML_TEMPLATE = r"""<!DOCTYPE html>
1192
  setTimeout(() => { toast.style.opacity = '0'; }, 3000);
1193
  }
1194
 
 
 
 
 
 
 
 
 
 
 
 
1195
  // 日志相关
1196
  let logRefreshInterval = null;
1197
  async function fetchLogs() {
@@ -1275,7 +1288,6 @@ HTML_TEMPLATE = r"""<!DOCTYPE html>
1275
  const ALLOWED_PAN_TYPES=['115','baidu','magnet'];
1276
  function extractLinkFromResource(r){return r.link||r.download_url||r.url||r.pan_url||'';}
1277
  function detectPanTypeFromLink(link){if(!link)return'unknown';let l=link.toLowerCase();if(l.includes('pan.baidu.com')||l.includes('baidu.com/s/'))return'baidu';if(l.includes('115.com'))return'115';if(l.includes('magnet:')||l.includes('ed2k://'))return'magnet';return'unknown';}
1278
- function getPanBadgeHtml(panType){let map={baidu:['百度网盘','🐻','pan-badge-baidu'],115:['115网盘','☁️','pan-badge-115'],magnet:['磁力链接','🧲','pan-badge-magnet']};let[name,icon,cls]=map[panType]||['其他网盘','📎','pan-badge-unknown'];return`<span class="pan-badge ${cls}">${icon} ${name}</span>`;}
1279
  // 加载 TMDB 类型
1280
  async function loadMovieGenres() {
1281
  try { let resp = await fetch('/api/tmdb/genres/movie'); let data = await resp.json(); movieGenres = data; } catch(e) { console.error(e); movieGenres = []; }
@@ -1620,12 +1632,9 @@ HTML_TEMPLATE = r"""<!DOCTYPE html>
1620
  // ========== 快捷解锁功能 ==========
1621
  function extractSlugFromUrl(input) {
1622
  let trimmed = input.trim();
1623
- // 如果是纯 slug (32位十六进制)
1624
  if (/^[a-f0-9]{32}$/i.test(trimmed)) return trimmed;
1625
- // 尝试匹配 URL 格式: /resource/115/xxxx 或 /resource/xxxx
1626
  let match = trimmed.match(/\/resource\/(?:[^\/]+\/)?([a-f0-9]{32})/i);
1627
  if (match) return match[1];
1628
- // 最后尝试匹配任意32位十六进制串
1629
  match = trimmed.match(/([a-f0-9]{32})/i);
1630
  return match ? match[1] : null;
1631
  }
@@ -1640,11 +1649,9 @@ HTML_TEMPLATE = r"""<!DOCTYPE html>
1640
  showToast('未能提取到有效的 slug (32位十六进制)', true);
1641
  return;
1642
  }
1643
- // 显示正在解锁
1644
  let resultDiv = document.getElementById('quickUnlockResult');
1645
  resultDiv.style.display = 'block';
1646
  resultDiv.innerHTML = '<div style="color:#aaa;">🔓 解锁中...</div>';
1647
- // 检查是否需要密码
1648
  if (typeof UNLOCK_PASSWORD_REQUIRED !== 'undefined' && UNLOCK_PASSWORD_REQUIRED === true) {
1649
  showPasswordModal({type:'quickUnlock', slug: slug});
1650
  } else {
@@ -1668,10 +1675,22 @@ HTML_TEMPLATE = r"""<!DOCTYPE html>
1668
  }
1669
  let link = data.link || data.data?.full_url || data.data?.url || data.url;
1670
  if (link) {
1671
- // 保存到 localStorage
1672
  localStorage.setItem(`unlock_${slug}`, link);
1673
  let cacheInfo = data.from_cache ? '<span style="color:#2ecc71;">📦 来自缓存,不消耗积分</span>' : '';
 
 
 
 
 
 
 
 
 
 
1674
  resultDiv.innerHTML = `
 
 
 
1675
  <div><strong>✅ 解锁成功</strong> ${cacheInfo}</div>
1676
  <div style="margin-top:8px; word-break:break-all;">
1677
  <a href="${link}" target="_blank">${link}</a>
@@ -1717,8 +1736,6 @@ HTML_TEMPLATE = r"""<!DOCTYPE html>
1717
  async function updateCountdown(){
1718
  try { let r=await fetch('/api/next-unlock-time'); let d=await r.json(); let rem=d.remaining||0; if(rem>0){ let m=Math.floor(rem/60); let s=rem%60; document.getElementById('next-unlock-countdown').innerText=`${m}:${s.toString().padStart(2,'0')}`; } else document.getElementById('next-unlock-countdown').innerText='0:00'; } catch(e){}
1719
  }
1720
- // 检测是否需要密码(通过检查后端是否设置了密码,可调用一个接口,但简单起见:如果 UNLOCK_PASSWORD 不为空,则需要)
1721
- // 这里通过一个变量控制,实际由后端密码弹窗逻辑接管。默认认为可能需要密码,会在调用解锁时弹出。
1722
  // 初始化
1723
  (async function init() {
1724
  await Promise.all([loadMovieGenres(), loadTVGenres()]);
 
921
  .unlock-result { background: #0f0f0f; border-radius: 12px; padding: 12px; margin-top: 12px; font-size: 13px; word-break: break-all; border-left: 3px solid #e50914; }
922
  .unlock-result a { color: #e50914; text-decoration: none; }
923
  .copy-result-btn { background: #555; border: none; border-radius: 16px; padding: 4px 12px; color: #fff; cursor: pointer; font-size: 11px; margin-left: 10px; }
924
+ .resource-detail { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
925
+ .resource-detail .pan-badge { font-size: 12px; }
926
  .two-columns { display: flex; gap: 20px; flex-wrap: wrap; }
927
  .left-panel, .right-panel { flex: 1; min-width: 280px; background: #141414; border-radius: 16px; border: 1px solid #2a2a2a; overflow: visible; }
928
  .panel-header { padding: 14px 18px; border-bottom: 1px solid #2a2a2a; display: flex; justify-content: space-between; align-items: baseline; }
 
1194
  setTimeout(() => { toast.style.opacity = '0'; }, 3000);
1195
  }
1196
 
1197
+ // 获取网盘徽章 HTML
1198
+ function getPanBadgeHtml(panType) {
1199
+ const map = {
1200
+ baidu: ['百度网盘', '🐻', 'pan-badge-baidu'],
1201
+ 115: ['115网盘', '☁️', 'pan-badge-115'],
1202
+ magnet: ['磁力链接', '🧲', 'pan-badge-magnet']
1203
+ };
1204
+ let [name, icon, cls] = map[panType] || ['其他网盘', '📎', 'pan-badge-unknown'];
1205
+ return `<span class="pan-badge ${cls}">${icon} ${name}</span>`;
1206
+ }
1207
+
1208
  // 日志相关
1209
  let logRefreshInterval = null;
1210
  async function fetchLogs() {
 
1288
  const ALLOWED_PAN_TYPES=['115','baidu','magnet'];
1289
  function extractLinkFromResource(r){return r.link||r.download_url||r.url||r.pan_url||'';}
1290
  function detectPanTypeFromLink(link){if(!link)return'unknown';let l=link.toLowerCase();if(l.includes('pan.baidu.com')||l.includes('baidu.com/s/'))return'baidu';if(l.includes('115.com'))return'115';if(l.includes('magnet:')||l.includes('ed2k://'))return'magnet';return'unknown';}
 
1291
  // 加载 TMDB 类型
1292
  async function loadMovieGenres() {
1293
  try { let resp = await fetch('/api/tmdb/genres/movie'); let data = await resp.json(); movieGenres = data; } catch(e) { console.error(e); movieGenres = []; }
 
1632
  // ========== 快捷解锁功能 ==========
1633
  function extractSlugFromUrl(input) {
1634
  let trimmed = input.trim();
 
1635
  if (/^[a-f0-9]{32}$/i.test(trimmed)) return trimmed;
 
1636
  let match = trimmed.match(/\/resource\/(?:[^\/]+\/)?([a-f0-9]{32})/i);
1637
  if (match) return match[1];
 
1638
  match = trimmed.match(/([a-f0-9]{32})/i);
1639
  return match ? match[1] : null;
1640
  }
 
1649
  showToast('未能提取到有效的 slug (32位十六进制)', true);
1650
  return;
1651
  }
 
1652
  let resultDiv = document.getElementById('quickUnlockResult');
1653
  resultDiv.style.display = 'block';
1654
  resultDiv.innerHTML = '<div style="color:#aaa;">🔓 解锁中...</div>';
 
1655
  if (typeof UNLOCK_PASSWORD_REQUIRED !== 'undefined' && UNLOCK_PASSWORD_REQUIRED === true) {
1656
  showPasswordModal({type:'quickUnlock', slug: slug});
1657
  } else {
 
1675
  }
1676
  let link = data.link || data.data?.full_url || data.data?.url || data.url;
1677
  if (link) {
 
1678
  localStorage.setItem(`unlock_${slug}`, link);
1679
  let cacheInfo = data.from_cache ? '<span style="color:#2ecc71;">📦 来自缓存,不消耗积分</span>' : '';
1680
+ // 提取资源标题和网盘类型(从 data.data 中)
1681
+ let resourceTitle = data.data?.title || data.data?.name || '未知资源';
1682
+ let panType = data.data?.pan_type || 'unknown';
1683
+ if (panType === 'unknown' && link) {
1684
+ let l = link.toLowerCase();
1685
+ if (l.includes('115.com')) panType = '115';
1686
+ else if (l.includes('pan.baidu.com')) panType = 'baidu';
1687
+ else if (l.includes('magnet:')) panType = 'magnet';
1688
+ }
1689
+ let panBadge = getPanBadgeHtml(panType);
1690
  resultDiv.innerHTML = `
1691
+ <div class="resource-detail">
1692
+ <strong>📽️ ${escapeHtml(resourceTitle)}</strong> ${panBadge}
1693
+ </div>
1694
  <div><strong>✅ 解锁成功</strong> ${cacheInfo}</div>
1695
  <div style="margin-top:8px; word-break:break-all;">
1696
  <a href="${link}" target="_blank">${link}</a>
 
1736
  async function updateCountdown(){
1737
  try { let r=await fetch('/api/next-unlock-time'); let d=await r.json(); let rem=d.remaining||0; if(rem>0){ let m=Math.floor(rem/60); let s=rem%60; document.getElementById('next-unlock-countdown').innerText=`${m}:${s.toString().padStart(2,'0')}`; } else document.getElementById('next-unlock-countdown').innerText='0:00'; } catch(e){}
1738
  }
 
 
1739
  // 初始化
1740
  (async function init() {
1741
  await Promise.all([loadMovieGenres(), loadTVGenres()]);