Help
RSS
API
Feed
Maltego
Contact
Domain > ai.adamdh7.org
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2025-12-21
172.67.180.251
(
ClassC
)
2026-02-13
172.66.44.64
(
ClassC
)
Port 443
HTTP/1.1 200 OKDate: Fri, 13 Feb 2026 21:35:14 GMTContent-Type: text/html; charsetutf-8Content-Length: 85116Connection: keep-aliveAccess-Control-Allow-Origin: *Cache-Control: public, max-age0, must-revalidateETag: 2e4dc8a4b966213b6fcb320e83cb90c5referrer-policy: strict-origin-when-cross-originx-content-type-options: nosniffReport-To: {group:cf-nel,max_age:604800,endpoints:{url:https://a.nel.cloudflare.com/report/v4?sBIaazexj02llhKJIwraNqsNeFRnzticMt1xwga84m%2BQF3yxbH0pJxrY%2FuP2wRjBqodSlUASnJp8QD5hMme%2FUeZyBCrF2bn4nUM3FMrAH}}Nel: {report_to:cf-nel,success_fraction:0.0,max_age:604800}Server: cloudflareCF-RAY: 9cd77450dcf2e6e0-PDXalt-svc: h3:443; ma86400 !DOCTYPE html>html langht>head> meta charsetUTF-8> meta nameviewport contentwidthdevice-width,initial-scale1,maximum-scale1,user-scalableno,viewport-fitcover> title>Ai.Adam_DH7/title> link relmanifest href/manifest.json?v18> meta nametheme-color content#000000> meta namegoogle-site-verification contentUItG8vIV9YM3napElbB9ZAf7QYCniXwYvImdM78xTKY /> meta namedescription contentBoostez votre quotidien avec Adam_DH7, lasistant nouvelle génération. Rédaction, automatisation et résolution de problèmes complexes en un clic.> meta namekeywords contentAdam_DH7, Ai, adamdhaiti, sit web Ai, Adam_DH7 | Ai, Ai gratuit, généré image gratuiment> meta nameauthor contentAdam_DH7> meta namerobots contentindex, follow> link relcanonical hrefhttps://ai.adamdh7.org /> link relapple-touch-startup-image hrefhttps://adamdh7.org/adamdh7.png> meta propertyog:type contentwebsite> meta propertyog:url contenthttps://ai.adamdh7.org/> meta propertyog:title contentAi> meta propertyog:description contentAdam_D’H7, assistant intelligent. Chat, images, code, tout en un seul endroit.> meta propertyog:image contenthttps://adamdh7.org/adamdh7.png> meta propertyog:site_name contentAi> meta nametwitter:card contentsummary_large_image> meta nametwitter:title contentAdam_DH7 Ai> meta nametwitter:description contentAdam_D’H7, assistant intelligent. Chat, images, code, tout en un seul endroit.> meta nametwitter:image contenthttps://adamdh7.org/adamdh7.png> link relicon typeimage/png hrefhttps://adamdh7.org/adamdh7.png> link relapple-touch-icon hrefhttps://adamdh7.org/adamdh7.png> meta nameapple-mobile-web-app-capable contentyes> meta nameapple-mobile-web-app-status-bar-style contentblack-translucent> meta namemobile-web-app-capable contentyes> script typeapplication/ld+json> { @context: https://schema.org, @type: WebApplication, name: Tout, url: https://ai.adamdh7.org, description: Adam_D’H7, assistant intelligent. Chat, images, code, tout en un seul endroit., applicationCategory: UtilitiesApplication, operatingSystem: All, browserRequirements: Requires JavaScript, offers: { @type: Offer, price: 0, priceCurrency: USD }, author: { @type: Person, name: Adam_DH7 } } /script> link hrefhttps://fonts.googleapis.com/css2?familyInter:wght@300;400;600;800&displayswap relstylesheet> script srchttps://cdn.tailwindcss.com>/script> style> :root { --bg: #000000; --panel: #000000; --ai-bubble: #161616; --ai-text: #e0e0e0; --user-blue: #0b3d91; --user-text: #e8f4ff; --muted: #6b6b6b; --header-h: 70px; --msg-gap: 16px; --max-msg-w: 85%; --wa-code-bg: #0e0e0e; --wa-inline-bg: rgba(255,255,255,0.06); --input-bg: #1c1c1e; --border: rgba(255,255,255,0.08); --safe-bottom: env(safe-area-inset-bottom); } *, *::before, *::after { box-sizing: border-box; } html, body { height: 100%; margin: 0; overflow: hidden; } body { background: var(--bg); color: var(--ai-text); font-family: Inter, sans-serif; display: flex; flex-direction: column; touch-action: pan-y; } .modern-input { background: #1c1c1e; border: none; border-radius: 14px; padding: 18px; color: white; width: 100%; outline: none; font-size: 16px; } #scr-chat { display: none; flex-direction: column; height: 100%; opacity: 0; transition: opacity 0.5s ease-in-out; } #scr-chat.visible { display: flex; opacity: 1; } header { height: var(--header-h); background: var(--panel); border-bottom: 1px solid rgba(255,255,255,0.04); display: flex; align-items: center; padding: 0 16px; } #menuBtn svg { width: 28px; height: 28px; stroke: white; stroke-width: 2; } .title { font-weight: 800; font-size: 21px; color: white; letter-spacing: -0.6px; cursor: pointer; } .subtitle { font-size: 12px; opacity: 0.65; margin-top: 2px; text-align: center; } .chat-box { flex: 1; overflow-y: auto; padding: 20px 16px 10px; display: flex; flex-direction: column; gap: var(--msg-gap); -webkit-overflow-scrolling: touch; } .chat-box::-webkit-scrollbar { display: none; } .message { max-width: var(--max-msg-w); align-self: flex-start; opacity: 0; animation: fadeIn .35s forwards; word-break: break-word; white-space: pre-wrap; position: relative; } .message.user { align-self: flex-end; } .bubble { padding: 14px 18px; border-radius: 20px; font-size: 16px; line-height: 1.45; box-shadow: 0 4px 16px rgba(0,0,0,0.5); user-select: contain; -webkit-user-select: contain; } .bubble.user { background: linear-gradient(135deg, #0b3d91, #1e6fd9); color: var(--user-text); } .bubble.bot { background: var(--ai-bubble); color: var(--ai-text); border: 1px solid var(--border); } .intermediate { margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid var(--border); font-size: 14.5px; opacity: 0.8; } .intermediate div { margin-bottom: 8px; } .msg-footer { display: flex; justify-content: flex-end; align-items: center; gap: 8px; margin-top: 6px; padding-right: 4px; } .msg-icon { width: 18px; height: 18px; fill: var(--muted); cursor: pointer; opacity: 0.7; transition: 0.2s; } .msg-icon:hover { opacity: 1; fill: white; } .msg-icon.active { fill: #4ade80; opacity: 1; } .meta { font-size: 11px; color: var(--muted); margin-right: 4px; } .message-images { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; align-items: flex-start; } .message-images .img-small { width: 80px; height: 80px; border-radius: 12px; object-fit: cover; cursor: pointer; border: 1px solid rgba(255,255,255,0.06); } .message-images .img-large { width: 100%; max-width: 920px; height: auto; border-radius: 16px; object-fit: contain; cursor: pointer; box-shadow: 0 12px 40px rgba(0,0,0,0.8); border: 1px solid rgba(255,255,255,0.04); } @media (max-width: 920px) { .message-images .img-large { max-width: 90vw; } .message { max-width: 90%; } } .wa-paragraph { margin: 8px 0; } .wa-strong { font-weight: 700; display: inline; } .wa-underline { text-decoration: underline; display: inline; } .wa-inline { background: var(--wa-inline-bg); padding: 4px 10px; border-radius: 8px; font-family: ui-monospace, Menlo, monospace; font-size: 14px; border: 1px solid var(--border); display: inline-block; } .wa-code-block { display: block; background: var(--wa-code-bg); padding: 18px; border-radius: 16px; font-family: ui-monospace, Menlo, monospace; font-size: 14px; line-height: 1.55; margin: 14px 0; white-space: pre-wrap; -webkit-user-select: text; user-select: text; cursor: pointer; overflow-x: auto; box-shadow: 0 8px 32px rgba(0,0,0,0.7); scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.2) transparent; } .wa-code-block::-webkit-scrollbar { height: 6px; } .wa-code-block::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 3px; } .wa-bullet { margin-right: 8px; color: var(--muted); font-weight: 600; display: inline-block; width: 20px; text-align: center; } .copied-flash { position: relative; display: inline-block; } .copied-flash::after { content: ✔ Copié; position: absolute; right: 0; top: -25px; background: #0b3d91; padding: 2px 8px; border-radius: 6px; font-size: 12px; opacity: 0; transform: translateY(10px); transition: all 0.25s ease-out; color: #fff; pointer-events: none; z-index: 10; } .copied-flash.copied::after { opacity: 1; transform: translateY(0); } .bottom-zone { padding: 12px 10px calc(20px + var(--safe-bottom)); background: var(--bg); border-top: 1px solid rgba(255,255,255,0.04); position: relative; } #quickActions { position: absolute; bottom: 100%; left: 10px; right: 10px; background: rgba(15, 15, 18, 0.95); backdrop-filter: blur(10px); border-radius: 18px; margin-bottom: 10px; padding: 8px; display: none; flex-direction: column; gap: 2px; border: 1px solid var(--border); z-index: 50; box-shadow: 0 -10px 25px rgba(0,0,0,0.5); } #quickActions.show { display: flex; } .action-item { display: flex; align-items: center; gap: 12px; padding: 14px 16px; color: white; font-size: 15.5px; border-radius: 14px; cursor: pointer; transition: background 0.2s; } .action-item:active { background: rgba(255,255,255,0.1); } .action-item svg { width: 22px; height: 22px; opacity: 0.8; } #errorMsg { text-align: center; padding: 8px; background: rgba(239, 68, 68, 0.2); color: #fca5a5; border-radius: 8px; margin: 0 16px 8px; font-size: 12px; opacity: 0; transition: opacity 0.4s; pointer-events: none; } #errorMsg.show { opacity: 1; } #imgPreview { display: none; padding: 0 4px 10px; position: relative; align-items: end; } #imgPreview.show { display: flex; } .preview-thumb { width: 56px; height: 56px; border-radius: 10px; object-fit: cover; border: 1px solid rgba(255,255,255,0.2); } .preview-close { position: absolute; left: 44px; top: -6px; background: rgba(40,40,40,0.95); border: 1px solid rgba(255,255,255,0.2); border-radius: 50%; width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 10; } .preview-close svg { width: 12px; height: 12px; stroke: white; } .unsupported-icon { width: 56px; height: 56px; border-radius: 10px; background: rgba(239, 68, 68, 0.15); border: 1px solid rgba(239, 68, 68, 0.4); display: flex; align-items: center; justify-content: center; } .unsupported-icon svg { width: 24px; height: 24px; stroke: #fca5a5; } .input-wrapper { display: flex; align-items: end; gap: 8px; } .attach-btn { width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: #1c1c1e; border: 1px solid var(--border); cursor: pointer; flex-shrink: 0; margin-bottom: 6px; transition: transform 0.2s; } .attach-btn.active { transform: rotate(45deg); } .attach-btn svg { width: 22px; height: 22px; stroke: var(--muted); } textarea { flex: 1; min-height: 50px; max-height: 160px; padding: 14px; border-radius: 24px; background: var(--input-bg); border: 1px solid var(--border); color: white; font-size: 16px; resize: none; outline: none; overflow-y: auto; } textarea::placeholder { color: rgba(255,255,255,0.35); } .action-btn { width: 50px; height: 50px; border-radius: 50%; background: linear-gradient(180deg, var(--user-blue), #06306a); border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 4px 15px rgba(11,61,145,0.3); flex-shrink: 0; transition: transform 0.2s; } .action-btn.recording { background: #ef4444; animation: pulse 1.5s infinite; } .action-btn svg { width: 24px; height: 24px; fill: white; } .action-btn svg.dimmed { fill: var(--muted); } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } #modePreview { position: fixed; bottom: calc(130px + var(--safe-bottom)); left: 50%; transform: translateX(-50%); z-index: 40; pointer-events: none; } #modePreview > div { pointer-events: auto; background: linear-gradient(180deg, var(--user-blue), #06306a); border-radius: 9999px; padding: 7px 16px; display: flex; align-items: center; gap: 10px; box-shadow: 0 6px 20px rgba(0,0,0,0.7); font-size: 14px; font-weight: 600; } #modePreview.hidden { display: none; } #scrollToBottomBtn { position: fixed; bottom: calc(90px + var(--safe-bottom)); right: 16px; z-index: 50; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } #scrollToBottomBtn.visible { opacity: 1; pointer-events: auto; } #userMenu { position: fixed; top: 0; left: 0; bottom: 0; width: 280px; background: #0f0f0f; border-right: 1px solid rgba(255,255,255,0.08); transform: translateX(-100%); transition: transform 0.3s ease; z-index: 100; padding-top: var(--header-h); } #userMenu.show { transform: translateX(0); } .backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.6); opacity: 0; pointer-events: none; transition: opacity 0.3s; z-index: 95; } .backdrop.show { opacity: 1; pointer-events: auto; } #lang-sheet { position: fixed; bottom: 0; left: 0; right: 0; background: #1c1c1e; border-radius: 20px 20px 0 0; padding: 20px 0; transform: translateY(100%); transition: transform 0.3s; z-index: 100; } #lang-sheet.show { transform: translateY(0); } #modal { position: fixed; inset: 0; background: #000; display: none; align-items: center; justify-content: center; z-index: 100; } #modal.active { display: flex; } #modal .controls { position: absolute; top: 16px; right: 16px; display: flex; gap: 10px; z-index: 110; } #closeModalBtn { background: transparent; border: none; color: white; font-size: 28px; padding: 8px; border-radius: 8px; cursor: pointer; } #downloadImgBtn { background: rgba(30,30,30,0.7); border: 1px solid rgba(255,255,255,0.1); color: white; padding: 9px 14px; border-radius: 10px; cursor: pointer; font-size: 14px; } #modalImg { max-width: 94%; max-height: 94%; object-fit: contain; border-radius: 12px; box-shadow: 0 15px 40px rgba(0,0,0,0.7); } img { cursor: pointer; user-drag: none; -webkit-user-drag: none; } audio { width: 100%; margin-top: 8px; height: 40px; } @keyframes fadeIn { to { opacity: 1; } } @keyframes dots { 0%,100% { opacity: 0.4; } 50% { opacity: 1; } } .hidden { display: none !important; } #aboutModal { position: fixed; inset: 0; background: rgba(0,0,0,0.95); display: none; align-items: center; justify-content: center; z-index: 200; padding: 16px; } #aboutModal.show { display: flex; } #aboutModal .modal-content { background: #0f0f0f; border-radius: 24px; width: 100%; max-width: 640px; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column; } #aboutModal .modal-header { padding: 24px 24px 16px; border-bottom: 1px solid rgba(255,255,255,0.08); display: flex; justify-content: space-between; align-items: center; } #aboutModal .modal-header h2 { font-size: 28px; font-weight: 800; color: white; } #aboutModal .modal-body { flex: 1; overflow-y: auto; padding: 24px; } #aboutModal .tab-buttons { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-bottom: 32px; } #aboutModal .tab-btn { padding: 16px; border-radius: 16px; text-align: center; font-weight: 600; font-size: 16px; transition: all 0.3s; } #aboutModal .tab-btn.active { background: var(--user-blue); color: white; } #aboutModal .tab-btn:not(.active) { background: #1c1c1e; color: #d0d0d0; } #aboutModal .tab-content { font-size: 17px; line-height: 1.6; color: #d0d0d0; white-space: pre-line; } /style>/head>body> section idscr-auth classflex-1 flex flex-col items-center justify-center p-8> div classw-full max-w-sm text-center> h1 classtext-7xl font-black tracking-tighter mb-2 italic cursor-pointer onclickshowLang()>DH7/h1> p classtext-zinc-600 text-xs uppercase tracking-0.6em mb-16 data-keysubtitle>Digital HUB 7/p> div idlogin-form classspace-y-4> input typetext idlogin-id data-keyplaceholder-tfid placeholderTFID oswa DH7 classmodern-input> input typepassword idlogin-pass data-keyplaceholder-password placeholderModpas classmodern-input> button onclicklogin() classw-full bg-white text-black font-black py-4 rounded-2xl mt-6 text-lg data-keyconnect>KONEKTE/button> button onclicktoggleAuth() classw-full text-zinc-500 text-sm mt-4 data-keyregister>KREYE YON KONT/button> /div> div idreg-form classhidden space-y-4> div classflex gap-3> input typetext idreg-nom data-keyplaceholder-lastname placeholderNom classmodern-input> input typetext idreg-prenom data-keyplaceholder-firstname placeholderPrenom classmodern-input> /div> input typetext idreg-dh7 data-keyplaceholder-dh7 placeholderDH7 ID (@dh7.tf) classmodern-input> input typenumber idreg-age data-keyplaceholder-age placeholderLaj classmodern-input> input typepassword idreg-pass data-keyplaceholder-password placeholderModpas classmodern-input> button onclickregister() classw-full bg-white text-black font-black py-4 rounded-2xl mt-6 data-keycreate-account>JOIN DH7/button> button onclicktoggleAuth() classw-full text-zinc-500 text-sm mt-4 data-keyback-to-login>RETOUNEN/button> /div> /div> /section> section idscr-chat> header> button idmenuBtn aria-labelMenu> svg xmlnshttp://www.w3.org/2000/svg viewBox0 0 24 24 fillnone strokecurrentColor> line x13 y16 x221 y26>/line> line x13 y112 x221 y212>/line> line x13 y118 x221 y218>/line> /svg> /button> div classflex-1 flex flex-col items-center justify-center> div classtitle onclickshowLang()>Adam_DH7/div> div classsubtitle>/div> /div> button idaboutBtn onclickshowAboutModal() aria-labelÀ propos> svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 classw-7 h-7> circle cx12 cy12 r10/> path dM12 16v-4/> path dM12 8h.01/> /svg> /button> /header> main idchatBox classchat-box aria-livepolite>/main> div idscrollToBottomBtn> div classbg-white/10 backdrop-blur-lg p-4 rounded-full border border-white/10 shadow-2xl cursor-pointer> svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2.5 stroke-linecapround stroke-linejoinround> path dM12 19V5M5 12l7 7 7-7/> /svg> /div> /div> div idmodePreview classhidden> div> span idmodeLabel classtext-white>/span> button idcancelModeBtn classtext-white/80 hover:text-white text-xl leading-none>×/button> /div> /div> div classbottom-zone> div idquickActions> div classaction-item onclicktriggerFileSelect()> svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2>rect x3 y3 width18 height18 rx2 ry2/>circle cx8.5 cy8.5 r1.5/>polyline points21 15 16 10 5 21/>/svg> span data-keyact-photo>1 Photo / Videyo/span> /div> div classaction-item onclicksetMode(thinking)> svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2>path dM21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 1 1-7.6-10.6 8.38 8.38 0 0 1 3.8.9/>polyline points16 12 12 8 8 12/>/svg> span data-keyact-think>2 Reflexion plus longue/span> /div> div classaction-item onclicksetMode(generate)> svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2>path dM12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83/>/svg> span data-keyact-gen>3 Genere une image/span> /div> div classaction-item onclicksetMode(cheche)> svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2>circle cx11 cy11 r8/>line x121 y121 x216.65 y216.65/>/svg> span data-keyact-web>4 Recherche sur le web/span> /div> div classaction-item onclicksetMode(pro)> svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2> path dM12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z/> /svg> span data-keyact-pro>5 Mode Pro/span> /div> div classaction-item stylecolor:#ff4444 onclickclearChat()> svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2>polyline points3 6 5 6 21 6/>path dM19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2/>line x110 y111 x210 y217/>line x114 y111 x214 y217/>/svg> span data-keyact-clear>6 Effacer tous de ce Chat/span> /div> /div> div iderrorMsg>/div> div idimgPreview> div classpreview-close onclickclearImagePreview()> svg xmlnshttp://www.w3.org/2000/svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width3 stroke-linecapround stroke-linejoinround> line x118 y16 x26 y218>/line> line x16 y16 x218 y218>/line> /svg> /div> img idpreviewThumb classpreview-thumb src altPreview> div idpreviewError classunsupported-icon hidden> svg xmlnshttp://www.w3.org/2000/svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround> circle cx12 cy12 r10>/circle> line x14.93 y14.93 x219.07 y219.07>/line> /svg> /div> /div> form idchatForm autocompleteoff novalidate> div classinput-wrapper> button typebutton classattach-btn idplusBtn onclicktoggleQuickActions()> svg xmlnshttp://www.w3.org/2000/svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround> line x112 y15 x212 y219>/line> line x15 y112 x219 y212>/line> /svg> /button> input typefile idmediaInput hidden acceptimage/*> textarea iduserInput aria-labelMesaj placeholderEkris mesaj ou... rows1>/textarea> button idactionBtn classaction-btn typebutton> svg idiconMic viewBox0 0 24 24 xmlnshttp://www.w3.org/2000/svg> path dM12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z/> path dM17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z/> /svg> svg idiconSend classhidden viewBox0 0 24 24 xmlnshttp://www.w3.org/2000/svg> path dM2,21L23,12L2,3V10L17,12L2,14V21Z/> /svg> /button> /div> /form> /div> /section> div iduserMenu> div classp-6 pt-8> div iduser-name classtext-2xl font-black text-white mb-6>/div> div classspace-y-3 text-sm text-zinc-400> p>TFID: span iduser-tfid classfont-mono text-white>/span>/p> div iduser-dh7-line classhidden> p>DH7: span iduser-dh7 classfont-mono text-white>/span>/p> /div> /div> button onclicklogout() classmt-12 w-full bg-red-900/80 text-white py-4 rounded-2xl font-bold text-lg data-keylogout-btn>DEKONEKTE/button> /div> /div> div idmenuBackdrop classbackdrop onclickcloseMenu()>/div> div idbackdrop classbackdrop onclickcloseOverlays()>/div> div idlang-sheet> div classpx-6 py-4 text-center text-white text-lg cursor-pointer onclickchangeLanguage(ht)>Kreyòl Ayisyen/div> div classpx-6 py-4 text-center text-white text-lg cursor-pointer onclickchangeLanguage(fr)>Français/div> div classpx-6 py-4 text-center text-white text-lg cursor-pointer onclickchangeLanguage(en)>English/div> div classpx-6 py-4 text-center text-white text-lg cursor-pointer onclickchangeLanguage(es)>Español/div> div classpx-6 py-4 text-center text-blue-500 font-bold text-lg cursor-pointer onclickcloseOverlays()>Fèmen/div> /div> div idmodal> div classcontrols> button iddownloadImgBtn>Télécharge/button> button idcloseModalBtn>✖/button> /div> img idmodalImg src altImaj/> /div> div idaboutModal> div classmodal-content> div classmodal-header> h2>À propos de Adam_DH7/h2> button classtext-4xl text-gray-400 hover:text-white onclickcloseAboutModal()>×/button> /div> div classmodal-body> div classtab-buttons idaboutTabs>/div> div classtab-content idaboutContent>/div> /div> /div> /div> audio idttsAudio hidden>/audio> script> const API_AUTH https://server.dh7.adamdh7.org; const API_WORKER https://server.ai.adamdh7.org/; const API_MEDIA https://teste.adamdh7.org; const SESSION_KEY dh7_session; let currentUser null; let currentTfid null; let currentLanguage localStorage.getItem(language) || ht; let currentMode null; let mediaRecorder; let audioChunks ; let isRecording false; let isInitialLoad false; let pendingImageDesc null; let pendingImageBlob null; let imgAnalysisController null; const originalViewportContent document.querySelector(metanameviewport).getAttribute(content); const modeConfig { thinking: {prefix: /thinking , key: act-think}, generate: {prefix: /generate , key: act-gen}, cheche: {prefix: /cheche , key: act-web}, pro: {prefix: /pro , key: act-pro} }; const translations { ht: { subtitle: Digital HUB 7, placeholder-tfid: TFID oswa DH7, placeholder-password: Modpas, connect: KONEKTE, register: KREYE YON KONT, placeholder-lastname: Non, placeholder-firstname: Prenom, placeholder-dh7: DH7 ID (@dh7.tf), placeholder-age: Laj, create-account: Jwen DH7, back-to-login: RETOUNEN, logout-btn: DEKONEKTE, chat_placeholder: Ekri on mesaj..., act-photo: Photo, act-think: Refleksyon pi long, act-gen: Genere yon imaj, act-web: cheche sou web lan, act-pro: Mòd Pro, act-clear: Efase tout chat sa }, fr: { subtitle: Digital HUB 7, placeholder-tfid: TFID ou DH7, placeholder-password: Mot de passe, connect: SE CONNECTER, register: CRÉER UN COMPTE, placeholder-lastname: Nom, placeholder-firstname: Prénom, placeholder-dh7: DH7 ID (@dh7.tf), placeholder-age: Âge, create-account: REJOINDRE DH7, back-to-login: RETOUR, logout-btn: DÉCONNEXION, chat_placeholder: Tapez votre message..., act-photo: Photo, act-think: Réflexion plus longue, act-gen: Générer une image, act-web: Recherche sur le web, act-pro: Mode Pro, act-clear: Effacer ce chat }, en: { subtitle: Digital HUB 7, placeholder-tfid: TFID or DH7, placeholder-password: Password, connect: LOGIN, register: CREATE ACCOUNT, placeholder-lastname: Last Name, placeholder-firstname: First Name, placeholder-dh7: DH7 ID (@dh7.tf), placeholder-age: Age, create-account: Join DH7, back-to-login: BACK, logout-btn: LOGOUT, chat_placeholder: Type your message..., act-photo: Photo, act-think: Long Reflection, act-gen: Generate an image, act-web: Web Search, act-pro: Pro Mode, act-clear: Clear this chat }, es: { subtitle: Digital HUB 7, placeholder-tfid: TFID o DH7, placeholder-password: Contraseña, connect: CONECTAR, register: CREAR CUENTA, placeholder-lastname: Apellido, placeholder-firstname: Nombre, placeholder-dh7: DH7 ID (@dh7.tf), placeholder-age: Edad, create-account: UNIRSE A DH7, back-to-login: REGRESAR, logout-btn: CERRAR SESIÓN, chat_placeholder: Escribe tu mensaje..., act-photo: Foto, act-think: Reflexión larga, act-gen: Generar una imagen, act-web: Búsqueda web, act-pro: Modo Pro, act-clear: Borrar este chat } }; const aboutTabTitles { ht: A propo, Mòd Pro, Refleksyon long, Rechèch, Jenere imaj, fr: À propos, Mode Pro, Réflexion longue, Recherche, Générer images, en: About, Pro Mode, Long Reflection, Web Search, Generate Images, es: Acerca de, Modo Pro, Reflexión larga, Búsqueda web, Generar imágenes }; const aboutContent { main: { ht: Adam_DH7 se yon asistan entèlijan ki reyini plizyè fonksyon nan yon sèl entèfas chat modèn ak adaptab.\n\nOu ka fè konvèsasyon nòmal, jenere imaj, fè rechèch sou entènèt, itilize reflexyon long, ak mòd Pro pou repons ki pi avanse.\n\nTout bagay fèt pou yon eksperyans rapid, flwid ak bèl sou tout aparèy., fr: Adam_DH7 est un assistant intelligent qui regroupe plusieurs fonctionnalités dans une interface chat moderne et fluide.\n\nConversation classique, génération d’images, recherche web en temps réel, réflexion approfondie et mode Pro sont disponibles.\n\nL’expérience est optimisée pour tous les appareils avec un design épuré et réactif., en: Adam_DH7 is an advanced AI assistant combining multiple features in a modern, responsive chat interface.\n\nStandard chat, image generation, real-time web search, deep reflection, and Pro mode are all available.\n\nThe experience is fast, smooth, and beautiful on any device., es: Adam_DH7 es un asistente IA avanzado que combina múltiples funciones en una interfaz de chat moderna y fluida.\n\nChat normal, generación de imágenes, búsqueda web en tiempo real, reflexión profunda y modo Pro están disponibles.\n\nLa experiencia está optimizada para todos los dispositivos con un diseño limpio y adaptable. }, pro: { ht: Mode Pro bay aksè a yon modèl IA ki pi pwisan pou repons ki pi detaye ak kreyatif.\n\nLè w aktive li ou wè indikatè frap la, epi repons lan parèt progresivman nan bil asistan an pou yon eksperyans natirèl., fr: Le Mode Pro utilise un modèle IA premium pour des réponses plus riches et créatives.\n\nVous voyez l’indicateur de frappe, puis la réponse apparaît progressivement dans la bulle de l’assistant pour une expérience fluide., en: Pro Mode uses a premium AI model for richer, more creative responses.\n\nYou see the typing indicator, then the response streams in naturally in the assistant bubble., es: El Modo Pro utiliza un modelo IA premium para respuestas más ricas y creativas.\n\nVes el indicador de escritura y la respuesta aparece progresivamente en la burbuja del asistente. }, thinking: { ht: Reflexyon long pèmèt IA a reflechi an pwofondè anvan repons final la.\n\nIndikatè frappe a dire pi lontan pandan IA a ap panse, epi repons rich parèt yon sèl fwa., fr: La Réflexion longue permet à l’IA de raisonner profondément avant la réponse finale.\n\nL’indicateur de frappe dure plus longtemps, puis la réponse détaillée apparaît d’un coup., en: Long Reflection lets the AI think deeply before the final answer.\n\nThe typing indicator lasts longer while the AI reasons, then the rich response appears at once., es: La Reflexión larga permite que la IA razone en profundidad antes de la respuesta final.\n\nEl indicador de escritura dura más, luego la respuesta detallada aparece de una vez. }, cheche: { ht: Rechèch sou entènèt an tan reyèl pou bay enfòmasyon ajou.\n\n Asistan an fè rechèch la epi entegre rezilta yo natirèlman nan repons li., fr: Recherche web en temps réel pour des informations à jour.\n\nL’assistant effectue la recherche et intègre les résultats naturellement dans sa réponse., en: Real-time web search for up-to-date information.\n\nThe assistant searches and naturally integrates fresh data into the response., es: Búsqueda web en tiempo real para información actualizada.\n\nEl asistente busca e integra los datos frescos de forma natural en la respuesta. }, generate: { ht: Jenere imaj ak deskripsyon ou bay la.\n\nEpi imaj la parèt dirèkteman nan konvèsasyon an, ak opsyon pou agrandi oswa telechaje., fr: Génération d’images à partir de votre description.\n\nL’image apparaît directement dans le chat avec possibilité de l’agrandir ou télécharger., en: Generate images from your description.\n\nThe image appears directly in the chat with enlarge and download options., es: Generar imágenes a partir de tu descripción.\n\nLa imagen aparece directamente en el chat con opciones de ampliar y descargar. } }; let currentAboutTab main; function showAboutModal(tab main) { currentAboutTab tab; updateAboutModal(); document.getElementById(aboutModal).classList.add(show); } function closeAboutModal() { document.getElementById(aboutModal).classList.remove(show); } function updateAboutModal() { const titles aboutTabTitlescurrentLanguage || aboutTabTitles.fr; const tabsContainer document.getElementById(aboutTabs); tabsContainer.innerHTML ; main, pro, thinking, cheche, generate.forEach((key, i) > { const btn document.createElement(div); btn.className tab-btn + (key currentAboutTab ? active : ); btn.textContent titlesi; btn.onclick () > { currentAboutTab key; updateAboutModal(); }; tabsContainer.appendChild(btn); }); document.getElementById(aboutContent).textContent aboutContentcurrentAboutTabcurrentLanguage || aboutContentcurrentAboutTab.fr; } const inputWrapper document.querySelector(.input-wrapper); function toggleQuickActions() { const qa document.getElementById(quickActions); const btn document.getElementById(plusBtn); qa.classList.toggle(show); btn.classList.toggle(active); } function closeQuickActions() { const qa document.getElementById(quickActions); const btn document.getElementById(plusBtn); qa.classList.remove(show); btn.classList.remove(active); } function triggerFileSelect() { closeQuickActions(); document.getElementById(mediaInput).click(); } function setMode(mode null) { if (mode && currentMode mode) mode null; currentMode mode; updateModePreview(); adjustModePreviewPosition(); closeQuickActions(); } function updateModePreview() { const preview document.getElementById(modePreview); const label document.getElementById(modeLabel); if (currentMode && modeConfigcurrentMode) { let text translationscurrentLanguagemodeConfigcurrentMode.key || ; text text.replace(/^\d+\s*/, ).trim(); label.textContent text; preview.classList.remove(hidden); } else { preview.classList.add(hidden); } } function adjustModePreviewPosition() { const preview document.getElementById(modePreview); if (preview.classList.contains(hidden)) return; const wrapperHeight inputWrapper.offsetHeight; const baseOffset 60; preview.style.bottom `calc(${wrapperHeight + baseOffset}px + var(--safe-bottom))`; } async function clearChat() { if(!confirm(Effacer toute la conversation ?)) return; closeQuickActions(); try { await fetch(API_WORKER, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({action: chat, text: /clear, tfid: currentTfid}) }); location.reload(); } catch(e) { showError(Erreur reset); } } async function login() { let id document.getElementById(login-id).value.trim(); const pass document.getElementById(login-pass).value; if (!id || !pass) return alert(Ranpli tout chan yo); if (!id.includes(@dh7.tf) && !id.startsWith(TF-)) id + @dh7.tf; try { const res await fetch(`${API_AUTH}/login`, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ identifier: id, password: pass }) }); const data await res.json(); if (data.success) { currentUser data.user; currentTfid data.user.tfid; localStorage.setItem(SESSION_KEY, JSON.stringify(currentUser)); showChat(); } else { alert(data.error || Erreur connexion); } } catch (e) { alert(Pa ka kontakte sèvè a); } } async function register() { const nom document.getElementById(reg-nom).value.trim(); const prenom document.getElementById(reg-prenom).value.trim(); let dh7 document.getElementById(reg-dh7).value.trim(); const age parseInt(document.getElementById(reg-age).value); const pass document.getElementById(reg-pass).value; if (!nom || !prenom || !dh7 || isNaN(age) || !pass) return alert(Tout chan obligatwa); if (!dh7.includes(@dh7.tf)) dh7 + @dh7.tf; try { const res await fetch(`${API_AUTH}/register`, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ nom, prenom, dh7, age, password: pass }) }); const result await res.json(); if (result.success) { alert(`${result.tfid}`); toggleAuth(); } else { alert(result.error || Erreur); } } catch (e) { alert(Erreur sèvè); } } function toggleAuth() { document.getElementById(login-form).classList.toggle(hidden); document.getElementById(reg-form).classList.toggle(hidden); } function logout() { localStorage.removeItem(SESSION_KEY); location.reload(); } function showChat() { document.getElementById(scr-auth).classList.add(hidden); document.getElementById(scr-chat).classList.add(visible); const name `${currentUser.prenom || } ${currentUser.nom || }`.trim(); document.getElementById(user-name).textContent name || Itilizatè; document.getElementById(user-tfid).textContent currentUser.tfid || ; if (currentUser.dh7) { document.getElementById(user-dh7).textContent currentUser.dh7; document.getElementById(user-dh7-line).classList.remove(hidden); } changeLanguage(currentLanguage); initChat(); } async function initChat() { chatBox.innerHTML ; messageCount 0; isInitialLoad true; await loadOrUpdateSession(); isInitialLoad false; if (messageCount 0) { showTyping(); const name `${currentUser.prenom || } ${currentUser.nom || }`.trim() || Nom Trouvé; const dh7 currentUser.dh7 || Aucun; const langNames {ht: Kreyòl Ayisyen, fr: Français, en: English, es: Español}; const langue langNamescurrentLanguage; const initText `Please keep this background information about me in mind for our future interactions : \nNom: ${name}\nTFID: ${currentTfid}\nD’H7: ${dh7}\nLangue: ${langue}`; try { await fetch(API_WORKER, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({action: chat, text: initText, tfid: currentTfid}) }); } catch (e) { console.error(e); hideTyping(); } await loadOrUpdateSession(); } chatBox.scrollTop chatBox.scrollHeight; updateScrollToBottomButton(); } function toggleMenu() { document.getElementById(userMenu).classList.toggle(show); document.getElementById(menuBackdrop).classList.toggle(show); } function closeMenu() { document.getElementById(userMenu).classList.remove(show); document.getElementById(menuBackdrop).classList.remove(show); } function showLang() { document.getElementById(backdrop).classList.add(show); document.getElementById(lang-sheet).classList.add(show); } function closeOverlays() { document.getElementById(backdrop).classList.remove(show); document.getElementById(lang-sheet).classList.remove(show); } function changeLanguage(lang) { currentLanguage lang; localStorage.setItem(language, lang); const t translationslang; document.querySelectorAll(data-key).forEach(el > { const key el.dataset.key; if (tkey) { if (el.tagName INPUT || el.tagName TEXTAREA) el.placeholder tkey; else el.innerText tkey; } }); document.getElementById(userInput).placeholder t.chat_placeholder; updateModePreview(); adjustModePreviewPosition(); if (!document.getElementById(aboutModal).classList.contains(hidden)) { updateAboutModal(); } closeOverlays(); } const chatBox document.getElementById(chatBox); const userInput document.getElementById(userInput); const actionBtn document.getElementById(actionBtn); const iconMic document.getElementById(iconMic); const iconSend document.getElementById(iconSend); const modal document.getElementById(modal); const modalImg document.getElementById(modalImg); const closeModalBtn document.getElementById(closeModalBtn); const downloadImgBtn document.getElementById(downloadImgBtn); const mediaInput document.getElementById(mediaInput); const scrollToBottomBtn document.getElementById(scrollToBottomBtn); let messageCount 0; let isWaiting false; let currentTypingEl null; function autoScrollIfNeeded() { const tolerance 150; if (chatBox.scrollHeight - chatBox.scrollTop - chatBox.clientHeight tolerance) { chatBox.scrollTop chatBox.scrollHeight; } } function updateScrollToBottomButton() { const tolerance 200; if (chatBox.scrollHeight - chatBox.scrollTop - chatBox.clientHeight > tolerance) { scrollToBottomBtn.classList.add(visible); } else { scrollToBottomBtn.classList.remove(visible); } } chatBox.addEventListener(scroll, updateScrollToBottomButton); scrollToBottomBtn.addEventListener(click, () > { chatBox.scrollTo({ top: chatBox.scrollHeight, behavior: smooth }); }); function escapeHtml(unsafe) { return unsafe .replace(/&/g, &) .replace(//g, <) .replace(/>/g, >) .replace(//g, ") .replace(//g, '); } function formatToFragment(raw) { if (!raw) return document.createDocumentFragment(); let s String(raw).replace(/\r\n/g,\n).replace(/\r/g,\n); const codeBlocks ; s s.replace(/```(\s\S*?)```/g, (m, inner) > { codeBlocks.push(inner); return `@@CODEBLOCK_${codeBlocks.length-1}@@`; }); const frag document.createDocumentFragment(); const paragraphs s.split(/\n{2,}/g); paragraphs.forEach(par > { if (/^@@CODEBLOCK_\d+@@$/.test(par)) { const idx parseInt(par.match(/\d+/)0); const pre document.createElement(pre); pre.className wa-code-block copied-flash; pre.textContent codeBlocksidx || ; pre.setAttribute(data-plain, codeBlocksidx || ); frag.appendChild(pre); return; } const container document.createDocumentFragment(); let cursor 0; const tokenRe /(@@CODEBLOCK_(\d+)@@)/g; let m; while ((m tokenRe.exec(par)) ! null) { if (m.index > cursor) container.appendChild(buildParagraphs(par.slice(cursor, m.index))); const pre document.createElement(pre); pre.className wa-code-block copied-flash; const idx parseInt(m2); pre.textContent codeBlocksidx || ; pre.setAttribute(data-plain, codeBlocksidx || ); container.appendChild(pre); cursor tokenRe.lastIndex; } if (cursor par.length) container.appendChild(buildParagraphs(par.slice(cursor))); frag.appendChild(container); }); return frag; } function buildParagraphs(text) { const frag document.createDocumentFragment(); const lines text.split(\n); lines.forEach(line > { const div document.createElement(div); div.className wa-paragraph; const bulletMatch line.match(/^(\s*)-*•\s+(.*)/); let content line; if (bulletMatch) { const b document.createElement(span); b.className wa-bullet; b.textContent •; div.appendChild(b); content bulletMatch2; } content escapeHtml(content); const temp document.createElement(div); temp.innerHTML content .replace(/\*\*(.*?)\*\*/g, strong classwa-strong>$1/strong>) .replace(/__(.*?)__/g, strong classwa-strong>$1/strong>) .replace(/~~(.*?)~~/g, del>$1/del>) .replace(/~(.*?)~/g, span classwa-underline>$1/span>) .replace(/`(.*?)`/g, span classwa-inline copied-flash data-plain$1>$1/span>); while (temp.firstChild) div.appendChild(temp.firstChild); frag.appendChild(div); }); return frag; } function createMessageFooter(rawText) { const footer document.createElement(div); footer.className msg-footer; const speakIcon document.createElementNS(http://www.w3.org/2000/svg, svg); speakIcon.setAttribute(viewBox, 0 0 24 24); speakIcon.classList.add(msg-icon); speakIcon.innerHTML path dM3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z/>; speakIcon.onclick () > playTTS(rawText); footer.appendChild(speakIcon); const copyIcon document.createElementNS(http://www.w3.org/2000/svg, svg); copyIcon.setAttribute(viewBox, 0 0 24 24); copyIcon.classList.add(msg-icon); copyIcon.innerHTML path dM16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z/>; copyIcon.onclick () > { navigator.clipboard.writeText(rawText).then(() > { copyIcon.style.fill #4ade80; copyIcon.style.opacity 1; setTimeout(() > { copyIcon.style.fill ; copyIcon.style.opacity ; }, 1500); }).catch(err > { console.error(Failed to copy, err); }); }; footer.appendChild(copyIcon); return footer; } async function playTTS(text) { if(!text) return; try { const res await fetch(`${API_MEDIA}/text-to-speech`, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({text}) }); if(res.ok) { const blob await res.blob(); const url URL.createObjectURL(blob); const audio document.getElementById(ttsAudio); audio.src url; audio.play(); } } catch(e) { console.error(e); } } function renderMessage({whobot, textnull, imagesnull, audionull, tsDate.now()}) { const msg document.createElement(div); msg.className `message ${who}`; let displayText text; let displayImages images || ; if (who bot && displayText && displayImages.length 0) { const lines displayText.split(\n).map(l > l.trim()).filter(Boolean); const isAllImageUrls lines.every(line > /^https?:\/\/^\s+$/.test(line) && /\.(jpe?g|png|gif|webp|svg|avif|bmp)(\?.*)?$/i.test(line) ); if (isAllImageUrls && lines.length > 0) { displayImages lines; displayText null; } } if (displayText) { const bubble document.createElement(div); bubble.className `bubble ${who}`; bubble.appendChild(formatToFragment(displayText)); msg.appendChild(bubble); } if (audio) { const bubble document.createElement(div); bubble.className `bubble ${who}`; const audioEl document.createElement(audio); audioEl.controls true; audioEl.src audio; bubble.appendChild(audioEl); msg.appendChild(bubble); } if (displayImages.length > 0) { const cont document.createElement(div); cont.className message-images; displayImages.forEach(src > { const img document.createElement(img); img.src src; img.loading lazy; img.className displayImages.length 1 ? img-large : img-small; img.onclick () > openModal(src); cont.appendChild(img); }); msg.appendChild(cont); } const meta document.createElement(div); meta.className meta; meta.style.textAlign who user ? right : left; meta.textContent new Date(ts).toLocaleTimeString(, {hour:2-digit, minute:2-digit}); msg.appendChild(meta); if (displayText && who ! sys) { msg.appendChild(createMessageFooter(displayText)); } chatBox.appendChild(msg); autoScrollIfNeeded(); updateScrollToBottomButton(); if (who bot && text && text.includes(⩔)) { setTimeout(() > location.reload(), 1000); } return msg; } function renderWithTypingEffect(rawText, ts Date.now()) { const msg document.createElement(div); msg.className message bot; const bubble document.createElement(div); bubble.className bubble bot; msg.appendChild(bubble); const meta document.createElement(div); meta.className meta; meta.textContent new Date(ts).toLocaleTimeString(, {hour:2-digit, minute:2-digit}); msg.appendChild(meta); chatBox.appendChild(msg); autoScrollIfNeeded(); updateScrollToBottomButton(); bubble.textContent ; let i 0; const speed rawText.length > 300 ? 12 : 25; const timer setInterval(() > { if (i rawText.length) { bubble.textContent + rawText.charAt(i); i++; autoScrollIfNeeded(); updateScrollToBottomButton(); } else { clearInterval(timer); bubble.textContent ; bubble.appendChild(formatToFragment(rawText)); msg.appendChild(createMessageFooter(rawText)); autoScrollIfNeeded(); updateScrollToBottomButton(); if (rawText.includes(⩔)) { setTimeout(() > location.reload(), 1000); } } }, speed); return msg; } function showTyping() { if (currentTypingEl) currentTypingEl.remove(); const msg document.createElement(div); msg.className message bot; const bubble document.createElement(div); bubble.className bubble bot; const dots document.createElement(span); dots.textContent •••; dots.style.animation dots 1.4s infinite; bubble.appendChild(dots); msg.appendChild(bubble); chatBox.appendChild(msg); autoScrollIfNeeded(); updateScrollToBottomButton(); currentTypingEl msg; } function hideTyping() { if (currentTypingEl) { currentTypingEl.remove(); currentTypingEl null; } } function showError(msg) { const el document.getElementById(errorMsg); el.textContent msg; el.classList.add(show); setTimeout(() > el.classList.remove(show), 3000); } async function fetchSession() { if (!currentTfid) return null; try { const res await fetch(`${API_WORKER}session?tfid${encodeURIComponent(currentTfid)}`, {signal: AbortSignal.timeout(15000)}); const j await res.json(); if (j?.ok && Array.isArray(j.session?.messages)) return j.session.messages; } catch (e) { console.error(e); } return null; } async function loadOrUpdateSession() { const messages await fetchSession(); if (!messages || messages.length 0) return; const newMsgs messages.slice(messageCount); if (newMsgs.length 0) return; hideTyping(); let hasBotMessage false; newMsgs.forEach((m, idx) > { const who m.from user ? user : bot; if (who user && !isInitialLoad) return; let displayText m.text || ; if (who user) { for (const config of Object.values(modeConfig)) { if (displayText.startsWith(config.prefix)) { displayText displayText.slice(config.prefix.length).trim(); break; } } } const skipRe /^(\Please keep this background information about me in mind for our future interactions : |\IMAGE_CONTEXT\|\VOICE_CONTEXT\|\/clear)/; if (skipRe.test(displayText)) return; displayText displayText.replace(/\\IMAGE\\\s\S*?\\\/IMAGE\\/g, ).trim(); displayText displayText.replace(/\\VOICE\\\s\S*?\\\/VOICE\\/g, ).trim(); displayText displayText.replace(/^Question:\s*/i, ).trim(); if (displayText.length 0) displayText null; let displayImages (m.type image && (Array.isArray(m.url) ? m.url : m.url ? m.url : )) || ; const ts m.ts || Date.now(); if (who bot) hasBotMessage true; if (idx newMsgs.length - 1 && who bot && displayText) { renderWithTypingEffect(displayText, ts); } else { renderMessage({who, text: displayText, images: displayImages, ts}); } }); if (hasBotMessage) { closeQuickActions(); } messageCount messages.length; updateScrollToBottomButton(); } function clearImagePreview() { if (imgAnalysisController) { imgAnalysisController.abort(); imgAnalysisController null; } document.getElementById(imgPreview).classList.remove(show); document.getElementById(previewThumb).src ; document.getElementById(previewError).classList.add(hidden); document.getElementById(previewThumb).classList.remove(hidden); document.getElementById(previewThumb).onclick null; document.getElementById(previewThumb).style.cursor default; pendingImageDesc null; pendingImageBlob null; mediaInput.value ; toggleIcons(); } function toggleImagePreview(show, src null, isError false) { const area document.getElementById(imgPreview); const thumb document.getElementById(previewThumb); const err document.getElementById(previewError); if (show) { area.classList.add(show); if (isError) { thumb.classList.add(hidden); err.classList.remove(hidden); thumb.onclick null; thumb.style.cursor default; } else { if (src) thumb.src src; thumb.classList.remove(hidden); err.classList.add(hidden); thumb.onclick () > { if (pendingImageBlob) openModal(pendingImageBlob); }; thumb.style.cursor pointer; } } else { area.classList.remove(show); } } async function sendMessage(overrideText null) { if (isWaiting) return; const inputText overrideText ! null ? overrideText : userInput.value.trim(); const hasPreview document.getElementById(imgPreview).classList.contains(show); const isImageReady pendingImageDesc && pendingImageDesc.trim().length > 0; if (!inputText && !hasPreview) return; if (hasPreview && !isImageReady && overrideText null) return; let limit 2000; if (currentMode thinking) limit 7000; if (currentMode pro) limit 10000; const charCount inputText.replace(/\s/g, ).length; if (charCount > limit) { showError(`Twò long (max ${limit} karaktè san espas)`); return; } isWaiting true; actionBtn.disabled true; const userDisplayImages pendingImageBlob && !document.getElementById(previewError).classList.contains(hidden) ? : pendingImageBlob ? pendingImageBlob : ; const displayUserText overrideText ? (overrideText.includes(VOICE) ? : overrideText) : inputText; renderMessage({who: user, text: displayUserText, images: userDisplayImages, audio: overrideText && overrideText.audioUrl ? overrideText.audioUrl : null}); let finalSendText ; let contentPart ; if (hasPreview) { contentPart `IMAGE${pendingImageDesc}/IMAGE`; if (inputText) { contentPart + `\n\n${inputText}`; } } else { contentPart inputText; } if (currentMode && modeConfigcurrentMode) { finalSendText modeConfigcurrentMode.prefix + contentPart; } else { finalSendText contentPart; } userInput.value ; clearImagePreview(); toggleIcons(); if (currentMode pro) { showTyping(); let botMessage currentTypingEl; const bubble botMessage.querySelector(.bubble); let intermediate document.createElement(div); intermediate.className intermediate; bubble.appendChild(intermediate); let response document.createElement(div); response.className response; bubble.appendChild(response); let fullText ; try { const responseStream await fetch(API_WORKER, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({text: finalSendText, tfid: currentTfid}) }); if (!responseStream.ok || !responseStream.body) throw new Error(); const reader responseStream.body.getReader(); const decoder new TextDecoder(); let buffer ; while (true) { const {done, value} await reader.read(); if (done) break; buffer + decoder.decode(value, {stream: true}); const lines buffer.split(\n); buffer lines.pop(); for (const line of lines) { if (!line.trim()) continue; try { const obj JSON.parse(line); if (obj.type thought && obj.content) { intermediate.innerHTML + `div classmb-2 italic>${escapeHtml(obj.content)}/div>`; } else if (obj.type search && obj.content) { intermediate.innerHTML + `div classmb-2>strong>Recherche:/strong> ${escapeHtml(obj.content)}/div>`; } else if (obj.type error && obj.content) { intermediate.innerHTML + `div classmb-2 text-red-400>Erreur: ${escapeHtml(obj.content)}/div>`; } else if (obj.content) { response.textContent + obj.content; fullText + obj.content; } } catch (e) { response.textContent + line + \n; fullText + line + \n; } } autoScrollIfNeeded(); updateScrollToBottomButton(); } hideTyping(); if (fullText.trim()) { response.innerHTML ; response.appendChild(formatToFragment(fullText.trim())); botMessage.appendChild(createMessageFooter(fullText.trim())); } if (intermediate.innerHTML.trim() ) { intermediate.remove(); } if (fullText.includes(⩔)) { setTimeout(() > location.reload(), 1000); } } catch (e) { hideTyping(); showError(Erreur Mode Pro); } } else { showTyping(); try { await fetch(API_WORKER, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({action: chat, text: finalSendText, tfid: currentTfid}) }); await loadOrUpdateSession(); setMode(null); } catch (e) { hideTyping(); showError(Erreur envoi mesaj la); } } isWaiting false; actionBtn.disabled false; } function toggleIcons() { const hasText userInput.value.trim().length > 0; const hasPreview document.getElementById(imgPreview).classList.contains(show); const isImageReady pendingImageDesc && pendingImageDesc.trim().length > 0; const showSend hasText || hasPreview; if (showSend) { iconMic.classList.add(hidden); iconSend.classList.remove(hidden); if (hasPreview && !isImageReady) { iconSend.classList.add(dimmed); actionBtn.disabled true; } else { iconSend.classList.remove(dimmed); actionBtn.disabled false; } } else { iconSend.classList.add(hidden); iconMic.classList.remove(hidden); iconSend.classList.remove(dimmed); actionBtn.disabled false; } userInput.style.height auto; userInput.style.height Math.min(userInput.scrollHeight, 160) + px; adjustModePreviewPosition(); } async function handleActionBtn() { if (actionBtn.disabled) return; if (!iconSend.classList.contains(hidden)) { sendMessage(); } else { if (!isRecording) startRecording(); else stopRecording(); } } async function startRecording() { try { const stream await navigator.mediaDevices.getUserMedia({ audio: true }); audioChunks ; mediaRecorder new MediaRecorder(stream); mediaRecorder.ondataavailable e > audioChunks.push(e.data); mediaRecorder.onstop processRecording; mediaRecorder.start(); isRecording true; actionBtn.classList.add(recording); } catch (e) { showError(Mikwo pa mache); } } function stopRecording() { if (mediaRecorder && isRecording) { mediaRecorder.stop(); isRecording false; actionBtn.classList.remove(recording); } } async function processRecording() { const blob new Blob(audioChunks, { type: audio/webm }); const audioUrl URL.createObjectURL(blob); showTyping(); try { const res await fetch(`${API_MEDIA}/audio-to-text`, { method: POST, body: blob }); const data await res.json(); hideTyping(); if (data.text) { const hiddenText `VOICE${data.text}/VOICE`; const textObj new String(hiddenText); textObj.audioUrl audioUrl; await sendMessage(textObj); } else { showError(Pa tande vwa); } } catch(e) { hideTyping(); showError(Erreur server audio); } } mediaInput.addEventListener(change, () > { const file mediaInput.files0; if (!file || !file.type.startsWith(image/)) { clearImagePreview(); return; } const reader new FileReader(); reader.onload () > { pendingImageBlob reader.result; toggleImagePreview(true, pendingImageBlob); toggleIcons(); }; reader.readAsDataURL(file); pendingImageDesc null; toggleIcons(); imgAnalysisController new AbortController(); const timeoutId setTimeout(() > { if(imgAnalysisController) imgAnalysisController.abort(); }, 17000); fetch(`${API_MEDIA}/analize-imaj`, { method: POST, body: file, signal: imgAnalysisController.signal }) .then(async res > { clearTimeout(timeoutId); if (!res.ok) throw new Error(); const data await res.json(); if (data.response && typeof data.response string && data.response.trim().length > 0) { pendingImageDesc data.response.trim(); if (document.getElementById(imgPreview).classList.contains(show)) { toggleImagePreview(true, pendingImageBlob); toggleIcons(); } } else { throw new Error(); } }) .catch((err) > { if (err.name AbortError) return; pendingImageDesc ; if (document.getElementById(imgPreview).classList.contains(show)) { toggleImagePreview(true, pendingImageBlob, true); toggleIcons(); } }) .finally(() > { imgAnalysisController null; }); }); userInput.addEventListener(input, toggleIcons); actionBtn.addEventListener(click, handleActionBtn); document.getElementById(menuBtn).addEventListener(click, toggleMenu); document.getElementById(cancelModeBtn).addEventListener(click, (e) > { e.stopPropagation(); setMode(null); }); function openModal(src) { modalImg.src src; modal.classList.add(active); document.body.style.overflow hidden; document.querySelector(metanameviewport).setAttribute(content, widthdevice-width, initial-scale1, maximum-scale5, user-scalableyes); downloadImgBtn.onclick () > { const a document.createElement(a); a.href src; a.download adam_dh7_image.png; a.click(); }; } function closeModal() { modal.classList.remove(active); modalImg.src ; document.body.style.overflow ; document.querySelector(metanameviewport).setAttribute(content, originalViewportContent); } closeModalBtn.onclick closeModal; modal.onclick e > e.target modal && closeModal(); document.addEventListener(click, e > { const el e.target.closest(data-plain); if (el) { const txt el.getAttribute(data-plain) || el.textContent; navigator.clipboard?.writeText(txt).then(() > { el.classList.add(copied); setTimeout(() > el.classList.remove(copied), 1000); }); } if(!e.target.closest(.bottom-zone)) { closeQuickActions(); } }); document.addEventListener(gesturestart, e > e.preventDefault()); document.addEventListener(gesturechange, e > e.preventDefault()); document.addEventListener(gestureend, e > e.preventDefault()); let lastTouchEnd 0; document.addEventListener(touchend, event > { const now Date.now(); if (now - lastTouchEnd 300) { event.preventDefault(); } lastTouchEnd now; }, { passive: false }); (function init() { currentUser JSON.parse(localStorage.getItem(SESSION_KEY)); if (currentUser && currentUser.tfid) { currentTfid currentUser.tfid; showChat(); } else { changeLanguage(currentLanguage); } adjustModePreviewPosition(); updateScrollToBottomButton(); })(); /script> script> const swCode ` const CACHE ai.adamdh7; const ASSETS /, /manifest.json?v18, https://adamdh7ai.pages.dev/asset/512.png; self.addEventListener(install, e > e.waitUntil(caches.open(CACHE).then(cache > cache.addAll(ASSETS)).then(() > self.skipWaiting()))); self.addEventListener(activate, e > e.waitUntil(self.clients.claim())); self.addEventListener(fetch, e > e.respondWith(caches.match(e.request).then(res > res || fetch(e.request)))); `; if (serviceWorker in navigator) { const blob new Blob(swCode, {type: application/javascript}); const url URL.createObjectURL(blob); navigator.serviceWorker.register(url); } /script> script srchttps://pl28411310.effectivegatecpm.com/ea/14/4b/ea144be968c6dd7e5e7d97fb017c6181.js>/script> script srchttps://pl28411312.effectivegatecpm.com/43/85/cc/4385ccb8591c2726fae96ede327e635b.js>/script>/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]