181 lines
8.4 KiB
HTML
181 lines
8.4 KiB
HTML
<!--
|
|
============================================================
|
|
TORRENT INDICATOR — Ghost Code Injection (Site Header)
|
|
============================================================
|
|
|
|
Coller CE BLOC dans :
|
|
Ghost Admin → Settings → Code injection → Site Header
|
|
|
|
Remplacer l'URL ci-dessous par celle de votre Cloudflare Worker.
|
|
============================================================
|
|
-->
|
|
|
|
<style id="ti-styles">
|
|
.ti-widget{display:inline-flex;flex-direction:column;font-family:system-ui,sans-serif;font-size:13px;border:1px solid #d0d7de;border-radius:8px;overflow:hidden;min-width:180px;max-width:260px;background:#fff;box-shadow:0 1px 4px rgba(0,0,0,.08);color:#24292f}
|
|
.ti-header{display:flex;align-items:center;gap:6px;padding:8px 12px;background:#f6f8fa;border-bottom:1px solid #d0d7de;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:#57606a}
|
|
.ti-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;background:#8c8c8c;transition:background .3s}
|
|
.ti-body{padding:10px 12px;display:flex;flex-direction:column;gap:6px}
|
|
.ti-row{display:flex;justify-content:space-between;align-items:center}
|
|
.ti-label{color:#57606a}
|
|
.ti-value{font-weight:600;font-variant-numeric:tabular-nums}
|
|
.ti-badge{display:inline-block;padding:1px 7px;border-radius:12px;font-size:11px;font-weight:600;letter-spacing:.02em}
|
|
.ti-health-dead{background:#ffeef0;color:#cf222e}
|
|
.ti-health-poor{background:#fff3cd;color:#9a6700}
|
|
.ti-health-good,.ti-health-excellent{background:#dafbe1;color:#116329}
|
|
.ti-dot-dead{background:#cf222e}
|
|
.ti-dot-poor{background:#d4a900}
|
|
.ti-dot-good,.ti-dot-excellent{background:#2da44e}
|
|
.ti-pop-low{background:#f0f0f0;color:#57606a}
|
|
.ti-pop-moderate{background:#ddf4ff;color:#0550ae}
|
|
.ti-pop-popular{background:#dbedff;color:#0550ae}
|
|
.ti-pop-viral{background:#fff0f0;color:#a40000}
|
|
.ti-footer{padding:5px 12px 7px;font-size:10px;color:#8c959f;border-top:1px solid #f0f0f0;text-align:right}
|
|
.ti-loading,.ti-error{padding:14px 12px;text-align:center;color:#57606a;font-size:12px}
|
|
.ti-error{color:#cf222e}
|
|
/* ── Layout large (data-layout="wide") ── */
|
|
.ti-widget--wide{max-width:680px;width:100%;margin:0 auto;min-width:0}
|
|
.ti-widget--wide .ti-body{flex-direction:row;padding:0;gap:0}
|
|
.ti-stat{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;flex:1;padding:14px 8px;border-right:1px solid #f0f0f0}
|
|
.ti-stat:last-child{border-right:none}
|
|
.ti-stat-label{font-size:10px;color:#8c959f;text-transform:uppercase;letter-spacing:.05em;font-weight:600}
|
|
.ti-stat-value{font-size:22px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1}
|
|
@media(max-width:480px){
|
|
.ti-widget--wide .ti-body{flex-wrap:wrap}
|
|
.ti-stat{flex:1 1 50%;border-bottom:1px solid #f0f0f0}
|
|
.ti-stat:nth-child(2n){border-right:none}
|
|
.ti-stat:nth-last-child(-n+2){border-bottom:none}
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
(function () {
|
|
'use strict';
|
|
|
|
// ← Remplacer par l'URL de votre Cloudflare Worker/Service selfhost
|
|
var API_URL = 'https://toscr.team4kw.fr';
|
|
|
|
var L = {
|
|
header:'État du torrent', seeders:'Seeders', leechers:'Leechers',
|
|
health:'Santé', popularity:'Popularité', updated:'Mis à jour',
|
|
health_dead:'Mort', health_poor:'Faible', health_good:'Bon', health_excellent:'Excellent',
|
|
pop_low:'Faible', pop_moderate:'Modérée', pop_popular:'Populaire', pop_viral:'Virale',
|
|
loading:'Chargement…', error:'Données indisponibles', no_data:'Aucun tracker n\'a répondu', stale:'données en cache',
|
|
};
|
|
|
|
function esc(s){ return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); }
|
|
function fmt(n){ return Number(n).toLocaleString('fr-FR'); }
|
|
function ts(){ var d=new Date(),p=function(n){return n<10?'0'+n:''+n;}; return p(d.getHours())+':'+p(d.getMinutes())+':'+p(d.getSeconds()); }
|
|
function row(label,val){ return '<div class="ti-row"><span class="ti-label">'+esc(label)+'</span>'+val+'</div>'; }
|
|
|
|
function footer(data) {
|
|
return data.stale
|
|
? L.updated+' à '+ts()+' · <em>'+L.stale+'</em>'
|
|
: L.updated+' à '+ts();
|
|
}
|
|
|
|
function stat(label, valueHtml) {
|
|
return '<div class="ti-stat"><span class="ti-stat-label">'+esc(label)+'</span>'+valueHtml+'</div>';
|
|
}
|
|
|
|
function render(el, data) {
|
|
var lbl = el.getAttribute('data-label') || L.header;
|
|
var wide = el.getAttribute('data-layout') === 'wide';
|
|
|
|
if (data.error) {
|
|
var cls = wide ? 'ti-widget ti-widget--wide' : 'ti-widget';
|
|
el.innerHTML='<div class="'+cls+'"><div class="ti-header"><span class="ti-dot"></span>'+esc(lbl)+'</div><div class="ti-error">'+esc(data.error)+'</div></div>';
|
|
return;
|
|
}
|
|
|
|
var h=data.health||'dead', p=data.popularity||'low';
|
|
|
|
if (wide) {
|
|
el.innerHTML='<div class="ti-widget ti-widget--wide">'
|
|
+'<div class="ti-header"><span class="ti-dot ti-dot-'+h+'"></span>'+esc(lbl)+'</div>'
|
|
+'<div class="ti-body">'
|
|
+stat(L.seeders, '<span class="ti-stat-value" style="color:#2da44e">'+fmt(data.seeders)+'</span>')
|
|
+stat(L.leechers, '<span class="ti-stat-value" style="color:#cf222e">'+fmt(data.leechers)+'</span>')
|
|
+stat(L.health, '<span class="ti-badge ti-health-'+h+'">'+esc(L['health_'+h]||h)+'</span>')
|
|
+stat(L.popularity,'<span class="ti-badge ti-pop-'+p+'">'+esc(L['pop_'+p]||p)+'</span>')
|
|
+'</div>'
|
|
+'<div class="ti-footer">'+footer(data)+'</div>'
|
|
+'</div>';
|
|
} else {
|
|
el.innerHTML='<div class="ti-widget">'
|
|
+'<div class="ti-header"><span class="ti-dot ti-dot-'+h+'"></span>'+esc(lbl)+'</div>'
|
|
+'<div class="ti-body">'
|
|
+row(L.seeders, '<span class="ti-value" style="color:#2da44e">'+fmt(data.seeders)+'</span>')
|
|
+row(L.leechers, '<span class="ti-value" style="color:#cf222e">'+fmt(data.leechers)+'</span>')
|
|
+row(L.health, '<span class="ti-badge ti-health-'+h+'">'+esc(L['health_'+h]||h)+'</span>')
|
|
+row(L.popularity,'<span class="ti-badge ti-pop-'+p+'">'+esc(L['pop_'+p]||p)+'</span>')
|
|
+'</div>'
|
|
+'<div class="ti-footer">'+footer(data)+'</div>'
|
|
+'</div>';
|
|
}
|
|
}
|
|
|
|
function buildUrl(el) {
|
|
var hash=el.getAttribute('data-hash'), magnet=el.getAttribute('data-magnet');
|
|
if (hash) return API_URL+'?hash='+encodeURIComponent(hash.trim());
|
|
if (magnet) return API_URL+'?magnet='+encodeURIComponent(magnet.trim());
|
|
return null;
|
|
}
|
|
|
|
function load(el) {
|
|
var url=buildUrl(el);
|
|
if (!url) { render(el,{error:'Attribut data-hash ou data-magnet manquant.'}); return; }
|
|
var lbl=el.getAttribute('data-label')||L.header;
|
|
el.innerHTML='<div class="ti-widget"><div class="ti-header"><span class="ti-dot"></span>'+esc(lbl)+'</div><div class="ti-loading">'+L.loading+'</div></div>';
|
|
var xhr=new XMLHttpRequest();
|
|
xhr.open('GET',url,true); xhr.timeout=15000;
|
|
xhr.onload=function(){
|
|
if(xhr.status>=200&&xhr.status<300){
|
|
try{ var d=JSON.parse(xhr.responseText); if(d.sources===0&&!d.stale) d.error=L.no_data; render(el,d); }
|
|
catch(e){ render(el,{error:L.error}); }
|
|
} else { render(el,{error:L.error+' ('+xhr.status+')'}); }
|
|
};
|
|
xhr.onerror=xhr.ontimeout=function(){ render(el,{error:L.error}); };
|
|
xhr.send();
|
|
}
|
|
|
|
function init() {
|
|
var els=document.querySelectorAll('.torrent-indicator');
|
|
for(var i=0;i<els.length;i++) load(els[i]);
|
|
}
|
|
|
|
document.readyState==='loading'
|
|
? document.addEventListener('DOMContentLoaded',init)
|
|
: init();
|
|
|
|
window.TorrentIndicator={ refreshAll:init, init:load };
|
|
})();
|
|
</script>
|
|
|
|
<!--
|
|
============================================================
|
|
UTILISATION DANS LES ARTICLES GHOST
|
|
============================================================
|
|
|
|
Dans l'éditeur Ghost, ajouter un bloc "HTML" et coller :
|
|
|
|
Layout compact (vertical, défaut) :
|
|
<div class="torrent-indicator"
|
|
data-hash="3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0"
|
|
data-label="Ubuntu 24.04 LTS"></div>
|
|
|
|
Layout large (horizontal, centré) :
|
|
<div class="torrent-indicator"
|
|
data-hash="3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0"
|
|
data-label="Ubuntu 24.04 LTS"
|
|
data-layout="wide"></div>
|
|
|
|
Via lien magnet (fonctionne dans les deux layouts) :
|
|
<div class="torrent-indicator"
|
|
data-magnet="magnet:?xt=urn:btih:3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0"
|
|
data-label="Mon Torrent"
|
|
data-layout="wide"></div>
|
|
|
|
Plusieurs widgets, layouts différents, sur la même page sont supportés.
|
|
============================================================
|
|
-->
|