|
133 | 133 | "💡 Highlight any text on the page,\nthen click to ask HackTricks AI about it"; |
134 | 134 |
|
135 | 135 | const API_BASE = "https://ai.hacktricks.wiki/api/assistants/threads"; |
| 136 | + const AUTH_STATUS_URL = "https://ai.hacktricks.wiki/api/auth/status"; |
| 137 | + const LOGIN_URL = "https://tools.hacktricks.wiki/"; |
136 | 138 | const BRAND_RED = "#b31328"; |
137 | 139 |
|
138 | 140 | /* ------------------------------ State ------------------------------ */ |
139 | 141 | let threadId = null; |
140 | 142 | let isRunning = false; |
| 143 | + let isAuthenticated = false; |
141 | 144 |
|
142 | 145 | /* ---------- helpers ---------- */ |
143 | 146 | const $ = (sel, ctx = document) => ctx.querySelector(sel); |
|
189 | 192 |
|
190 | 193 | console.log(`${LOG} Injecting widget… v1.16`); |
191 | 194 |
|
192 | | - await ensureThreadId(); |
193 | 195 | injectStyles(); |
194 | 196 |
|
195 | 197 | const btn = createFloatingButton(); |
|
201 | 203 | const resetBtn = $("#ht-ai-reset"); |
202 | 204 | const closeBtn = $("#ht-ai-close"); |
203 | 205 |
|
| 206 | + await refreshAuthState(btn); |
| 207 | + if (isAuthenticated) { |
| 208 | + await ensureThreadId(); |
| 209 | + } |
| 210 | + |
204 | 211 | /* ------------------- Selection snapshot ------------------- */ |
205 | 212 | let savedSelection = ""; |
206 | 213 | btn.addEventListener("pointerdown", () => { |
|
235 | 242 | }; |
236 | 243 |
|
237 | 244 | /* ------------------- Panel open / close ------------------- */ |
238 | | - btn.addEventListener("click", () => { |
| 245 | + btn.addEventListener("click", async () => { |
| 246 | + const ok = await refreshAuthState(btn); |
| 247 | + if (!ok) { |
| 248 | + showLoginPopup(); |
| 249 | + return; |
| 250 | + } |
239 | 251 | if (!savedSelection) { |
240 | 252 | alert("Please highlight some text first."); |
241 | 253 | return; |
|
350 | 362 |
|
351 | 363 | /* =================================================================== */ |
352 | 364 | function injectStyles() { |
353 | | - const css = ` |
354 | | -#ht-ai-btn{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);min-width:60px;height:60px;border-radius:30px;background:linear-gradient(45deg, #b31328, #d42d3f, #2d5db4, #3470e4);background-size:300% 300%;animation:gradientShift 8s ease infinite;color:#fff;font-size:18px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:99999;box-shadow:0 2px 8px rgba(0,0,0,.4);transition:opacity .2s;padding:0 20px} |
| 365 | + let css = ` |
| 366 | +#ht-ai-btn{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);min-width:60px;height:60px;border-radius:30px;background:linear-gradient(45deg, #b31328, #d42d3f, #2d5db4, #3470e4);background-size:300% 300%;animation:gradientShift 8s ease infinite;color:#fff;font-size:18px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:99999;box-shadow:0 2px 8px rgba(0,0,0,.4);transition:opacity .2s, filter .2s; padding:0 20px} |
| 367 | +#ht-ai-btn.ht-ai-locked{filter:grayscale(.2);opacity:.85} |
355 | 368 | #ht-ai-btn span{margin-left:8px;font-weight:bold} |
356 | 369 | @keyframes gradientShift{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}} |
357 | 370 | #ht-ai-btn:hover{opacity:.85} |
|
388 | 401 | #ht-ai-resizer:hover{background:rgba(255,255,255,.15);border-right:1px solid rgba(255,255,255,.3)} |
389 | 402 | #ht-ai-resizer:active{background:rgba(255,255,255,.25)} |
390 | 403 | #ht-ai-resizer::before{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:2px;height:20px;background:rgba(255,255,255,.4);border-radius:1px}`; |
| 404 | + css += ` |
| 405 | +#ht-ai-login-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.6);backdrop-filter:blur(6px);z-index:100200} |
| 406 | +#ht-ai-login-card{max-width:420px;width:calc(100% - 32px);padding:20px;border-radius:14px;background:#111;border:1px solid rgba(255,255,255,.08);box-shadow:0 12px 28px rgba(0,0,0,.4);text-align:center;color:#fff;font-family:system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial,sans-serif} |
| 407 | +.ht-ai-login-title{font-size:1.1rem;font-weight:700;margin-bottom:8px} |
| 408 | +.ht-ai-login-text{font-size:.95rem;color:#cfcfcf;margin-bottom:12px} |
| 409 | +.ht-ai-login-link{display:inline-block;margin-bottom:16px;color:#ff6b5b;text-decoration:none;word-break:break-all} |
| 410 | +.ht-ai-login-link:hover{text-decoration:underline} |
| 411 | +.ht-ai-login-close{background:#b31328;color:#fff;border:none;border-radius:8px;padding:8px 14px;cursor:pointer} |
| 412 | +.ht-ai-login-close:hover{opacity:.9} |
| 413 | +`; |
391 | 414 | const s = document.createElement("style"); |
392 | 415 | s.id = "ht-ai-style"; |
393 | 416 | s.textContent = css; |
|
416 | 439 | btn.addEventListener("mouseleave", () => t.classList.remove("show")); |
417 | 440 | } |
418 | 441 |
|
| 442 | + async function checkAuthStatus() { |
| 443 | + try { |
| 444 | + const res = await fetch(AUTH_STATUS_URL, { method: "GET", credentials: "include" }); |
| 445 | + isAuthenticated = res.ok; |
| 446 | + return isAuthenticated; |
| 447 | + } catch (e) { |
| 448 | + isAuthenticated = false; |
| 449 | + return false; |
| 450 | + } |
| 451 | + } |
| 452 | + |
| 453 | + function setAuthButtonState(btn, ok) { |
| 454 | + btn.classList.toggle("ht-ai-locked", !ok); |
| 455 | + } |
| 456 | + |
| 457 | + async function refreshAuthState(btn) { |
| 458 | + const ok = await checkAuthStatus(); |
| 459 | + setAuthButtonState(btn, ok); |
| 460 | + return ok; |
| 461 | + } |
| 462 | + |
| 463 | + function showLoginPopup() { |
| 464 | + if (document.getElementById("ht-ai-login-overlay")) return; |
| 465 | + const overlay = document.createElement("div"); |
| 466 | + overlay.id = "ht-ai-login-overlay"; |
| 467 | + overlay.innerHTML = ` |
| 468 | + <div id="ht-ai-login-card"> |
| 469 | + <div class="ht-ai-login-title">Sign in required</div> |
| 470 | + <div class="ht-ai-login-text"> |
| 471 | + To use HackTricks AI, please log in or create a free account on Tools. |
| 472 | + </div> |
| 473 | + <a class="ht-ai-login-link" href="${LOGIN_URL}" target="_blank" rel="noopener noreferrer">${LOGIN_URL}</a> |
| 474 | + <button class="ht-ai-login-close" type="button">Close</button> |
| 475 | + </div> |
| 476 | + `; |
| 477 | + overlay.addEventListener("click", (e) => { |
| 478 | + if (e.target === overlay) overlay.remove(); |
| 479 | + }); |
| 480 | + overlay.querySelector(".ht-ai-login-close").addEventListener("click", () => overlay.remove()); |
| 481 | + document.body.appendChild(overlay); |
| 482 | + } |
| 483 | + |
419 | 484 | /* =================================================================== */ |
420 | 485 | function createSidebar() { |
421 | 486 | const saved = parseInt(localStorage.getItem("htAiWidth") || DEF_W, 10); |
|
491 | 556 | handle.addEventListener("touchstart", onStart, { passive: false }); |
492 | 557 | } |
493 | 558 | })(); |
494 | | - |
|
0 commit comments