Siteβ―Builder
Editing:
morellll.php
writable 0666
<?php // CONFIG define('COOKIE_NAME','openai_key'); define('COOKIE_TTL', 30 * 24 * 3600); define('SECRET', __FILE__); function encrypt_val($v) { $method = 'aes-128-ctr'; $key = substr(hash('sha256', SECRET, true), 0, 16); $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method)); $ct = openssl_encrypt($v, $method, $key, 0, $iv); return base64_encode("$ct::$iv"); } function decrypt_val($c) { @list($ct, $iv) = explode('::', base64_decode($c), 2); $method = 'aes-128-ctr'; $key = substr(hash('sha256', SECRET, true), 0, 16); return openssl_decrypt($ct, $method, $key, 0, $iv); } $msg = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_key'])) { $raw = trim($_POST['api_key']); $opts = ['http' => ['method' => 'GET', 'header' => "Authorization: Bearer $raw\r\n", 'timeout' => 10]]; if (@file_get_contents('https://api.openai.com/v1/models', false, stream_context_create($opts))) { setcookie(COOKIE_NAME, encrypt_val($raw), time() + COOKIE_TTL, '/', '', isset($_SERVER['HTTPS']), true); $msg = "β Key saved!"; } else { $msg = "β Invalid key."; } } if (isset($_GET['delete_key'])) { setcookie(COOKIE_NAME, '', time() - 3600, '/', '', isset($_SERVER['HTTPS']), true); header("Location: {$_SERVER['PHP_SELF']}"); exit; } $allowed_models = ['gpt-3.5-turbo','gpt-4o-mini','gpt-4']; $allowed_types = ['B','C','Dtxt','Dnum']; $model = in_array($_GET['model'] ?? '', $allowed_models, true) ? $_GET['model'] : 'gpt-3.5-turbo'; $type = in_array($_GET['type'] ?? '', $allowed_types, true) ? $_GET['type'] : 'B'; $scope = $_GET['scope'] ?? 'general'; $word = trim($_GET['word'] ?? ''); $count = intval($_GET['count'] ?? 5); $def = intval($_GET['def'] ?? 1); $count = max(1, min(15, $count)); $def = max(1, min($count, $def)); $cookie = $_COOKIE[COOKIE_NAME] ?? ''; $key = $cookie ? decrypt_val($cookie) : ''; $items = []; $nm = preg_replace('/[^a-z0-9_]+/', '_', strtolower($word)); // β FETCH AI TOKENS (non-numeric) β if ($key && $word && $type && $type !== 'Dnum') { $payload = [ 'model' => $model, 'messages' => [ ['role' => 'system', 'content' => "You are a helpful assistant that replies ONLY with a comma-separated list of {$scope}, no extra text."], ['role' => 'user', 'content' => "List up to {$count} {$scope} variations for '{$word}'"] ], 'max_tokens' => 60, 'temperature'=> 0.3, 'stop' => ["\n"] ]; $ch = curl_init('https://api.openai.com/v1/chat/completions'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer '.$key, 'Content-Type: application/json'], CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_TIMEOUT => 15, ]); $resp = curl_exec($ch); curl_close($ch); $data = json_decode($resp, true); $raw = array_filter(array_map('trim', explode(',', $data['choices'][0]['message']['content'] ?? ''))); array_unshift($raw, $word); $items = array_slice(array_unique($raw), 0, $count); } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Promptinator</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <style> body { margin: 0; background: #f5f7fa; color: #23253a; font-family: 'Segoe UI', 'Roboto', Arial, sans-serif; min-height: 100vh; display: flex; } .sidebar { width: 330px; min-width:190px; background: #181c23; color: #fff; padding: 24px 14px 16px 14px; display: flex; flex-direction: column; align-items: flex-start; box-shadow: 2px 0 18px rgba(0,0,0,0.06); z-index: 3; height:100vh; } .sidebar h1 { font-size: 2rem; font-weight: 800; color: #4f8cff; margin-bottom:12px;} .sidebar .row { display:flex; gap:10px; width:100%; margin-bottom:10px;} .sidebar label {font-size:0.99em;} .sidebar select { flex:1; font-size:1.05em; border-radius:9px; padding:8px 4px; background: #22304a; color: #fff; border:none; min-width:0; margin:0; } .sidebar select:focus {background:#31425d;} .sidebar-shortcode { background: #23253a; color: #c4e7ff; border-radius:8px; padding: 11px 9px; font-size: 1em; font-family: 'Fira Mono', 'Menlo', 'Consolas', monospace; margin: 15px 0 0 0; min-height:36px; user-select:all; cursor:pointer; word-break:break-all; border:none; outline:none; width:100%; max-width:295px; } .sidebar-status { font-size: 1.05rem; margin-bottom: 12px;} .sidebar a.logout { width: 100%; background: #4f8cff; color:#fff; border-radius:10px; font-size:1.09em; font-weight:600; padding:10px 0; text-decoration:none; text-align:center; margin-top:12px; } .sidebar a.logout:hover { background: #275dbe;} @media (max-width:900px){.sidebar{width:100vw; min-width:0; max-width:none; height:auto;}} .main-area { margin-left:330px; width:100%; min-height:100vh; padding: 32px 0;} @media (max-width:900px){.main-area{margin-left:0;padding:16px 0;}} .main-panel { background: #fff; box-shadow: 0 4px 24px 0 rgba(20,22,37,0.12); border-radius: 18px; padding: 32px 24px 24px 24px; width: 100%; max-width: 620px; margin: 0 auto; display: flex; flex-direction: column; gap: 0.8em; animation: fadein 0.3s; } @keyframes fadein { from { opacity: 0; transform: translateY(32px);} to { opacity: 1; transform: none;} } h2 { font-size: 1.28rem; font-weight: 700; margin-bottom: 0.8em; margin-top: 0.4em;} form label { font-weight: 600;} form select, form input[type=text], form input[type=number] { padding: 12px 14px; font-size: 1.10rem; border-radius: 9px; border: 1px solid #dde2ee; margin-bottom: 10px; width: 98%; background: #f7faff; color: #23253a; transition: border .16s; } form select:focus, form input:focus { outline: none; border: 1.7px solid #4f8cff; background: #fff;} .seed-input { width: 99%; font-size: 1.12em; border-radius: 11px; border: 1.5px solid #b3d1ff; padding: 14px 14px; margin: 8px 0 18px 0;} .seed-input:focus { border: 1.5px solid #4f8cff; background: #f6faff;} .tooltip { display: inline-block; font-size: 1.09em; color: #4f8cff; margin-left: 6px; cursor: pointer;} #tokens-section h3 { font-size:1.09em; font-weight:700;} #tokens { margin-bottom:10px;} .token { font-size: 1.07em; background: #eaf2ff; color: #3256a8; font-weight: 600; padding: 9px 17px; border-radius: 18px; margin: 7px 10px 7px 0; display: inline-block; cursor:pointer;} .token span { font-size: 1.1em; font-weight: 700; margin-left: 12px; color: #d04a3f;} button, input[type=submit], #gen, .change-default { background: #4f8cff; color: #fff; font-size: 1.08em; border: none; border-radius: 9px; padding: 10px 20px; margin-top: 10px; margin-bottom: 6px; cursor: pointer; box-shadow: 0 1.5px 7px rgba(79,140,255,0.08); transition: background 0.12s; } button:hover, input[type=submit]:hover, #gen:hover { background: #275dbe;} pre { font-family: 'Fira Mono', 'Menlo', 'Consolas', monospace; font-size: 1.09em; background: #181c23; color: #f5f7ff; border-radius: 10px; margin: 11px 0 0 0; padding: 12px 14px; box-shadow: 0 2px 10px rgba(20,22,37,0.07); overflow-x: auto;} #modal { display:none; position:fixed; left:0; top:0; right:0; bottom:0; background:rgba(0,0,0,0.19); align-items:center; justify-content:center; z-index:9;} #modal .inner { background:#fff; border-radius:12px; padding:20px 15px 18px 15px; text-align:center; max-width:310px;} #picker-tokens { margin:10px 0 4px 0;} #picker-tokens .token { margin: 6px 8px 6px 0; padding: 10px 18px; background: #edf5ff; color: #2959ad; border: 2px solid #e7eaf5; border-radius: 15px; font-size: 1.09em;} #picker-tokens .token:hover { border: 2px solid #4f8cff; background: #dbecff;} </style> </head> <body> <div class="sidebar"> <h1>Promptinator</h1> <div style="width:100%;"> <?php if(!$key): ?> <form method="post" autocomplete="off"> <input type="password" name="api_key" placeholder="sk-..." required> <button name="save_key">Save & Login</button> </form> <div class="muted">Your API key stays in your browser cookie.</div> <?php else: ?> <div class="sidebar-status"> <span style="color:#72eb99;">β</span> Logged in </div> <div class="row"> <form id="sidebar-model-form" style="flex:1;"> <label style="font-size:0.98em;">Model</label> <select id="sidebar-model" name="model"> <option value="gpt-3.5-turbo"<?= $model==='gpt-3.5-turbo'?' selected':''?>>GPT-3.5 Turbo</option> <option value="gpt-4o-mini"<?= $model==='gpt-4o-mini'?' selected':''?>>GPT-4.1 Mini</option> <option value="gpt-4"<?= $model==='gpt-4'?' selected':''?>>GPT-4</option> </select> </form> <form id="sidebar-type-form" style="flex:1;"> <label style="font-size:0.98em;">Type</label> <select id="sidebar-type" name="type"> <option value="B"<?= $type==='B'?' selected':'' ?>>Radio</option> <option value="C"<?= $type==='C'?' selected':'' ?>>Checkbox</option> <option value="Dtxt"<?= $type==='Dtxt'?' selected':'' ?>>Dropdown Text</option> <option value="Dnum"<?= $type==='Dnum'?' selected':'' ?>>Dropdown Numeric</option> </select> </form> </div> <label style="margin-top:1em; font-weight:500;">Shortcode Preview</label> <pre id="sidebar-shortcode" class="sidebar-shortcode"></pre> <?php endif; ?> </div> <?php if($key): ?> <a href="?delete_key=1" class="logout">Logout</a> <?php endif; ?> </div> <div class="main-area"> <div class="main-panel"> <?php if($key): ?> <h2>Configure Promptinator</h2> <form id="cfg" method="get"> <input type="hidden" id="model" name="model" value="<?=htmlspecialchars($model)?>"> <input type="hidden" id="type" name="type" value="<?=htmlspecialchars($type)?>"> <div id="ai-fields" style="display:none;"> <div id="relation-row"> <label>Relation</label> <select id="scope" name="scope" style="width:98%"> <option value="general"<?= $scope==='general'?' selected':'' ?>>General</option> <option value="broad"<?= $scope==='broad'?' selected':'' ?>>Broad</option> <option value="narrow"<?= $scope==='narrow'?' selected':'' ?>>Narrow</option> <option value="longtail"<?= $scope==='longtail'?' selected':'' ?>>Long-tail</option> <option value="shorttail"<?= $scope==='shorttail'?' selected':'' ?>>Short-tail</option> </select> </div> <div id="count-row"> <label>Count</label> <select id="count" name="count" style="width:98%"> <?php for($i=1; $i<=15; $i++): ?> <option value="<?=$i?>"<?=$i===$count?' selected':''?>><?=$i?></option> <?php endfor; ?> </select> </div> <div id="seed-box"> <label for="seed" class="biglabel"> Seed <span class="tooltip" title="Enter your main keyword or phrase.">?</span> </label> <input id="seed" name="word" value="<?=htmlspecialchars($word)?>" class="seed-input" autocomplete="off"> <button id="gen">Generate</button> </div> </div> <div id="num-box" style="display:none;"> <label>Max</label><input id="max" type="number" min="1" max="15" value="<?= $count ?>"><br> <label>Default</label><input id="def" type="number" min="1" max="<?= $count ?>" value="<?= $def ?>"><br> <label>Option Name</label><input id="opt" type="text" placeholder="optional"><br> </div> </form> <div id="tokens-section"> <h3>Tokens</h3> <div id="tokens"></div> <button id="change" class="change-default">Change Default</button> </div> <h3 style="margin-bottom:0.4em;margin-top:1.3em;">Shortcode Preview</h3> <pre id="shortcode"></pre> <div id="modal"><div class="inner"> <h3>Select new default</h3> <div id="picker-tokens"></div> </div></div> <?php endif; ?> </div> </div> <script> (() => { const typeEl = document.getElementById('type'), aiFields = document.getElementById('ai-fields'), relation = document.getElementById('relation-row'), countRow = document.getElementById('count-row'), seedBox = document.getElementById('seed-box'), numBox = document.getElementById('num-box'), tokensSec= document.getElementById('tokens-section'), countEl = document.getElementById('count'), maxEl = document.getElementById('max'), defEl = document.getElementById('def'), optEl = document.getElementById('opt'), tokensEl = document.getElementById('tokens'), scEl = document.getElementById('shortcode'), changeBtn= document.getElementById('change'), genBtn = document.getElementById('gen'), nm = "<?= $nm ?>", modal = document.getElementById('modal'), picker = document.getElementById('picker-tokens'), sidebarModel = document.getElementById('sidebar-model'), sidebarType = document.getElementById('sidebar-type'), sidebarShortcode = document.getElementById('sidebar-shortcode'), mainModelInput = document.getElementById('model'), mainTypeInput = document.getElementById('type'); let items = <?= json_encode($items) ?>; function renderTokens() { tokensEl.innerHTML = ''; items.forEach((t,i) => { const sp = document.createElement('span'); sp.className = 'token'; sp.textContent = t; const x = document.createElement('span'); x.textContent = 'Γ'; x.onclick = (e) => { e.stopPropagation(); items.splice(i,1); renderTokens(); update(); }; sp.appendChild(x); tokensEl.appendChild(sp); }); } function update() { const t = mainTypeInput.value, ps = items.join('|'), df = items[0]||'', cnt= parseInt(countEl?.value || "5",10), mx = parseInt(maxEl?.value || "5",10), dm = parseInt(defEl?.value || "1",10), opt= optEl?.value||nm; let prefix = t; if (t==='Dtxt' || t==='Dnum') prefix = 'D'; let sc = ''; if (prefix==='D' && t==='Dnum') { const nums = []; for(let i=1;i<=mx;i++) nums.push(i.toString()); items = nums; renderTokens(); sc = `[D-${opt}-${mx}~${dm}~]`; } else if (prefix==='D') { sc = `[D-${opt}-|${ps}|~${df}~]`; } else if (items.length) { sc = `[${prefix}-${opt}-|${ps}|~${df}~]`; } scEl.textContent = sc; if (sidebarShortcode) sidebarShortcode.textContent = sc; } function syncFields() { const t = mainTypeInput.value; if (!t) { aiFields.style.display = 'none'; numBox.style.display = 'none'; tokensSec.style.display= 'none'; return; } const isNum = t === 'Dnum'; aiFields.style.display = isNum ? 'none' : 'block'; numBox.style.display = isNum ? 'block' : 'none'; tokensSec.style.display = isNum ? 'none' : 'block'; update(); } if (mainTypeInput) mainTypeInput.onchange = syncFields; window.addEventListener('DOMContentLoaded', syncFields); // Model and Type sync (sidebar <-> main) if (sidebarModel && mainModelInput) { sidebarModel.onchange = function() { mainModelInput.value = this.value; document.getElementById('cfg').submit(); } } if (sidebarType && mainTypeInput) { sidebarType.onchange = function() { mainTypeInput.value = this.value; document.getElementById('cfg').submit(); } } if (countEl) countEl.onchange = () => document.getElementById('cfg').submit(); [maxEl, defEl, optEl].forEach(el=>el && (el.oninput=update)); if (genBtn) genBtn.onclick = e=>{e.preventDefault(); if(mainTypeInput.value!=='Dnum') document.getElementById('cfg').submit();}; // Dynamic Change Default: popover with token buttons if (changeBtn) changeBtn.onclick = () => { picker.innerHTML = ''; items.forEach((t, i) => { const tok = document.createElement('span'); tok.className = 'token'; tok.textContent = t; tok.onclick = () => { items.splice(i,1); items.unshift(t); renderTokens(); update(); modal.style.display = 'none'; }; picker.appendChild(tok); }); modal.style.display = 'flex'; }; if (modal) modal.onclick = e => { if(e.target===modal) modal.style.display='none'; }; renderTokens(); update(); syncFields(); })(); </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel