Code viewer for World: Story Generator with Image
// Snippets of code and ideas taken from https://ancientbrain.com/world.php?world=2850716357

// Story Telling Generator using OpenAI ChatGPT API

// Apply basic CSS styling to the body of the page for margin and padding
$('body').css("margin", "20px");
$('body').css("padding", "20px");

// Define the URLs for OpenAI's ChatGPT and DALL-E APIs
const openaiURL = "https://api.openai.com/v1/chat/completions";
const themodel = "gpt-3.5-turbo";
const dalleURL = "https://api.openai.com/v1/images/generations";

// Initialize a variable to store the API key
var apikey = "";

// Using document.write to inject HTML content into the document
document.write(`
<!DOCTYPE html>
<html>
<head>
    <title>Interactive Story and Image Generator</title>
    <style>
        /* CSS styles for buttons and image output */
        .ab-normbutton {
            padding: 10px;
            margin: 5px;
            cursor: pointer;
        }

        #imageOutput img {
            max-width: 90%;
            max-height: 90%;
            display: block; /* Ensures no extra space below the image */
            margin: auto; /* Centers the image within its container */
        }
    </style>
</head>
<body>
    <h1>Interactive Story and Image Generator</h1>

    <!-- Section for API Key Input -->
    <div id="enterkey" style="margin:20px;">
        Enter API key: 
        <input style='width:25vw;' maxlength='2000' id="apikey" value=''>  
        <button id="setKeyButton" class="ab-normbutton">Set API Key</button>
    </div>

    <!-- Section for entering details for story generation -->
    <div style="width:60vw; background-color:white; border: 1px solid black; margin:20px; padding: 20px;">
        Genre: <input style="width:50vw;" id="genre" placeholder="Adventure, Mystery, Fantasy..."><br>
        Place: <input style="width:50vw;" id="place" placeholder="A forest, a city, an alien planet..."><br>
        Person: <input style="width:50vw;" id="person" placeholder="A brave knight, a curious child..."><br>
        Action: <input style="width:50vw;" id="action" placeholder="Exploring a cave, solving a mystery..."><br>
        Word Count: <input type="number" id="wordCount" min="1" max="500" placeholder="Up to 500 words"><br>
        <button id="generateButton" class="ab-normbutton">Generate Story</button>
    </div>

    <!-- Section to display the generated story -->
    <div id="storyOutput" style="width:60vw; background-color:#ffffcc; border: 1px solid black; margin:20px; padding: 20px;">
        <h3>Generated Story</h3>
        <div id="storyText">Your story will appear here...</div>
    </div>
    
    <!-- Section to display the generated image -->
    <div id="imageOutput" style="width:60vw; background-color:#fffccc; border: 1px solid black; margin:20px; padding: 20px;">
        <h3>Generated Image</h3>
        <div id="imageOutput">The generated image will be displayed here...</div>
    </div>
</body>
</html>
`);

// JavaScript functions to interact with the OpenAI API
$(document).ready(function() {
    // Function to set the API key
    function setkey() {
        apikey = $("#apikey").val().trim(); // Retrieves and trims the API key from input
        $("#enterkey").html("<b>API key has been set.</b>"); // Displays confirmation message
    }

    // Function to generate a story based on user inputs
    function generateStory() {
        // Retrieve values from input fields
        var genre = $("#genre").val();
        var place = $("#place").val();
        var person = $("#person").val();
        var action = $("#action").val();
        var wordCount = $("#wordCount").val();

        // Create a story prompt using the input values
        var storyPrompt = `Write a story in the genre of ${genre}. This story is set in ${place}. The main character in the story will be ${person}. The main character in this story is ${action}. Please keep the story under ${wordCount} words.`;
        // Create a image prompt using the input values
        var imagePrompt = `Generate an image in the genre of ${genre}. This story is set in ${place}. The main character in the picture will be ${person}. The main character in this image is ${action}.`;
        
    // Set up default AJAX settings for all requests
    $.ajaxSetup({
        headers: {
            "Content-Type": "application/json", // Set Content-Type header for JSON data format
            "Authorization": "Bearer " + apikey // Set Authorization header with the API key
        }
    });

    // AJAX POST request to OpenAI API for generating a story
    $.ajax({
        type: "POST", // HTTP request method
        url: openaiURL, // OpenAI API endpoint URL
        data: JSON.stringify({ // Convert request payload to JSON string
            "model": themodel, // Define the model to use
            "messages": [{ // Messages array containing user's prompt
                "role": "user", // Role type
                "content": storyPrompt // Story prompt based on user input
            }]
        }),
        dataType: "json", // Expecting JSON response
        success: function(data) {
            var story = data.choices[0].message.content; // Extracting story from the response
            $("#storyText").html(story); // Displaying the story in the webpage
            generateImage(imagePrompt); // Call to function for generating image based on the story
        },
        error: function(xhr, status, error) {
            // Error handling
            if (apikey === "") {
                $("#storyText").html("<font color=red><b>Enter API key to be able to generate a story.</b></font>");
            } else {
                $("#storyText").html("<font color=red><b>Error: " + error + "</b></font>");
            }
        }
    });
}

// Function to generate an image based on the story
function generateImage(imagePrompt) {
    // Additional comments can be added here for the generateImage function

    // AJAX POST request to DALL-E API for generating an image
    $.ajax({
        type: "POST", // HTTP request method
        url: dalleURL, // DALL-E API endpoint URL
        data: JSON.stringify({ // Convert request payload to JSON string
            "prompt": imagePrompt, // Image prompt
            "n": 1, // Number of images to generate
            "size": "1024x1024" // Size of the generated image
        }),
        headers: {
            "Authorization": "Bearer " + apikey, // Authorization header with the API key
            "Content-Type": "application/json" // Set Content-Type header for JSON data format
        },
        success: function(response) {
            var generatedImageUrl = response.data[0].url; // Extract URL of the generated image
            $("#imageOutput").html('<img src="' + generatedImageUrl + '" alt="Generated Image"/>'); // Display image in webpage
        },
        error: function(xhr, status, error) {
            // Error handling for image generation
            $("#imageOutput").html("<font color='red'><b>Error generating image: " + error + "</b></font>");
        }
    });
}

// Event listeners for buttons
$("#setKeyButton").on('click', setkey);
$("#generateButton").on('click', generateStory);

}); // End of document ready function