Генератор изображений по описанию - 7Post

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ИИ-чат + рисовалка</title>
  <style>
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background: #f0f4f8;
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      margin: 20px;
    }
    .chat-container {
      max-width: 700px;
      width: 100%;
      background: white;
      border-radius: 24px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
      overflow: hidden;
      display: flex;
      flex-direction: column;
      height: 80vh;
      max-height: 700px;
    }
    .chat-header {
      background: #1a1a2e;
      color: #fff;
      padding: 18px 24px;
      font-size: 1.2rem;
      font-weight: 600;
      display: flex;
      align-items: center;
      gap: 10px;
    }
    .chat-header span {
      background: #e94560;
      border-radius: 50%;
      width: 12px;
      height: 12px;
      display: inline-block;
    }
    .chat-messages {
      flex: 1;
      padding: 20px 24px;
      overflow-y: auto;
      background: #fafbfc;
      display: flex;
      flex-direction: column;
      gap: 12px;
    }
    .message {
      padding: 12px 16px;
      border-radius: 18px;
      max-width: 80%;
      word-wrap: break-word;
      line-height: 1.5;
      animation: fadeIn 0.3s ease;
    }
    .message.user {
      align-self: flex-end;
      background: #1a1a2e;
      color: white;
      border-bottom-right-radius: 4px;
    }
    .message.bot {
      align-self: flex-start;
      background: #e9eef2;
      color: #1a1a2e;
      border-bottom-left-radius: 4px;
    }
    .message img {
      max-width: 100%;
      border-radius: 12px;
      margin-top: 8px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.1);
    }
    .message .image-prompt {
      font-size: 0.9rem;
      color: #555;
      margin-top: 4px;
      font-style: italic;
    }
    @keyframes fadeIn {
      from { opacity: 0; transform: translateY(8px); }
      to { opacity: 1; transform: translateY(0); }
    }
    .typing {
      align-self: flex-start;
      background: #e9eef2;
      padding: 12px 16px;
      border-radius: 18px;
      border-bottom-left-radius: 4px;
      color: #555;
      font-style: italic;
      display: inline-block;
    }
    .typing::after {
      content: '...';
      animation: dots 1.2s steps(3, end) infinite;
    }
    @keyframes dots {
      0% { content: ''; }
      33% { content: '.'; }
      66% { content: '..'; }
      100% { content: '...'; }
    }
    .chat-input-area {
      display: flex;
      padding: 16px 24px;
      background: white;
      border-top: 1px solid #e2e8f0;
      gap: 10px;
      align-items: center;
    }
    .chat-input-area input {
      flex: 1;
      padding: 12px 16px;
      border: 1px solid #d1d9e6;
      border-radius: 30px;
      font-size: 1rem;
      outline: none;
      transition: border 0.2s;
    }
    .chat-input-area input:focus {
      border-color: #1a1a2e;
    }
    .chat-input-area button {
      background: #1a1a2e;
      color: white;
      border: none;
      padding: 12px 24px;
      border-radius: 30px;
      font-size: 1rem;
      cursor: pointer;
      transition: background 0.2s;
      white-space: nowrap;
    }
    .chat-input-area button:hover {
      background: #e94560;
    }
    .chat-input-area button:disabled {
      opacity: 0.6;
      cursor: not-allowed;
    }
    .info {
      font-size: 0.8rem;
      color: #888;
      text-align: center;
      padding: 6px;
      background: #f8fafc;
    }
    .info a {
      color: #1a1a2e;
    }
  </style>
</head>
<body>
  <div class="chat-container">
    <div class="chat-header">
      <span></span> ИИ-чат · текст + картинки
    </div>
    <div class="chat-messages" id="chatMessages">
      <div class="message bot">👋 Привет! Я умею отвечать на вопросы и рисовать по описанию. Просто напиши «нарисуй ...» или «сгенерируй ...»</div>
    </div>
    <div class="chat-input-area">
      <input type="text" id="userInput" placeholder="Спроси что-нибудь или попроси нарисовать..." autofocus>
      <button id="sendBtn">Отправить</button>
    </div>
    <div class="info">
      Используется <a href="https://pollinations.ai" target="_blank">Pollinations.ai</a> (бесплатно, без ключей)
    </div>
  </div>

  <script>
    (function() {
      const messagesContainer = document.getElementById('chatMessages');
      const userInput = document.getElementById('userInput');
      const sendBtn = document.getElementById('sendBtn');

      // История диалога (для контекста)
      let conversationHistory = [];

      // Функция добавления сообщения в чат
      function addMessage(text, sender, imageUrl = null, promptText = null) {
        const div = document.createElement('div');
        div.className = `message ${sender}`;

        if (imageUrl) {
          // Сообщение-картинка
          const img = document.createElement('img');
          img.src = imageUrl;
          img.alt = 'Сгенерированное изображение';
          div.appendChild(img);
          if (promptText) {
            const caption = document.createElement('div');
            caption.className = 'image-prompt';
            caption.textContent = `🖼 «${promptText}»`;
            div.appendChild(caption);
          }
          // Добавляем и текстовое пояснение, если есть
          if (text) {
            const textNode = document.createElement('div');
            textNode.textContent = text;
            div.prepend(textNode);
          }
        } else {
          div.textContent = text;
        }

        messagesContainer.appendChild(div);
        messagesContainer.scrollTop = messagesContainer.scrollHeight;
      }

      // Показать индикатор печати
      function showTyping() {
        const typingDiv = document.createElement('div');
        typingDiv.className = 'typing';
        typingDiv.id = 'typingIndicator';
        typingDiv.textContent = 'ИИ думает';
        messagesContainer.appendChild(typingDiv);
        messagesContainer.scrollTop = messagesContainer.scrollHeight;
      }

      function hideTyping() {
        const el = document.getElementById('typingIndicator');
        if (el) el.remove();
      }

      // Проверка, является ли запрос на генерацию картинки
      function isImageRequest(text) {
        const triggers = ['нарисуй', 'сгенерируй', 'покажи', 'нарисуй мне', 'создай'];
        const lower = text.toLowerCase().trim();
        for (let trigger of triggers) {
          if (lower.startsWith(trigger) || lower.includes(trigger)) {
            return true;
          }
        }
        return false;
      }

      // Извлечение промпта для картинки (убираем команду)
      function extractPrompt(text) {
        const triggers = ['нарисуй', 'сгенерируй', 'покажи', 'нарисуй мне', 'создай'];
        let prompt = text;
        for (let trigger of triggers) {
          if (prompt.toLowerCase().startsWith(trigger)) {
            prompt = prompt.slice(trigger.length).trim();
            break;
          }
          // Ищем внутри
          const idx = prompt.toLowerCase().indexOf(trigger);
          if (idx !== -1) {
            prompt = prompt.slice(idx + trigger.length).trim();
            break;
          }
        }
        // Если осталось пусто, ставим дефолт
        if (!prompt) prompt = 'красивое абстрактное искусство';
        return prompt;
      }

      // Генерация картинки через Pollinations (GET-запрос)
      function generateImage(prompt) {
        // Кодируем промпт для URL
        const encoded = encodeURIComponent(prompt);
        // Используем параметр width=512&height=512, можно изменить
        const url = `https://image.pollinations.ai/prompt/${encoded}?width=512&height=512&nologo=true`;
        return url; // Просто возвращаем URL, т.к. это GET-запрос, изображение отдаётся сразу
      }

      // Получение текстового ответа от ИИ (Pollinations text API)
      async function getTextResponse(userMessage, history) {
        // Строим историю для контекста (последние 5 сообщений)
        const context = history.slice(-5).map(msg => `${msg.role}: ${msg.content}`).join('\n');
        const fullPrompt = `${context}\nПользователь: ${userMessage}\nАссистент:`;

        try {
          const response = await fetch('https://text.pollinations.ai/', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              messages: [
                { role: 'system', content: 'Ты полезный и дружелюбный ассистент, отвечаешь на русском языке.' },
                ...history.map(msg => ({ role: msg.role, content: msg.content })),
                { role: 'user', content: userMessage }
              ],
              model: 'openai',
              seed: Math.floor(Math.random() * 1000000),
              temperature: 0.7
            })
          });

          if (!response.ok) throw new Error(`HTTP error ${response.status}`);
          const data = await response.json();
          // Ответ может быть в поле choices[0].message.content или напрямую текст
          let reply = '';
          if (data.choices && data.choices.length > 0) {
            reply = data.choices[0].message.content;
          } else if (data.message) {
            reply = data.message.content;
          } else if (typeof data === 'string') {
            reply = data;
          } else {
            reply = 'Извините, не удалось получить ответ.';
          }
          return reply.trim();
        } catch (error) {
          console.error('Ошибка при запросе к текстовому API:', error);
          return 'Произошла ошибка при обращении к ИИ. Попробуйте позже.';
        }
      }

      // Основная функция отправки сообщения
      async function sendMessage() {
        const userMessage = userInput.value.trim();
        if (!userMessage) return;

        // Отключаем кнопку и инпут на время обработки
        sendBtn.disabled = true;
        userInput.disabled = true;

        // Добавляем сообщение пользователя в чат и историю
        addMessage(userMessage, 'user');
        conversationHistory.push({ role: 'user', content: userMessage });

        // Проверяем, является ли запрос на генерацию картинки
        if (isImageRequest(userMessage)) {
          const prompt = extractPrompt(userMessage);
          // Показываем индикатор загрузки
          showTyping();
          // Имитация задержки (можно убрать)
          await new Promise(resolve => setTimeout(resolve, 800));
          hideTyping();

          // Генерируем URL картинки
          const imageUrl = generateImage(prompt);
          // Отображаем картинку в чате
          addMessage('', 'bot', imageUrl, prompt);
          // Сохраняем в истории (как ответ бота)
          conversationHistory.push({ role: 'assistant', content: `[Изображение: ${prompt}]` });
        } else {
          // Обычный текстовый запрос
          showTyping();
          let botReply = await getTextResponse(userMessage, conversationHistory);
          hideTyping();

          // Если ответ пустой, даём заглушку
          if (!botReply) botReply = 'Не удалось сформулировать ответ.';
          addMessage(botReply, 'bot');
          conversationHistory.push({ role: 'assistant', content: botReply });
        }

        // Очищаем поле и включаем обратно
        userInput.value = '';
        sendBtn.disabled = false;
        userInput.disabled = false;
        userInput.focus();
      }

      // Обработчики событий
      sendBtn.addEventListener('click', sendMessage);
      userInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
          e.preventDefault();
          sendMessage();
        }
      });

      // Автофокус
      userInput.focus();
    })();
  </script>
</body>
</html>

Сервис полностью бесплатный и не требует регистрации, что идеально подходит для публичного блога

✨ Возможности

- 🎯 5 размеров изображения (1:1, 16:9, 9:16, 4:3, 3:4)

- 🤖 5 моделей (Flux для качества, Turbo для скорости, Anime, 3D, Realism)

- 🌱 Seed — позволяет воспроизводить одинаковые результаты

- 💡 Готовые примеры — клик по чипу вставляет текст

- ⬇️ Кнопка скачивания результата

- 📱 Адаптивный дизайн — работает на телефонах

- ⌨️ Ctrl+Enter для быстрой генерации