// ==UserScript==
// @name ChatGPT Modal для всех сайтов
// @namespace http://tampermonkey.net/
// @version 1.2
// @description Добавляет модальное окно с ChatGPT на любой сайт
// @author Taras V Penzin (apexweb.ru)
// @match *://*/*
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @run-at document-start
// @connect www.tampermonkey.net
// @connect self
// @connect localhost
// @connect 8.8.8.8
// @connect api.openai.com
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// ========== НАСТРОЙКИ ==========
// Задайте здесь ваш OpenAI API ключ
const API_KEY = '...'; // ЗАМЕНИТЕ НА ВАШ КЛЮЧ!
// ===============================
// Ждем полной загрузки страницы
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initChatGPT);
} else {
initChatGPT();
}
function initChatGPT() {
console.log('🤖 Инициализация ChatGPT Modal...');
// Проверяем API ключ
if (!API_KEY) {
console.error('🤖 ОШИБКА: Не задан API ключ OpenAI! Отредактируйте скрипт и задайте ваш ключ в переменной API_KEY');
return;
}
// Добавляем стили для модального окна
GM_addStyle(`
.chatgpt-modal-overlay {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
background: rgba(0, 0, 0, 0.7) !important;
z-index: 2147483646 !important;
display: none !important;
align-items: center !important;
justify-content: center !important;
backdrop-filter: blur(4px) !important;
}
.chatgpt-modal-overlay.show {
display: flex !important;
}
.chatgpt-modal {
background: white !important;
border-radius: 12px !important;
width: 90% !important;
max-width: 600px !important;
max-height: 80vh !important;
overflow: hidden !important;
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3) !important;
animation: chatgpt-modal-appear 0.3s ease-out !important;
position: relative !important;
}
@keyframes chatgpt-modal-appear {
from {
opacity: 0;
transform: scale(0.9) translateY(-20px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.chatgpt-modal-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
color: white !important;
padding: 20px !important;
position: relative !important;
}
.chatgpt-modal-title {
margin: 0 !important;
font-size: 20px !important;
font-weight: 600 !important;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}
.chatgpt-modal-close {
position: absolute !important;
right: 15px !important;
top: 50% !important;
transform: translateY(-50%) !important;
background: none !important;
border: none !important;
color: white !important;
font-size: 24px !important;
cursor: pointer !important;
padding: 5px !important;
border-radius: 50% !important;
width: 35px !important;
height: 35px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
transition: background 0.2s !important;
}
.chatgpt-modal-close:hover {
background: rgba(255, 255, 255, 0.2) !important;
}
.chatgpt-modal-body {
padding: 20px !important;
max-height: 60vh !important;
overflow-y: auto !important;
}
.chatgpt-input-group {
margin-bottom: 15px !important;
}
.chatgpt-label {
display: block !important;
margin-bottom: 8px !important;
font-weight: 600 !important;
color: #333 !important;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}
.chatgpt-textarea {
width: 100% !important;
min-height: 100px !important;
padding: 12px !important;
border: 2px solid #e1e5e9 !important;
border-radius: 8px !important;
font-size: 14px !important;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
resize: vertical !important;
transition: border-color 0.2s !important;
box-sizing: border-box !important;
}
.chatgpt-textarea:focus {
outline: none !important;
border-color: #667eea !important;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
}
.chatgpt-buttons {
display: flex !important;
gap: 10px !important;
margin-top: 20px !important;
}
.chatgpt-btn {
padding: 12px 24px !important;
border: none !important;
border-radius: 8px !important;
font-size: 14px !important;
font-weight: 600 !important;
cursor: pointer !important;
transition: all 0.2s !important;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
outline: none !important;
}
.chatgpt-btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
color: white !important;
}
.chatgpt-btn-primary:hover:not(:disabled) {
transform: translateY(-2px) !important;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4) !important;
}
.chatgpt-btn-primary:disabled {
opacity: 0.6 !important;
cursor: not-allowed !important;
transform: none !important;
}
.chatgpt-btn-secondary {
background: #f8f9fa !important;
color: #6c757d !important;
border: 2px solid #e9ecef !important;
}
.chatgpt-btn-secondary:hover {
background: #e9ecef !important;
}
.chatgpt-response {
margin-top: 20px !important;
padding: 15px !important;
background: #f8f9fa !important;
border-left: 4px solid #667eea !important;
border-radius: 0 8px 8px 0 !important;
white-space: pre-wrap !important;
line-height: 1.6 !important;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
color: #111;
}
.chatgpt-loading {
display: flex !important;
align-items: center !important;
gap: 10px !important;
color: #667eea !important;
font-style: italic !important;
}
.chatgpt-spinner {
width: 20px !important;
height: 20px !important;
border: 2px solid #e9ecef !important;
border-top: 2px solid #667eea !important;
border-radius: 50% !important;
animation: chatgpt-spin 1s linear infinite !important;
}
@keyframes chatgpt-spin {
to { transform: rotate(360deg); }
}
.chatgpt-error {
color: #dc3545 !important;
background: #f8d7da !important;
border-left-color: #dc3545 !important;
}
.chatgpt-floating-btn {
position: fixed !important;
bottom: 20px !important;
right: 20px !important;
width: 60px !important;
height: 60px !important;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
border: none !important;
border-radius: 50% !important;
cursor: pointer !important;
box-shadow: 0 4px 20px rgba(102, 126, 234, 0.4) !important;
z-index: 2147483647 !important;
transition: all 0.3s ease !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
color: white !important;
font-size: 24px !important;
opacity: 1 !important;
visibility: visible !important;
pointer-events: auto !important;
outline: none !important;
}
.chatgpt-floating-btn:hover {
transform: scale(1.1) !important;
box-shadow: 0 6px 25px rgba(102, 126, 234, 0.6) !important;
}
.chatgpt-floating-btn:active {
transform: scale(0.95) !important;
}
`);
// Создаем плавающую кнопку
function createFloatingButton() {
// Проверяем, не создана ли уже кнопка
if (document.getElementById('chatgpt-floating-btn')) {
console.log('🤖 Кнопка уже существует');
return document.getElementById('chatgpt-floating-btn');
}
const floatingBtn = document.createElement('button');
floatingBtn.id = 'chatgpt-floating-btn';
floatingBtn.className = 'chatgpt-floating-btn';
floatingBtn.innerHTML = '🤖';
floatingBtn.title = 'Открыть ChatGPT';
// Добавляем кнопку к body
document.body.appendChild(floatingBtn);
console.log('🤖 Плавающая кнопка создана');
return floatingBtn;
}
// Создаем плавающую кнопку
const floatingBtn = createFloatingButton();
// Создаем модальное окно
const modalOverlay = document.createElement('div');
modalOverlay.className = 'chatgpt-modal-overlay';
modalOverlay.innerHTML = `
<div class="chatgpt-modal">
<div class="chatgpt-modal-header">
<h3 class="chatgpt-modal-title">ChatGPT Assistant</h3>
<button class="chatgpt-modal-close">×</button>
</div>
<div class="chatgpt-modal-body">
<div class="chatgpt-input-group">
<label class="chatgpt-label">Ваш вопрос к ChatGPT:</label>
<textarea class="chatgpt-textarea" id="chatgpt-prompt" placeholder="Задайте любой вопрос..."></textarea>
</div>
<div class="chatgpt-buttons">
<button class="chatgpt-btn chatgpt-btn-primary" id="chatgpt-send">Отправить</button>
<button class="chatgpt-btn chatgpt-btn-secondary" id="chatgpt-clear">Очистить</button>
</div>
<div id="chatgpt-response-container"></div>
</div>
</div>
`;
document.body.appendChild(modalOverlay);
// Элементы интерфейса
const modal = modalOverlay.querySelector('.chatgpt-modal');
const closeBtn = modalOverlay.querySelector('.chatgpt-modal-close');
const promptTextarea = document.getElementById('chatgpt-prompt');
const sendBtn = document.getElementById('chatgpt-send');
const clearBtn = document.getElementById('chatgpt-clear');
const responseContainer = document.getElementById('chatgpt-response-container');
// Функция отправки запроса к ChatGPT
async function sendToChatGPT(prompt) {
showLoading();
sendBtn.disabled = true;
const requestData = {
model: 'gpt-4o',
messages: [
{
role: 'user',
content: prompt
}
],
max_tokens: 1000,
temperature: 0.7
};
GM_xmlhttpRequest({
method: 'POST',
url: 'https://api.openai.com/v1/chat/completions',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
data: JSON.stringify(requestData),
onload: function(response) {
sendBtn.disabled = false;
try {
const data = JSON.parse(response.responseText);
if (data.error) {
showResponse(`❌ Ошибка API: ${data.error.message}`, true);
return;
}
if (data.choices && data.choices[0] && data.choices[0].message) {
showResponse(data.choices[0].message.content);
} else {
showResponse('❌ Неожиданный формат ответа от API', true);
}
} catch (e) {
showResponse(`❌ Ошибка обработки ответа: ${e.message}`, true);
}
},
onerror: function() {
sendBtn.disabled = false;
showResponse('❌ Ошибка сети. Проверьте подключение к интернету.', true);
},
ontimeout: function() {
sendBtn.disabled = false;
showResponse('❌ Превышено время ожидания ответа', true);
},
timeout: 30000
});
}
// Функция показа загрузки
function showLoading() {
responseContainer.innerHTML = `
<div class="chatgpt-response">
<div class="chatgpt-loading">
<div class="chatgpt-spinner"></div>
Генерирую ответ...
</div>
</div>
`;
}
// Функция показа ответа
function showResponse(text, isError = false) {
const responseDiv = document.createElement('div');
responseDiv.className = `chatgpt-response ${isError ? 'chatgpt-error' : ''}`;
responseDiv.textContent = text;
// Добавляем кнопку копирования для успешных ответов
if (!isError) {
const copyBtn = document.createElement('button');
copyBtn.className = 'chatgpt-btn chatgpt-btn-secondary';
copyBtn.textContent = '📋 Копировать';
copyBtn.style.marginTop = '10px';
copyBtn.onclick = () => {
navigator.clipboard.writeText(text).then(() => {
copyBtn.textContent = '✅';
setTimeout(() => {
copyBtn.textContent = '📋';
}, 2000);
});
};
responseDiv.appendChild(copyBtn);
}
responseContainer.innerHTML = '';
responseContainer.appendChild(responseDiv);
}
// Функция открытия модального окна
function openModal() {
modalOverlay.classList.add('show');
setTimeout(() => {
if (promptTextarea) {
promptTextarea.focus();
}
}, 100);
}
// Функция закрытия модального окна
function closeModal() {
modalOverlay.classList.remove('show');
}
// Обработчики событий
if (floatingBtn) {
floatingBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('🤖 Кнопка нажата');
openModal();
});
} else {
console.error('🤖 Не удалось создать плавающую кнопку');
}
closeBtn.addEventListener('click', (e) => {
e.preventDefault();
closeModal();
});
modalOverlay.addEventListener('click', (e) => {
if (e.target === modalOverlay) {
closeModal();
}
});
sendBtn.addEventListener('click', (e) => {
e.preventDefault();
const prompt = promptTextarea.value.trim();
if (!prompt) {
alert('Введите вопрос для ChatGPT');
return;
}
sendToChatGPT(prompt);
});
clearBtn.addEventListener('click', (e) => {
e.preventDefault();
promptTextarea.value = '';
responseContainer.innerHTML = '';
promptTextarea.focus();
});
// Отправка по Enter (Ctrl+Enter)
promptTextarea.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && e.ctrlKey) {
e.preventDefault();
sendBtn.click();
}
});
// Закрытие по Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && modalOverlay.classList.contains('show')) {
closeModal();
}
});
console.log('🤖 ChatGPT Modal загружен! Ищите плавающую кнопку внизу справа.');
// Дополнительная проверка через 2 секунды
setTimeout(() => {
const btn = document.getElementById('chatgpt-floating-btn');
if (btn) {
console.log('🤖 Кнопка найдена и работает!');
} else {
console.error('🤖 Кнопка не найдена! Попробуйте перезагрузить страницу.');
// Пытаемся создать еще раз
createFloatingButton();
}
}, 2000);
} // Закрываем функцию initChatGPT
})();