Site Builder
Editing:
tools-promptinator2.php
writable 0666
<?php /************************************************************************** * Promptinator — Business AI tool * Path: /ai-tools/business-tools/promptinator/tools-promptinator.php * (c) BestDealOn 2025 **************************************************************************/ require_once $_SERVER['DOCUMENT_ROOT'].'/members/lib/auth.php'; require_login(); /* ---------- CONFIG ---------------------------------------------------- */ define('COOKIE_NAME','openai_key'); define('COOKIE_TTL',30*24*3600); // 30 days define('SECRET',__FILE__); // salt for AES /* ---------- tiny AES helpers ----------------------------------------- */ function enc($v){ $k=substr(hash('sha256',SECRET,true),0,16); $iv=random_bytes(16); return base64_encode(openssl_encrypt($v,'aes-128-ctr',$k,0,$iv)."::$iv"); } function dec($c){ [$ct,$iv]=explode('::',base64_decode($c),2)+[null,null]; if(!$ct||!$iv) return ''; $k=substr(hash('sha256',SECRET,true),0,16); return openssl_decrypt($ct,'aes-128-ctr',$k,0,$iv); } /* ---------- save / delete key ---------------------------------------- */ $msg=''; if($_SERVER['REQUEST_METHOD']==='POST' && isset($_POST['save_key'])){ $raw=trim($_POST['api_key']??''); $ctx=['http'=>[ 'method'=>'GET', 'header'=>"Authorization: Bearer $raw\r\n", 'timeout'=>8 ]]; if(@file_get_contents('https://api.openai.com/v1/models',false,stream_context_create($ctx))){ setcookie(COOKIE_NAME,enc($raw),time()+COOKIE_TTL,'/','',isset($_SERVER['HTTPS']),true); header('Location: '.$_SERVER['REQUEST_URI']); exit; } $msg='❌ Invalid key.'; } if(isset($_GET['logout'])){ setcookie(COOKIE_NAME,'',time()-3600,'/','',isset($_SERVER['HTTPS']),true); header('Location: '.$_SERVER['PHP_SELF']); exit; } /* ---------- UI params ------------------------------------------------- */ $models = ['gpt-3.5-turbo','gpt-4o-mini','gpt-4']; $types = ['B'=>'Radio','C'=>'Checkbox','Dtxt'=>'Dropdown Text']; $model = in_array($_GET['model']??'',$models,true) ? $_GET['model'] : 'gpt-3.5-turbo'; $type = array_key_exists($_GET['type']??'',$types) ? $_GET['type'] : 'B'; $scope = $_GET['scope'] ?? 'general'; $word = trim($_GET['word'] ?? ''); $count = max(1,min(15,intval($_GET['count'] ?? 5))); $key = ($_COOKIE[COOKIE_NAME]??'') ? dec($_COOKIE[COOKIE_NAME]) : ''; /* ---------- call OpenAI when we have everything ----------------------- */ $tokens=[]; if($key && $word){ $payload=[ 'model'=>$model, 'messages'=>[ ['role'=>'system','content'=>'You are a helpful assistant that replies ONLY with a comma‑separated list of '.$scope.' ideas, no extra text.'], ['role'=>'user','content'=>"List up to {$count} {$scope} variations for '{$word}' – give ONLY the list."] ], '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); $txt=preg_replace('/[\r\n"]+/','',json_decode($resp,true)['choices'][0]['message']['content']??''); $raw=array_filter(array_map('trim',explode(',',$txt))); array_unshift($raw,$word); $tokens=array_slice(array_unique($raw),0,$count); } ?> <!doctype html> <html lang=en> <meta charset=utf-8> <title>Promptinator – BestDealOn</title> <meta name=viewport content="width=device-width,initial-scale=1"> <link rel=stylesheet href="/members/css/dashboard-shell.css?v=3"><!-- gold header + breadcrumb --> <style> /* --- colour tokens (same palette as AI Toolbox) --- */ :root{ --c-bg:#f0f3fb; --c-card:#ffffff; --c-blue:#0066ff; --c-blue-d:#004ed7; --c-gold:#ffb63b; --c-dark:#0f111a; --br:22px; font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif; } body{background:var(--c-bg);margin:0} .wrap{max-width:1120px;margin:0 auto;padding:2rem 1rem;display:grid;gap:2.2rem;grid-template-columns:320px 1fr} @media(max-width:900px){.wrap{grid-template-columns:1fr}.side{order:2}.main{order:1}} /* --- sidebar --- */ .side{ background:var(--c-dark);color:#fff;border-radius:var(--br);padding:2rem 1.7rem; display:flex;flex-direction:column;gap:1.3rem;min-height:430px;opacity:<?= $key?1:0 ?>;transition:opacity .3s } .side h2{margin:0 0 .2rem;font-size:1.6rem;color:var(--c-gold)} .status{display:flex;align-items:center;gap:.55rem;font-size:.95rem} .status i{display:inline-block;width:.55rem;height:.55rem;background:#72eb99;border-radius:50%} .side label{font-weight:600;margin:.8rem 0 .25rem;font-size:.95rem} .side select{width:100%;padding:.65rem .75rem;border-radius:12px;background:#192035;color:#fff;border:none;font-size:.95rem} .side button{padding:.8rem 1rem;border:none;border-radius:14px;font-weight:700;font-size:1rem;cursor:pointer} .btn-blue{background:var(--c-blue);color:#fff} .btn-blue:hover{background:var(--c-blue-d)} .btn-grey{background:#384050;color:#fff} .btn-grey:hover{background:#495266} .side a.logout{margin-top:auto;color:var(--c-blue);text-align:center;text-decoration:none;font-weight:600} /* --- main card --- */ .main{background:var(--c-card);border-radius:var(--br);padding:2.5rem 2rem;box-shadow:0 8px 26px #0001} .main h3{margin-top:0;font-size:1.55rem} form.grid{display:grid;grid-template-columns:1fr 1fr;gap:1.4rem} @media(max-width:600px){form.grid{grid-template-columns:1fr}} form.grid label{font-weight:600;font-size:.95rem;margin-bottom:.25rem;display:block} form.grid input[type=text],form.grid select{width:100%;padding:.7rem .8rem;border:1px solid #cdd5e6;border-radius:12px;font-size:1rem} #gen{grid-column:1/-1;width:max-content;padding:.8rem 2.2rem} .tokens{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:.5rem;margin-top:.4rem} .token{background:#eaf2ff;color:#3256a8;padding:.45em 1.45em .45em .9em;border-radius:1.5em;font-weight:600;position:relative} .token .x{position:absolute;right:6px;top:1px;cursor:pointer;font-weight:700;color:#d04a3f} #shortcode{grid-column:1/-1;background:#0f111a;color:#fff;border-radius:14px;padding:1.3rem;font-size:1rem;white-space:pre-wrap;direction:ltr} .muted{font-size:.9rem;color:#999} #msg{color:#d91c31;font-weight:600} </style> <body> <?php /* gold header / crumb (re‑use members shell) */ ?> <?php include $_SERVER['DOCUMENT_ROOT'].'/members/partials/breadcrumb.php'; // echoBreadcrumb('Promptinator','/ai-tools/tools.php'); ?> <div class=wrap> <!-- ASIDE ------------------------------------------------------ --> <aside class=side <?= $key?'':'style="pointer-events:none"'?>> <h2>Promptinator</h2> <?php if(!$key): ?> <form method=post autocomplete=off> <label for=api>OpenAI key</label> <input id=api type=password name=api_key placeholder="sk-..." required style="width:100%;padding:.7rem .8rem;border-radius:12px;border:none"> <button class="btn-blue" name=save_key>Save & Login</button> <p id=msg><?= $msg ?></p> <p class=muted> Your key is AES‑encrypted, stored only in your browser for 30 days.<br> <a href="https://platform.openai.com/api-keys" target="_blank" style="color:var(--c-gold)">Where do I find my key?</a> </p> </form> <?php else: ?> <p class=status><i></i><span role=status>API key saved</span></p> <label for=mdl>Model</label> <select id=mdl onchange="switchOpt('model',this.value)"> <?php foreach($models as $m): ?> <option value="<?=$m?>" <?=$m===$model?'selected':''?>><?=$m?></option> <?php endforeach ?> </select> <label for=ctl>Control type</label> <select id=ctl onchange="switchOpt('type',this.value)"> <?php foreach($types as $k=>$v): ?> <option value="<?=$k?>" <?=$k===$type?'selected':''?>><?=$v?></option> <?php endforeach ?> </select> <button id=copy class="btn-blue" disabled>Copy Shortcode</button> <button id=copyCsv class="btn-grey" style="display:none">Copy CSV</button> <a class=logout href="?logout=1">Log out</a> <?php endif; ?> </aside> <!-- MAIN ------------------------------------------------------- --> <main class=main> <?php if(!$key): ?> <h3>Get started</h3> <p>Save your API key on the left to unlock Promptinator.</p> <?php else: ?> <h3>Generate options</h3> <form id=cfg class=grid method=get autocomplete=off> <input type=hidden name=model value="<?=htmlspecialchars($model)?>"> <input type=hidden name=type value="<?=htmlspecialchars($type)?>"> <div style="grid-column:1/-1"> <label for=word>Seed word 🎤</label> <input id=word type=text name=word value="<?=htmlspecialchars($word)?>" placeholder="e.g. shoes" required> </div> <div> <label for=scope>Relation</label> <select id=scope name=scope> <?php foreach(['general','broad','narrow','longtail','shorttail'] as $s): ?> <option value="<?=$s?>" <?=$s===$scope?'selected':''?>><?=$s?></option> <?php endforeach ?> </select> </div> <div> <label for=count>Count</label> <select id=count name=count> <?php for($i=1;$i<=15;$i++): ?> <option value="<?=$i?>" <?=$i===$count?'selected':''?>><?=$i?></option> <?php endfor ?> </select> </div> <button id=gen class="btn-blue">Generate</button> <div class=tokens id=tokens> <?php foreach($tokens as $t): ?> <span class=token><?=htmlspecialchars($t)?><span class=x>×</span></span> <?php endforeach ?> </div> <div style="grid-column:1/-1"> <label for=default>Select default value</label> <select id=default> <?php foreach($tokens as $t): ?> <option value="<?=htmlspecialchars($t)?>"><?=htmlspecialchars($t)?></option> <?php endforeach ?> </select> </div> <pre id=shortcode dir=ltr></pre> </form> <?php endif;?> </main> </div><!-- /.wrap --> <script> /* ---------------------------------------------------------- switch model/type without losing query params ---------------------------------------------------------- */ function switchOpt(key,val){ const url=new URL(location.href); url.searchParams.set(key,val); location.href=url.toString(); } /* ---------------------------------------------------------- JS only when key present ---------------------------------------------------------- */ <?php if($key): ?> (()=>{ const tokensDiv = document.getElementById('tokens'); const scEl = document.getElementById('shortcode'); const copyBtn = document.getElementById('copy'); const copyCsvBtn = document.getElementById('copyCsv'); const defSel = document.getElementById('default'); let tokens = <?= json_encode($tokens) ?>; const type = "<?= $type ?>"; const wordIn = document.getElementById('word'); /* helpers */ const render = ()=>{ tokensDiv.innerHTML=''; tokens.forEach((t,i)=>{ const el=document.createElement('span'); el.className='token'; el.textContent=t; const x=document.createElement('span'); x.className='x'; x.textContent='×'; x.onclick=()=>{tokens.splice(i,1);render();}; el.appendChild(x); tokensDiv.appendChild(el); }); /* default picker */ defSel.innerHTML=''; tokens.forEach(t=>{ const o=document.createElement('option');o.value=t;o.text=t;defSel.appendChild(o); }); updateCode(); toggleCsv(); }; const updateCode=()=>{ if(!tokens.length){scEl.textContent='';copyBtn.disabled=true;return;} copyBtn.disabled=false; const prefix=type==='Dtxt'?'D':type; const def=tokens[0]; scEl.textContent=`[${prefix}-${wordIn.value||'seed'}-|${tokens.join('|')}|~${def}~]`; }; const toggleCsv=()=>{copyCsvBtn.style.display=tokens.length?'block':'none';}; /* events */ document.getElementById('gen').onclick=e=>{ if(!wordIn.value.trim()) return; }; copyBtn.onclick=()=>{navigator.clipboard.writeText(scEl.textContent) .then(()=>copyBtn.textContent='Copied!') .finally(()=>setTimeout(()=>copyBtn.textContent='Copy Shortcode',1500));}; copyCsvBtn.onclick=()=>{navigator.clipboard.writeText(tokens.join(', ')) .then(()=>copyCsvBtn.textContent='Copied CSV!') .finally(()=>setTimeout(()=>copyCsvBtn.textContent='Copy CSV',1500));}; defSel.onchange=()=>{ const sel=defSel.value; tokens=[sel,...tokens.filter(x=>x!==sel)]; render(); }; render(); })(); <?php endif;?> </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel