Site Builder
Editing:
indexokkkk.php
writable 0666
<?php // ----------------------------------------------------------------------------- // RF Safe – Single‑Prompt Article Generator (v1.6.2 – mic+autosroll) // ----------------------------------------------------------------------------- // • Restores sidebar model selector (GPT‑3.5‑Turbo, GPT‑4o‑mini, GPT‑4) // • Keeps all form values after generation (sticky) // • Raw HTML shown inside <details> (collapsed by default) with Copy button // • Rendered Preview always populated + Copy Rendered HTML button // • NEW: Microphone button on Topic field (Web Speech API) + smooth scroll to preview // ----------------------------------------------------------------------------- // ---------- Constants & Crypto helpers ---------- const COOKIE_NAME = 'openai_key'; const COOKIE_TTL = 30 * 24 * 3600; // 30 days const SECRET = __FILE__; function encrypt_val(string $v): string { $m = 'aes-128-ctr'; $k = substr(hash('sha256', SECRET, true), 0, 16); $iv= random_bytes(openssl_cipher_iv_length($m)); return base64_encode(openssl_encrypt($v,$m,$k,0,$iv).'::'.$iv); } function decrypt_val(string $c): string { [$ct,$iv] = explode('::', base64_decode($c), 2) + [null,null]; if(!$ct||!$iv) return ''; $m='aes-128-ctr'; $k=substr(hash('sha256', SECRET, true), 0, 16); return openssl_decrypt($ct,$m,$k,0,$iv) ?: ''; } // ---------- Handle API‑key save / delete ---------- $msg=''; if ($_SERVER['REQUEST_METHOD']==='POST' && isset($_POST['save_key'])) { $raw = trim($_POST['api_key']); $ctx = stream_context_create(['http'=>['method'=>'GET','header'=>"Authorization: Bearer $raw\r\n",'timeout'=>8]]); if (@file_get_contents('https://api.openai.com/v1/models',false,$ctx)) { setcookie(COOKIE_NAME, encrypt_val($raw), time()+COOKIE_TTL, '/', '', isset($_SERVER['HTTPS']), true); header('Location: '.$_SERVER['REQUEST_URI']); exit; } $msg='❌ Invalid key.'; } if (isset($_GET['delete_key'])) { setcookie(COOKIE_NAME,'',time()-3600,'/','',isset($_SERVER['HTTPS']),true); header('Location: '.$_SERVER['PHP_SELF']); exit; } // ---------- Defaults & sticky vars ---------- $topic=$keywords=$linkurl=''; $sections=$paras=3; $lang='English'; $style='Creative'; $tone='Neutral'; $models=['gpt-3.5-turbo','gpt-4o-mini','gpt-4']; $model = in_array($_POST['model'] ?? ($_GET['model'] ?? ''), $models, true) ? ($_POST['model'] ?? $_GET['model']) : 'gpt-4o-mini'; $rawHTML=''; if ($_SERVER['REQUEST_METHOD']==='POST' && isset($_POST['generate'])) { // capture post vals for sticky $topic = trim($_POST['topic'] ?? ''); $keywords = trim($_POST['keywords'] ?? ''); $linkurl = trim($_POST['linkurl'] ?? ''); $sections = max(1, intval($_POST['sections'] ?? 3)); $paras = max(1, intval($_POST['paras'] ?? 3)); $lang = $_POST['lang'] ?? 'English'; $style = $_POST['style'] ?? 'Creative'; $tone = $_POST['tone'] ?? 'Neutral'; $model = in_array($_POST['model'] ?? '', $models, true) ? $_POST['model'] : $model; $keyCookie = $_COOKIE[COOKIE_NAME] ?? ''; $key = $keyCookie ? decrypt_val($keyCookie) : ''; if (!$key) { $msg='❌ Missing API key.'; } else { $kwText = $keywords ? " Include the following keywords naturally throughout the article: $keywords." : ''; $linkText = ($keywords && $linkurl) ? " Hyperlink each keyword exactly once to $linkurl using <a> tags." : ''; $prompt = "Write a $lang article in a $tone tone and $style style about \"$topic\". " . "Structure it into $sections sections, each starting with an <h2> and containing $paras paragraph".($paras>1?'s':'').". " . "Use additional <h3> sub‑headings if it improves readability.".$kwText.$linkText. " After the body, append <p class=\"excerpt\">Excerpt: …</p>. Return ONLY the complete HTML."; $payload=[ 'model'=>$model, 'messages'=>[['role'=>'user','content'=>$prompt]], 'max_tokens'=>max(800,$sections*$paras*180), 'temperature'=>0.7 ]; $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=>50 ]); $resp=curl_exec($ch); curl_close($ch); $data=json_decode($resp,true); $rawHTML=$data['choices'][0]['message']['content'] ?? '❌ No content returned.'; } } $langs = ['English','Spanish','German','French','Italian','Portuguese','Dutch']; $styles= ['Creative','Informative','Narrative','Persuasive','Analytical','Journalistic']; $tones = ['Neutral','Cheerful','Humorous','Assertive','Inspirational','Professional','Emotional']; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Article Generator – Promptinator</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"> <style> :root{--blue:#4f8cff;--blue-d:#275dbe;--grey-l:#f5f7fa;--radius:.75rem} body{margin:0;display:flex;min-height:100vh;font-family:system-ui,sans-serif;background:var(--grey-l)} .sidebar{flex:0 0 280px;background:#181c23;color:#fff;padding:2rem;display:flex;flex-direction:column;gap:1.25rem} .sidebar h1{margin:0;font-size:1.6rem;color:var(--blue)} .main{flex:1;padding:2rem;display:flex;justify-content:center} .panel{background:#fff;border-radius:var(--radius);box-shadow:0 4px 24px rgba(0,0,0,.08);padding:2rem;max-width:780px;width:100%;display:grid;gap:1.3rem} button.copy{background:var(--blue);color:#fff;border:none;border-radius:var(--radius);padding:.55rem 1.1rem;cursor:pointer} .preview{border:1px solid #d0d4e0;padding:1rem;border-radius:var(--radius);background:#fafbff} textarea{width:100%;min-height:130px;font-family:"Fira Code",monospace} @media(max-width:800px){body{flex-direction:column}.sidebar{width:100%;order:2}.main{order:1;padding:1rem}} </style> </head> <body> <?php $cookie=$_COOKIE[COOKIE_NAME]??''; $hasKey = $cookie && decrypt_val($cookie); ?> <div class="sidebar"> <h1>Promptinator</h1> <?php if(!$hasKey): ?> <form method="post" autocomplete="off"> <input type="password" name="api_key" placeholder="sk-..." required> <button name="save_key">Save & Login</button> <a href="https://platform.openai.com/api-keys" target="_blank" style="font-size:.9rem;color:var(--blue)">👉 Get API Key</a> </form> <small><?= $msg ?: 'Your key is stored only in your browser cookie.' ?></small> <?php else: ?> <div style="font-size:.95rem"><span style="color:#72eb99">●</span> Logged in</div> <form method="get" style="margin-bottom:1rem"> <label style="font-size:.8rem">Model <select name="model" onchange="this.form.submit()" style="margin-top:.3rem"> <?php foreach($models as $m): ?> <option value="<?= $m ?>" <?= $model===$m?'selected':''?>><?= $m ?></option> <?php endforeach; ?> </select> </label> </form> <a href="?delete_key=1" style="color:#fff;text-decoration:none;font-size:.9rem">Logout</a> <?php endif; ?> </div> <div class="main"><div class="panel"> <h2>Create an Article</h2> <?php if(!$hasKey): ?> <p>Please enter your OpenAI API key to continue.</p> <?php else: ?> <form method="post" id="frm"> <input type="hidden" name="model" value="<?= htmlspecialchars($model) ?>"> <label>Topic <div style="position: relative; display: inline-block; width: 100%;"> <input name="topic" id="topic" required value="<?= htmlspecialchars($topic,ENT_QUOTES) ?>" style="padding-right:2.5em;"> <button type="button" id="startMic" title="Speak topic" style="position:absolute;right:.5em;top:50%;transform:translateY(-50%);border:none;background:transparent;font-size:1.2em;cursor:pointer;">🎤</button> </div> </label> <label>Keywords (comma‑separated) <input name="keywords" id="keywords" value="<?= htmlspecialchars($keywords,ENT_QUOTES) ?>"></label> <label>Link URL (optional) <input name="linkurl" id="linkurl" type="url" value="<?= htmlspecialchars($linkurl,ENT_QUOTES) ?>"></label> <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1rem"> <label># Sections <select name="sections" id="sections"> <?php for($i=1;$i<=8;$i++):?><option value="<?=$i?>" <?= $sections==$i?'selected':''?>><?=$i?></option><?php endfor;?> </select></label> <label># Paragraphs / Section <select name="paras" id="paras"> <?php for($i=1;$i<=6;$i++):?><option value="<?=$i?>" <?= $paras==$i?'selected':''?>><?=$i?></option><?php endfor;?> </select></label> <label>Language <select name="lang" id="lang"> <?php foreach($langs as $l):?><option value="<?=$l?>" <?= $lang===$l?'selected':''?>><?=$l?></option><?php endforeach;?> </select></label> <label>Style <select name="style" id="style"> <?php foreach($styles as $s):?><option value="<?=$s?>" <?= $style===$s?'selected':''?>><?=$s?></option><?php endforeach;?> </select></label> <label>Tone <select name="tone" id="tone"> <?php foreach($tones as $t):?><option value="<?=$t?>" <?= $tone===$t?'selected':''?>><?=$t?></option><?php endforeach;?> </select></label> </div> <label>Prompt Preview <textarea id="prompt" readonly></textarea></label> <button type="button" class="copy" id="copyPrompt">Copy Prompt</button> <button name="generate" style="margin-top:1rem">Generate Article</button> </form> <?php if($rawHTML): ?> <details style="margin-top:1rem"><summary style="cursor:pointer;font-weight:600">Raw HTML</summary> <label style="margin-top:1rem"><textarea id="articleHTMLRaw" readonly><?= htmlspecialchars($rawHTML) ?></textarea></label> <button type="button" class="copy" id="copyRaw">Copy HTML</button> </details> <h3>Rendered Preview</h3> <div id="articlePreview" class="preview"></div> <button type="button" class="copy" id="copyRendered">Copy Rendered HTML</button> <?php endif; ?> <?php endif; ?> </div></div> <script> (function(){ const q=id=>document.getElementById(id); const promptBox=q('prompt'); // ——— SpeechRecognition setup ——— const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; if (SpeechRecognition) { const recognition = new SpeechRecognition(); recognition.lang = 'en-US'; recognition.interimResults = false; recognition.maxAlternatives = 1; const micBtn = document.getElementById('startMic'); micBtn.addEventListener('click', () => { recognition.start(); }); recognition.addEventListener('result', (evt) => { const transcript = evt.results[0][0].transcript; const topicInput = document.getElementById('topic'); topicInput.value = transcript; buildPrompt(); }); recognition.addEventListener('error', (evt) => { console.error('Speech recognition error:', evt.error); }); } else { const micBtn = document.getElementById('startMic'); if (micBtn) { micBtn.disabled = true; micBtn.title = 'Speech API not supported'; } } function buildPrompt(){ const topic=q('topic').value.trim(); if(!topic){promptBox.value='';return;} const kw=q('keywords').value.trim(); const link=q('linkurl').value.trim(); const sec=q('sections').value; const par=q('paras').value; const lang=q('lang').value; const style=q('style').value; const tone=q('tone').value; const kwTxt=kw?` Include the following keywords naturally throughout the article: ${kw}.`:''; const linkTxt=(kw && link)?` Hyperlink each keyword exactly once to ${link} using <a> tags.`:''; promptBox.value=`Write a ${lang} article in a ${tone} tone and ${style} style about "${topic}". `+ `Structure it into ${sec} sections, each starting with an <h2> and containing ${par} paragraph${par>1?'s':''}. `+ `Use <h3> sub‑headings if helpful.`+kwTxt+linkTxt+ ` After the body, append <p class="excerpt">Excerpt: …</p>. Return ONLY the HTML.`; } ['topic','keywords','linkurl','sections','paras','lang','style','tone'].forEach(id=>{const el=q(id); if(el) el.addEventListener('input',buildPrompt);}); buildPrompt(); const copy=(btnId,textFn)=>{ const btn=q(btnId); if(!btn) return; btn.addEventListener('click',()=>{ navigator.clipboard.writeText(textFn()).then(()=>{const t=btn.textContent;btn.textContent='Copied!';setTimeout(()=>btn.textContent=t,1200);}); }); }; copy('copyPrompt',()=>promptBox.value); copy('copyRaw',()=>q('articleHTMLRaw')?q('articleHTMLRaw').value:''); copy('copyRendered',()=>q('articlePreview')?q('articlePreview').innerHTML:''); // Inject rendered preview if raw exists & scroll into view <?php if($rawHTML): ?> const prev=q('articlePreview'); if(prev){ prev.innerHTML=<?php echo json_encode($rawHTML); ?>; prev.scrollIntoView({ behavior: 'smooth' }); } <?php endif; ?> })(); </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel