1(function () { 2 const API_URL = 3 "https://thesport.winfast.dev/api/v1/football/hot_tips?lang=vn"; 4 const IMG_BASE = "https://img.bongdako.net"; 5 6 function getImgUrl(path) { 7 if (!path) return ""; 8 if (path.startsWith("http")) return path; 9 return IMG_BASE + path; 10 } 11 12 function timeAgo(dateStr) { 13 const now = new Date(); 14 const then = new Date(dateStr.replace(" ", "T") + "+07:00"); 15 const diffMs = now - then; 16 const diffMin = Math.floor(diffMs / 60000); 17 const diffHr = Math.floor(diffMin / 60); 18 19 if (diffMin < 1) return "Vừa xong"; 20 if (diffMin < 60) return diffMin + " phút trưá»c"; 21 if (diffHr < 24) return diffHr + " giá» trưá»c"; 22 23 // >= 24h: show "d thg M, YYYY" 24 var d = then.getDate(); 25 var m = then.getMonth() + 1; 26 var y = then.getFullYear(); 27 return d + " thg " + m + ", " + y; 28 } 29 30 function formatMatchTime(dateStr) { 31 const d = new Date(dateStr.replace(" ", "T") + "+07:00"); 32 const hh = String(d.getHours()).padStart(2, "0"); 33 const mm = String(d.getMinutes()).padStart(2, "0"); 34 const dd = String(d.getDate()).padStart(2, "0"); 35 const mo = String(d.getMonth() + 1).padStart(2, "0"); 36 const yy = d.getFullYear(); 37 return hh + ":" + mm + " " + dd + "/" + mo + "/" + yy; 38 } 39 40 function getRankColor(type) { 41 switch ((type || "").toLowerCase()) { 42 case "gold": 43 return "#d4a017"; 44 case "silver": 45 return "#8a8a8a"; 46 case "bronze": 47 return "#cd7f32"; 48 default: 49 return "#2e7d32"; 50 } 51 } 52 53 function escHtml(str) { 54 const d = document.createElement("div"); 55 d.textContent = str || ""; 56 return d.innerHTML; 57 } 58 59 function renderTip(tip) { 60 const avatarUrl = tip.avatar || ""; 61 const winPercent = Math.max( 62 tip.HomeWinPercent || 0, 63 tip.GuestWinPercent || 0, 64 ); 65 const rankColor = getRankColor(tip.ranking_type); 66 67 return ` 68 <div class="dbk-tip-card"> 69 <!-- User info --> 70 <div class="dbk-tip-card__user"> 71 <div class="dbk-tip-card__user-left"> 72 <img class="dbk-tip-card__avatar" src="${escHtml(avatarUrl)}" alt="${escHtml(tip.UserName)}" onerror="this.style.display='none'"> 73 <span class="dbk-tip-card__username">${escHtml(tip.UserName)}</span> 74 </div> 75 <div class="dbk-tip-card__badge" style="color: ${rankColor}"> 76 ð¥ Tá»· lá» thắng ${winPercent}% 77 </div> 78 </div> 79 80 <!-- Summary --> 81 <p class="dbk-tip-card__summary">${escHtml(tip.Summary)}</p> 82 83 <!-- Teams --> 84 <div class="dbk-tip-card__teams"> 85 <div class="dbk-tip-card__team"> 86 <span class="dbk-tip-card__team-name">${escHtml(tip.HomeName)}</span> 87 <img class="dbk-tip-card__team-logo" src="${escHtml(getImgUrl(tip.HomeLogo))}" alt="${escHtml(tip.HomeName)}" onerror="this.style.display='none'"> 88 </div> 89 <span class="dbk-tip-card__vs">-</span> 90 <div class="dbk-tip-card__team"> 91 <img class="dbk-tip-card__team-logo" src="${escHtml(getImgUrl(tip.GuestLogo))}" alt="${escHtml(tip.GuestName)}" onerror="this.style.display='none'"> 92 <span class="dbk-tip-card__team-name">${escHtml(tip.GuestName)}</span> 93 </div> 94 </div> 95 96 <!-- Match info --> 97 <div class="dbk-tip-card__match-info"> 98 <span class="dbk-tip-card__match-time">Trá»±c tiếp lúc: ${formatMatchTime(tip.MatchTime)}</span> 99 <span class="dbk-tip-card__match-sep">âº</span> 100 <span class="dbk-tip-card__league">${escHtml(tip.SclassName)}</span> 101 </div> 102 103 <!-- Footer --> 104 <div class="dbk-tip-card__footer"> 105 <span class="dbk-tip-card__time-ago">ð ${timeAgo(tip.created_at || tip.updated_at || tip.MatchTime)}</span> 106 <span class="dbk-tip-card__stats"> 107 <span class="dbk-tip-card__views">ð ${tip.view || 0}</span> 108 <span class="dbk-tip-card__likes">ð ${tip.like || 0}</span> 109 </span> 110 </div> 111 </div> 112 `; 113 } 114 115 function init() { 116 const containers = document.querySelectorAll(".dbk-hot-tips"); 117 if (!containers.length) return; 118
119 containers.forEach(function (section) { 120 const listEl = section.querySelector(".dbk-hot-tips__list"); 121 const limit = parseInt(section.dataset.limit, 10) || 5; 122 123 fetch(API_URL) 124 .then(function (res) { 125 return res.json(); 126 }) 127 .then(function (json) { 128 if (json.ErrCode !== 0 || !Array.isArray(json.Data)) { 129 listEl.innerHTML = 130 '<div class="dbk-hot-tips__empty">Không có dữ liá»u</div>'; 131 return; 132 } 133 134 const tips = json.Data.slice(0, limit); 135 listEl.innerHTML = tips.map(renderTip).join(""); 136 }) 137 .catch(function () { 138 listEl.innerHTML = 139 '<div class="dbk-hot-tips__empty">Lá»i tải dữ liá»u</div>'; 140 }); 141 }); 142 } 143 144 if (document.readyState === "loading") { 145 document.addEventListener("DOMContentLoaded", init); 146 } else { 147 init(); 148 } 149})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.