본문 바로가기
취미 또는 부업/openai 블로그 글 생성기

ChatGPT와 OpenAI를 활용한 블로그 글쓰기3

by cy.kim 2024. 10. 1.
반응형

다음으로는 view와 view의 액션을 처리할 js를 첨부하도록 하겠다.

<!DOCTYPE html>
<html lang="kr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>chatgpt 블로그 생성</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6">
            <h3>GPT Editor</h3>
            <div>
                <div class="form-group mb-3">
                    <label for="key" class="form-label">API key</label>
                    <input type="email" class="form-control" id="key" placeholder="api key">
                    <input type="checkbox" class="form-check-input" id="save">
                    <label class="form-check-label" for="save">API 키 저장</label>
                </div>
                <div class="form-group mb-3">
                    <label for="modelSelect" class="form-label">모델 선택</label>
                    <select class="form-select" id="modelSelect">
                        <option value="o1-preview">o1-preview</option>
                        <option value="o1-preview-2024-09-12">o1-preview-2024-09-12</option>
                        <option value="o1-mini">o1-mini</option>
                        <option value="o1-mini-2024-09-12">o1-mini-2024-09-12</option>
                        <option value="gpt-4o">gpt-4o</option>
                        <option value="gpt-4o-2024-08-06">gpt-4o-2024-08-06</option>
                        <option value="gpt-4o-2024-05-13">gpt-4o-2024-05-13</option>
                        <option value="chatgpt-4o-latest">chatgpt-4o-latest</option>
                        <option value="gpt-4o-mini" selected>gpt-4o-mini</option>
                        <option value="gpt-4o-mini-2024-07-18">gpt-4o-mini-2024-07-18</option>
                        <option value="gpt-4-turbo">gpt-4-turbo</option>
                        <option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option>
                        <option value="gpt-4-0125-preview">gpt-4-0125-preview</option>
                        <option value="gpt-4-turbo-preview">gpt-4-turbo-preview</option>
                        <option value="gpt-4-1106-preview">gpt-4-1106-preview</option>
                        <option value="gpt-4-vision-preview">gpt-4-vision-preview</option>
                        <option value="gpt-4">gpt-4</option>
                        <option value="gpt-4-0314">gpt-4-0314</option>
                        <option value="gpt-4-0613">gpt-4-0613</option>
                        <option value="gpt-4-32k">gpt-4-32k</option>
                        <option value="gpt-4-32k-0314">gpt-4-32k-0314</option>
                        <option value="gpt-4-32k-0613">gpt-4-32k-0613</option>
                        <option value="gpt-3.5-turbo">gpt-3.5-turbo</option>
                        <option value="gpt-3.5-turbo-16k">gpt-3.5-turbo-16k</option>
                        <option value="gpt-3.5-turbo-0301">gpt-3.5-turbo-0301</option>
                        <option value="gpt-3.5-turbo-0613">gpt-3.5-turbo-0613</option>
                        <option value="gpt-3.5-turbo-1106">gpt-3.5-turbo-1106</option>
                        <option value="gpt-3.5-turbo-0125">gpt-3.5-turbo-0125</option>
                        <option value="gpt-3.5-turbo-16k-0613">gpt-3.5-turbo-16k-0613</option>
                    </select>
                </div>

                <div class="form-group mb-3">
                    <label for="editor" class="form-label">작성 프롬프트</label>
                    <textarea class="form-control" id="editor" rows="3" placeholder="블로그 작성 내용 입력"></textarea>
                </div>
                <div class="form-group form-check mb-3">
                    <input type="checkbox" class="form-check-input" id="image_flag">
                    <label class="form-check-label" for="image_flag">관련 AI 이미지 생성</label>
                </div>
                <div id="image_model_wrapper" class="form-group mb-3" style="display: none;">
                    <label for="modelSelect2" class="form-label">이미지 모델 선택</label>
                    <select class="form-select" id="modelSelect2">
                        <option value="dall-e-2">dall-e-2</option>
                        <option value="dall-e-3" selected>dall-e-3</option>
                    </select>
                </div>
                <div class="mb-3 text-center">
                    <button id="submit" type="button" class="btn btn-primary btn-lg">블로그 생성</button>
                </div>
            </div>
        </div>

        <div class="col-md-6">
            <div>
                <h3>HTML 프리뷰</h3>
                <div id="title" class="border p-3 mb-3" style="height: 50px; background-color: #f8f9fa;">제목이 노출됩니다.</div>
                <!-- 프리뷰 텍스트 편집 영역 -->
                <textarea id="html-editor" class="form-control border mb-3" rows="10" style="height: 600px; display: none;"></textarea>

                <!-- 기존 HTML 프리뷰 영역 -->
                <div id="html-preview" class="border p-3" style="height: 600px; overflow-y: auto; background-color: #f8f9fa;">내용이 출력됩니다.</div>
            </div>

            <div class="pt-3 text-center">
                <button id="copyHtml" type="button" class="btn btn-secondary btn-lg" style="display:none;">HTML 복사</button>
                <button id="editHtml" type="button" class="btn btn-warning btn-lg" style="display:none;">HTML 편집</button>
                <button id="saveEdit" type="button" class="btn btn-success btn-lg" style="display:none;">수정 저장</button>
            </div>

        </div>
    </div>
</div>
<div id="loader">
    <div class="spinner-wrapper">
        <div class="spinner-border text-light" role="status">
            <span class="visually-hidden">Loading...</span>
        </div>
    </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<script src="./js/renderer.js"></script>
</body>
</html>

별거 없다

 

bootstrap을 사용했고 api키 저장 및 버튼 액션 그리고 최종적으로 출력 될 내용 프리뷰 영역과 수정 가능하게 하는 버튼이 있다.

맨 처음 포스팅의 화면과 동일하게 출력 될 것이다.

 

다음은 액션 처리 js이다.

document.addEventListener('DOMContentLoaded', async () => {
    const key = localStorage.getItem('openai_key');
    if (key) {
        document.getElementById('key').value = key;
        document.getElementById('save').checked = true;
    }
});

// API 키 저장
document.getElementById('save').addEventListener('change', async (e) => {
    e.target.checked && document.getElementById('key').value ? localStorage.setItem('openai_key', document.getElementById('key').value) : localStorage.removeItem('openai_key');
});
document.getElementById('image_flag').addEventListener('change',  (e) => {
    e.target.checked ? document.getElementById('image_model_wrapper').style.display = 'block' : document.getElementById('image_model_wrapper').style.display = 'none';
});
// 블로그 생성 버튼
document.getElementById('submit').addEventListener('click', async () => {
    const userInput = document.getElementById('editor').value;
    const key = document.getElementById('key').value;
    const flag = document.getElementById('image_flag').checked;
    const selectedModel = document.getElementById('modelSelect').value;
    const selectedModel2 = document.getElementById('modelSelect2').value;
    const loader = document.getElementById('loader');

    if (!key) {
        alert('API 키를 입력해주세요.');
        return;
    }

    if (!userInput) {
        alert('블로그 작성 내용을 입력해주세요.');
        return;
    }

    loader.style.display = 'block';

    await window.electronAPI.invoke('generate-blog-post', { key: key, userInput: userInput, imgFlag: flag, chatModel: selectedModel,imageModel: selectedModel2})
        .then((res) => {
            const title = document.getElementById('title');
            const wrapper = document.getElementById('html-preview')
            if(res.error) {
                throw new Error(res.error);
            }

            wrapper.innerHTML = res.blogContent;
            title.innerText = wrapper.getElementsByTagName('h1')[0].innerText;
            wrapper.removeChild(wrapper.getElementsByTagName('h1')[0]);

            alert('HTML이 생성되었습니다!');
            loader.style.display = 'none';

            // HTML 편집 버튼 활성화
            document.getElementById('copyHtml').style.display = 'inline-block';
            document.getElementById('editHtml').style.display = 'inline-block';
        }).catch((e) => {
            loader.style.display = 'none';
            alert(e.message);
        });
});

// HTML 복사 버튼
document.getElementById('copyHtml').addEventListener('click', () => {
    const htmlContent = document.getElementById('html-preview').innerHTML;

    const tempTextArea = document.createElement('textarea');
    tempTextArea.value = htmlContent;
    document.body.appendChild(tempTextArea);
    tempTextArea.select();
    document.execCommand('copy');
    document.body.removeChild(tempTextArea);

    alert('HTML이 클립보드에 복사되었습니다!');
});

// HTML 편집 버튼
document.getElementById('editHtml').addEventListener('click', () => {
    const htmlPreview = document.getElementById('html-preview').innerHTML;
    const htmlEditor = document.getElementById('html-editor');

    // 기존 HTML을 텍스트 에디터에 불러오기
    htmlEditor.value = htmlPreview;
    htmlEditor.style.display = 'block';
    document.getElementById('html-preview').style.display = 'none';  // 프리뷰 숨김

    document.getElementById('saveEdit').style.display = 'inline-block';  // 저장 버튼 표시
});

// 수정 저장 버튼
document.getElementById('saveEdit').addEventListener('click', () => {
    const editorContent = document.getElementById('html-editor').value;
    document.getElementById('html-preview').innerHTML = editorContent;

    document.getElementById('html-preview').style.display = 'block';
    document.getElementById('html-editor').style.display = 'none';  // 텍스트 에디터 숨김

    alert('HTML 수정이 완료되었습니다!');
});

키 저장을 위해 localstorage를 사용했고 버튼마다 액션을 추가했다.

 

그리고 preload.js에 설정된 통신 채널을 통해 openai api와 통신 후 프리뷰 영역에 넣게되는 것이다.

여기서 입맛에 맞게 프롬프트를 수정 추가하면 조금 더 나은 양질의 글이 생성될 것으로 판단된다.

 

이렇게 openai를 활용한 블로그 글쓰기 프로그램이 완성됐다.

아직 미완성이 기능이 많지만 이정도로 나름 쓸만하다 생각해서 현재 사용 중에 있다.

아직 미숙한 프로그램이지만 사용해줬으면 좋겠다..

 

다음에는 github에서 openai를 활용한 youtube short 생성기를 리뷰 해보려고 한다...

 

반응형