let open_ai_response;// Apply some modern styles to the body
document.body.style.fontFamily ="'Segoe UI', Tahoma, Geneva, Verdana, sans-serif";
document.body.style.margin ="0";
document.body.style.padding ="20px";
document.body.style.backgroundColor ="#22092C !important";// Create a futuristic-looking title for the pageconst pageTitle = document.createElement("h1");
pageTitle.textContent ="AI TaleForge: ChatGPT & DALL-E Craft 4 Images, 1 Line, Endless Stories";
pageTitle.style.textAlign ="center";
pageTitle.style.color ="#4caf50";// Green color
pageTitle.style.fontFamily ="'Orbitron', sans-serif";// Futuristic font
pageTitle.style.fontSize ="36px";
pageTitle.style.marginBottom ="20px";
pageTitle.style.transition ="transform 0.3s ease-in-out";// Add transition effect
pageTitle.style.borderBox ="border-box";// Add box-sizing property// Add a mouseover event to create a 3D effect on hover
pageTitle.addEventListener("mouseover",()=>{
pageTitle.style.transform ="rotateX(10deg)";// Adjust the rotation angle as needed});// Add a mouseout event to reset the transform on mouse leave
pageTitle.addEventListener("mouseout",()=>{
pageTitle.style.transform ="rotateX(0)";});// Apply additional styles
pageTitle.style.backgroundColor ="#22092C";// Background color
pageTitle.style.padding ="20px";// Padding
pageTitle.style.boxShadow ="0 0 10px rgba(0, 0, 0, 0.1)";// Box shadow// Typing effectconst titleText = pageTitle.textContent;
pageTitle.textContent ="";// Clear the initial text// Function to simulate typing effectfunction typeText(index){if(index <= titleText.length){
pageTitle.textContent = titleText.slice(0, index);
setTimeout(()=>{
typeText(index +1);},100);// Adjust the typing speed (milliseconds)}}// Trigger the typing effect after a delay (e.g., 500 milliseconds)
setTimeout(()=>{
typeText(0);},500);// Append the title to the document
document.body.appendChild(pageTitle);// Updated styles for the dropdownconst dropdownStyles =`.dropdown-container {
position: relative;
margin:0auto;
width:500px;/* Adjust the width as needed */
text-align: center;
margin-top:20px;}.model-dropdown {
width:100%;
padding:8px;
font-size:24px;/* Adjust font size for better readability */
border:1px solid #4caf50;/* Green border */
border-radius:10px;
background:#D5BDAF;/* Dark background color */
color:#000000;/* Green text color */
appearance: none;/* Remove default dropdown arrow */
cursor: pointer;
outline: none;/* Remove focus outline */
transition: background 0.3s, border 0.3s;
animation: fadeIn 0.5s ease-out;/* Add fadeIn animation */
text-align: center;
font-family:'Roboto', sans-serif;/* Change the font to Roboto */
font-weight:500;/* Increase font weight for a bolder look */
position: relative;/* Added position relative */
overflow: hidden;/* Hide overflow for animation */}.model-dropdown option {
background-color:#D5BDAF;/* Dark background color */
color:#000000;/* Green text color */
padding:8px;
font-size:24px;/* Adjust font size for better readability */
text-align: center;
font-family:'Roboto', sans-serif;/* Change the font to Roboto */
font-weight:500;/* Increase font weight for a bolder look */
white-space: nowrap;/* Prevent text from wrapping */
overflow: hidden;/* Hide overflow for animation */
animation: typeWriter 2s steps(30, end);/* Reverse typing animation */}.model-dropdown:hover {
background:#4caf50;/* Green background color on hover */
border:1px solid #fff;/* White border on hover */}.model-dropdown:focus {
background:#4caf50;/* Green background color on focus */
border:1px solid #fff;/* White border on focus */}.model-dropdown::after {
content:'';
border-style: solid;
border-width:8px8px0;
border-color:#000000 transparent transparent transparent;
position: absolute;
top: calc(50%-4px);
right:15px;
transition: transform 0.3s ease-in-out;/* Added transition for animation */
transform: scaleY(1);/* Initial transform state */}.model-dropdown:hover::after {
transform: scaleY(0);/* Final transform state on hover */}@keyframes fadeIn {
from {
opacity:0;}
to {
opacity:1;}}@keyframes typeWriter {
from {
width:0;}
to {
width:auto;}}`;// Create a style element and append it to the headconst dropdownStyleElement = document.createElement("style");
dropdownStyleElement.textContent = dropdownStyles;
document.head.appendChild(dropdownStyleElement);// Create a container for the dropdownconst dropdownContainer = document.createElement("div");
dropdownContainer.classList.add("dropdown-container");// Create a dropdown for selecting the modelconst modelDropdown = document.createElement("select");
modelDropdown.classList.add("model-dropdown");// Add options for DALL-E 2 and DALL-E 3const dalle2Option = document.createElement("option");
dalle2Option.value ="dall-e-2";
dalle2Option.textContent ="DALL-E 2";
modelDropdown.appendChild(dalle2Option);const dalle3Option = document.createElement("option");
dalle3Option.value ="dall-e-3";
dalle3Option.textContent ="DALL-E 3";
modelDropdown.appendChild(dalle3Option);// Append the dropdown to the container
dropdownContainer.appendChild(modelDropdown);// Append the container to the body
document.body.appendChild(dropdownContainer);// Append the title to the body
document.body.appendChild(pageTitle);// Create an input field for the user to enter the one-line storyconst userInput = document.createElement("input");
userInput.type ="text";
userInput.placeholder ="Enter one-line story";
userInput.style.width ="100%";
userInput.style.padding ="10px";
userInput.style.margin ="20px auto";
userInput.style.fontSize ="16px";
userInput.style.border ="1px solid #ccc";
userInput.style.borderRadius ="5px";
document.body.appendChild(userInput);const userAPIkey = document.createElement("input");
userAPIkey.type ="text";
userAPIkey.placeholder ="Enter OPEN AI API Key";
userAPIkey.style.width ="100%";
userAPIkey.style.padding ="10px";
userAPIkey.style.margin ="20px auto";
userAPIkey.style.fontSize ="16px";
userAPIkey.style.border ="1px solid #ccc";
userAPIkey.style.borderRadius ="5px";
document.body.appendChild(userAPIkey);// Create a button to trigger the generation based on the user's inputconst generateButton = document.createElement("button");
generateButton.textContent ="Generate Image";
generateButton.style.width ="100%";
generateButton.style.padding ="10px";
generateButton.style.margin ="10px auto";
generateButton.style.fontSize ="16px";
generateButton.style.cursor ="pointer";
generateButton.style.background ="#872341";
generateButton.style.color ="white";
generateButton.style.border ="none";
generateButton.style.borderRadius ="5px";// Add margin to separate from the input
generateButton.addEventListener("click",(event)=>{
event.preventDefault();// Prevent default form submission behaviorconst openAPIKey = userAPIkey.value;const oneLineStory = userInput.value;const model=modelDropdown.value;
generatePrompts(oneLineStory,model,openAPIKey);});// Container to display generated promptsconst promptContainer = document.createElement("div");
promptContainer.style.width ="80%";
promptContainer.style.margin ="20px auto";
promptContainer.style.padding ="20px";
promptContainer.style.background ="#f8f8f8";
promptContainer.style.borderRadius ="5px";
promptContainer.style.boxShadow ="0 0 10px rgba(0, 0, 0, 0.1)";
document.body.appendChild(userInput);
document.body.appendChild(modelDropdown);
document.body.appendChild(generateButton);
document.body.appendChild(promptContainer);// Function to get ChatGPT response// Create a loading spinnerconst loadingSpinner = document.createElement("div");
loadingSpinner.classList.add("loader");
document.body.appendChild(loadingSpinner);
async function getChatGPTResponse(prompt,openAPIKey){const chatGPTApiKey = openAPIKey;const chatGPTUrl ="https://api.openai.com/v1/chat/completions";
loadingSpinner.style.display ="block";const chatGPTData = JSON.stringify({
model:"gpt-3.5-turbo",
messages:[{ role:"system", content:"You are story teller who follows below template and provide dalle 2 prompts, Make sure that you strictly follow below the template"},{ role:"user", content: prompt },],});const chatGPTResponse = await fetch(chatGPTUrl,{
method:"POST",
headers:{"Content-Type":"application/json","Authorization":`Bearer ${chatGPTApiKey}`,},
body: chatGPTData,});const chatGPTResult = await chatGPTResponse.json();
loadingSpinner.style.display ="none";const generatedPrompt = chatGPTResult.choices[0].message.content;// Display generated prompt in UIconst promptElement = document.createElement("p");
promptElement.textContent =`UsingChatGPT API GeneratedDalle2Prompt: ${generatedPrompt}`;
promptContainer.appendChild(promptElement);return generatedPrompt;}// Function to generate prompts for DALL-E 2
async function generatePrompts(oneLineStory,model,openAPIKey){// Call ChatGPT to get a responseconst title = oneLineStory;// Use user's input as the titleconst promptTemplate =`Title: ${title}Prompt:[Line1:Introduce the setting or context of StoryTitle.Describe the visual elements you want in the image (e.g., colors, shapes, objects, scenes)(max 250 characters)][Line2:Introduce the main character and their goal or challenge .Specify any particular style or mood (e.g., surreal, vibrant, calm)(max 250 characters)][Line3:Add a twist or complication to the story .Additional details to refine the visual concept (max 250 characters)][Line4:Describe a critical moment or turning point .Any specific constraints or requirements for the image(max 250 characters)]Description:Create an image that captures the essence of [Title of the VisualConcept].Emphasize[visual elements], ensuring a [specified style or mood].Pay attention to [additional details]while adhering to [constraints or requirements]`;// Call ChatGPT to get a responseconst chatGPTResponse = await getChatGPTResponse(promptTemplate,openAPIKey);// Limit the length of the generated promptconst truncatedPrompt = chatGPTResponse;// Use regex to split the prompt into four linesconst lineRegex =/\[Line (\d+): (.+?)\]/g;
let match;const lines =[];while((match = lineRegex.exec(truncatedPrompt))!==null){
lines.push(match[2]);}// Check if the lines array is emptyif(lines.length ===0){// Recall generatePrompts with the same parameters
await generatePrompts(oneLineStory, model, openAPIKey);return;// Exit the current invocation}
console.log(lines)// Display the formatted prompts in the UIfor(let i =0; i <4; i++){const formattedPrompt = lines[i];// Display the formatted prompt in the UIconst promptElement = document.createElement("p");
loadingSpinner.style.display ="block";
promptElement.textContent =`GeneratedPrompt ${i +1}:\n${formattedPrompt}`;//promptContainer.appendChild(promptElement);// Call DALL-E 2 with the formatted prompt//try{
await generateImageWithPrompt(formattedPrompt,model,openAPIKey);}//catch(error){console.log("Maximum retries reached. Unable to generate image.");}
loadingSpinner.style.display ="none";//}}const maxRetries =50;
let currentRetry =0;
async function generateImageWithPrompt(prompt, model,openAPIKey){// Show loading spinner while waiting for the response
loadingSpinner.style.display ="block";
console.log(model)const DALLE2ApiKey = openAPIKey;const DALLE2Url ="https://api.openai.com/v1/images/generations";const DALLE2Data = JSON.stringify({
model: model,
prompt: prompt,});try{const response = await fetch(DALLE2Url,{
method:"POST",
headers:{"Content-Type":"application/json","Authorization":`Bearer ${DALLE2ApiKey}`,},
body: DALLE2Data,});// Check if the response indicates a rate limit errorif(response.status ===429){// Implement exponential backoffconst delay =Math.pow(2, currentRetry)*1000;// Backoff in milliseconds
currentRetry++;// Wait for the specified delay
await newPromise(resolve => setTimeout(resolve, delay));// Retry the requestreturn generateImageWithPrompt(prompt, model,openAPIKey);}// Handle the response as neededconst DALLE2Result = await response.json();// Log DALL-E 2 result for debugging
console.log("DALL-E 2 Result:", DALLE2Result);// Display the generated image with a borderconst imageURL = DALLE2Result.data[0].url;const img = document.createElement("img");
img.src = imageURL;
img.style.border ="1px solid #ccc";// Add a border to the image
img.style.marginTop ="10px";// Add margin to separate images
document.body.appendChild(img);}catch(error){// Handle other errors if neededif(currentRetry >= maxRetries){
console.log("Maximum retries reached. Unable to generate image.");// You can handle this situation as needed, e.g., display a message to the user.}else{
console.log("Error generating image with prompt:", error.message);// Log the warning, but don't propagate the error}} finally {// Hide loading spinner once the response is received
loadingSpinner.style.display ="none";}}// Add styles for the loading spinnerconst spinnerStyles =`.loader {
display: none;
border:8px solid #f3f3f3;
border-top:8px solid #3498db;
border-radius:50%;
width:50px;
height:50px;
animation: spin 1s linear infinite;
position: fixed;
top:50%;
left:50%;
transform: translate(-50%,-50%);
z-index:1000;/* Ensure the spinner is on top of other elements */}@keyframes spin {0%{ transform: rotate(0deg);}100%{ transform: rotate(360deg);}}`;const spinnerStyleElement = document.createElement("style");
spinnerStyleElement.textContent = spinnerStyles;
document.head.appendChild(spinnerStyleElement);// Apply some modern styles to the body
document.body.style.fontFamily ="'Segoe UI', Tahoma, Geneva, Verdana, sans-serif";
document.body.style.margin ="0";
document.body.style.padding ="20px";
document.body.style.backgroundColor ="#22092C !important";