
сегодня в 09:23
Девушка с двухлетним ребёнком попала под колёса иномарки в Шпаковском округе
Проблема в двух местах:
Ошибка stopShareButtonMonitoring - нужно убрать вызов этого методаОбрезанный текст - проблема в извлечении полного ответа
Вот исправленный content.js:
javascriptКопироватьСкачать// Защита от повторной загрузки
if (typeof window.deepSeekContentScriptInitialized === 'undefined') {
window.deepSeekContentScriptInitialized = true;
class DeepSeekContentScript {
constructor() {
this.isProcessing = false;
this.currentTask = null;
this.currentTaskId = null;
this.retryCount = 0;
this.maxRetries = 3;
this.init();
}
init() {
console.log('🎯 DeepSeek Content Script initialized for:', window.location.href);
// Немедленно отправляем ready сигнал несколько раз
this.sendRepeatedReadySignal();
// Слушаем сообщения
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
return this.handleMessage(message, sender, sendResponse);
});
console.log('✅ Content script ready to receive messages');
}
async sendRepeatedReadySignal() {
// Отправляем ready сигнал несколько раз с интервалом
for (let i = 0; i < 5; i++) {
try {
await chrome.runtime.sendMessage({
type: 'CONTENT_SCRIPT_READY',
url: window.location.href,
timestamp: Date.now()
});
console.log('✅ Ready signal sent (attempt ' + (i + 1) + ')');
break;
} catch (error) {
console.log('⏳ Could not send ready signal, retrying...');
await this.delay(2000);
}
}
}
async handleMessage(message, sender, sendResponse) {
console.log('📨 Received message:', message.type);
switch (message.type) {
case 'PING':
console.log('🏓 PONG - Content script is alive');
sendResponse({
ready: true,
url: window.location.href,
timestamp: Date.now()
});
return true;
case 'PROCESS_TASK':
console.log('🎯 Processing task request:', message.task.id);
if (this.isProcessing) {
sendResponse({
success: false,
error: 'Already processing a task'
});
return true;
}
// Немедленно отвечаем что задача принята
sendResponse({
success: true,
taskId: message.task.id,
message: 'Task accepted for processing'
});
// Обрабатываем задачу асинхронно
this.processTaskAsync(message.task);
return true;
default:
sendResponse({ success: false, error: 'Unknown message type' });
}
}
async processTaskAsync(task) {
this.isProcessing = true;
this.currentTask = task;
this.currentTaskId = task.id;
this.retryCount = 0;
try {
console.log(`🔄 Starting async task processing: ${task.id}`);
// Проверяем что мы на правильной странице
if (!this.isDeepSeekChatPage()) {
throw new Error('Not on DeepSeek chat page');
}
// Ждем загрузки интерфейса
await this.waitForInterface();
// Выключаем "Глубокое мышление" если оно включено
await this.disableDeepThinking();
// Создаем новый чат
await this.createNewChat();
// Вводим задание
await this.enterPrompt(task.prompt || task.text || task.content);
// Ждем ответа
const response = await this.waitForResponse();
// Проверяем что ответ не пустой
if (!response || response.trim().length < 10) {
throw new Error('AI response is empty or too short');
}
console.log(`✅ Response received: ${response.length} characters`);
// Отправляем результат немедленно после получения ответа
await this.sendResultToBackground(task.id, response);
} catch (error) {
console.error('❌ Task processing error:', error);
// Пробуем повторить при временных ошибках
if (this.retryCount < this.maxRetries && this.isRetryableError(error)) {
this.retryCount++;
console.log(`🔄 Retrying task (attempt ${this.retryCount})...`);
await this.delay(2000 * this.retryCount);
this.processTaskAsync(task);
return;
}
// Отправляем ошибку
await this.sendErrorToBackground(task.id, error.message);
}
}
async disableDeepThinking() {
console.log('🔍 Checking Deep Thinking button state...');
// Даем время для полной загрузки интерфейса
await this.delay(2000);
// Ищем кнопку "Глубокое мышление" разными способами
const deepThinkingButton = await this.findDeepThinkingButtonWithRetry();
if (!deepThinkingButton) {
console.log('❌ Deep Thinking button not found, continuing without disabling');
return;
}
console.log('✅ Found Deep Thinking button, checking state...');
if (this.isDeepThinkingEnabled(deepThinkingButton)) {
console.log('🔄 Deep Thinking is ENABLED, attempting to disable...');
// Пробуем несколько раз выключить
let attempts = 0;
const maxAttempts = 3;
while (attempts < maxAttempts && this.isDeepThinkingEnabled(deepThinkingButton)) {
console.log(`🔄 Disabling attempt ${attempts + 1}/${maxAttempts}...`);
// Кликаем на кнопку
deepThinkingButton.click();
await this.delay(2000);
// Проверяем состояние после клика
const currentState = this.isDeepThinkingEnabled(deepThinkingButton);
console.log(`🔍 State after click: ${currentState ? 'STILL ENABLED' : 'DISABLED'}`);
if (!currentState) {
console.log('✅ Successfully disabled Deep Thinking');
break;
}
attempts++;
}
if (this.isDeepThinkingEnabled(deepThinkingButton)) {
console.log('⚠️ Failed to disable Deep Thinking after multiple attempts');
}
} else {
console.log('✅ Deep Thinking is already DISABLED');
}
}
async findDeepThinkingButtonWithRetry() {
let attempts = 0;
const maxAttempts = 10;
while (attempts < maxAttempts) {
const button = this.findDeepThinkingButton();
if (button) {
return button;
}
console.log(`⏳ Deep Thinking button not found, retrying... (${attempts + 1}/${maxAttempts})`);
await this.delay(1000);
attempts++;
}
return null;
}
findDeepThinkingButton() {
// Способ 1: Поиск по тексту в span
const spans = document.querySelectorAll('span._6dbc175');
for (const span of spans) {
if (span.textContent.includes('Глубокое мышление') ||
span.textContent.includes('Глубокое размышление')) {
console.log('✅ Found by text in span');
const button = span.closest('button.ds-atom-button');
if (button) return button;
}
}
// Способ 2: Поиск всех toggle кнопок
const toggleButtons = document.querySelectorAll('.ds-atom-button.f79352dc.ds-toggle-button');
console.log(`🔍 Found ${toggleButtons.length} toggle buttons total`);
for (const button of toggleButtons) {
const buttonText = button.textContent || '';
if (buttonText.includes('Глубокое')) {
console.log('✅ Found by button text content');
return button;
}
}
// Способ 3: Поиск по уникальному SVG
const allButtons = document.querySelectorAll('button');
for (const button of allButtons) {
const svg = button.querySelector('svg');
if (svg && this.isDeepThinkingSVG(svg)) {
console.log('✅ Found by unique SVG');
return button;
}
}
// Способ 4: Поиск в конкретных контейнерах
const containers = [
'.ec4f5d61',
'[class*="toggle"]',
'[class*="thinking"]',
'[class*="deep"]'
];
for (const selector of containers) {
const elements = document.querySelectorAll(selector);
for (const element of elements) {
const buttons = element.querySelectorAll('button');
for (const button of buttons) {
const text = button.textContent || '';
if (text.includes('Глубокое')) {
console.log('✅ Found in container');
return button;
}
}
}
}
return null;
}
isDeepThinkingEnabled(button) {
if (!button) return false;
// Основной признак - класс selected
const hasSelectedClass = button.classList.contains('ds-toggle-button--selected');
// Дополнительные признаки
const icon = button.querySelector('.ds-icon');
let hasBrandColor = false;
if (icon) {
const style = window.getComputedStyle(icon);
const color = style.color;
// Проверяем brand цвет (синий)
hasBrandColor = color.includes('77, 107, 254') ||
color.includes('4b6bfb') ||
color.includes('rgb(77, 107, 254)');
}
// Также проверяем aria-attributes если есть
const ariaPressed = button.getAttribute('aria-pressed');
const isAriaPressed = ariaPressed === 'true';
const isEnabled = hasSelectedClass || hasBrandColor || isAriaPressed;
console.log(`🔍 Button state analysis:`);
console.log(` - Selected class: ${hasSelectedClass}`);
console.log(` - Brand color: ${hasBrandColor}`);
console.log(` - Aria-pressed: ${isAriaPressed}`);
console.log(` - Final state: ${isEnabled ? 'ENABLED' : 'DISABLED'}`);
return isEnabled;
}
isDeepThinkingSVG(svgElement) {
const paths = svgElement.querySelectorAll('path');
const svgHTML = svgElement.innerHTML || '';
// Проверяем по характерным path элементам
const characteristicPaths = [
'M8.6815 0.963693',
'M11.3573 8.01154',
'M9.97171 1.29987',
'M7.06431 5.93342'
];
for (const path of paths) {
const d = path.getAttribute('d') || '';
for (const characteristic of characteristicPaths) {
if (d.includes(characteristic)) {
return true;
}
}
}
return false;
}
isDeepSeekChatPage() {
return window.location.href.includes('deepseek.com') &&
(window.location.href.includes('/chat') || window.location.href.includes('chat.deepseek.com'));
}
async waitForInterface() {
console.log('⏳ Waiting for DeepSeek interface...');
let attempts = 0;
const maxAttempts = 10;
while (attempts < maxAttempts) {
if (this.findInputField()) {
console.log('✅ DeepSeek interface found');
return true;
}
console.log(`⏳ Waiting for interface (attempt ${attempts + 1})...`);
await this.delay(2000);
attempts++;
}
throw new Error('DeepSeek interface not found');
}
async createNewChat() {
console.log('🔍 Checking chat state...');
// Сначала проверяем, есть ли уже активный чат
if (await this.hasActiveChat()) {
console.log('✅ Using existing active chat');
return;
}
// Только если нет активного чата, создаем новый
console.log('📝 Creating new chat...');
const newChatSelectors = [
'a[href="/chat/new"]',
'button[data-testid="new-chat-button"]',
'[class*="new-chat"]',
'button[aria-label*="new chat" i]',
'button[title*="new chat" i]'
];
for (const selector of newChatSelectors) {
const element = document.querySelector(selector);
if (element && this.isVisible(element)) {
console.log('✅ Found new chat button');
element.click();
await this.delay(3000);
// Проверяем что чат создался
if (await this.hasActiveChat()) {
return;
}
}
}
// Только как последнее средство - навигация
console.log('⚠️ Using navigation fallback');
window.location.href = 'https://chat.deepseek.com/';
await this.delay(5000);
}
async hasActiveChat() {
// Проверяем есть ли активный чат по наличию:
// 1. Поля ввода сообщения
// 2. Истории сообщений
// 3. Конкретных элементов интерфейса чата
const hasInput = this.findInputField();
const hasMessages = document.querySelector('.ds-message') ||
document.querySelector('[class*="message"]');
// Проверяем что мы не на стартовой странице без чата
const isNewChatPage = window.location.href.includes('/chat/new');
const isEmptyStartPage = !hasInput && !hasMessages;
return hasInput && !isNewChatPage && !isEmptyStartPage;
}
async enterPrompt(prompt) {
console.log(`⌨️ Entering prompt: ${prompt.length} characters`);
const textarea = this.findInputField();
if (!textarea) {
throw new Error('Could not find prompt input field');
}
textarea.focus();
await this.delay(1000);
this.clearInputField(textarea);
await this.delay(500);
this.setValue(textarea, prompt);
await this.delay(1000);
const currentValue = this.getValue(textarea);
if (!currentValue.includes(prompt.substring(0, 20))) {
throw new Error('Failed to enter prompt text');
}
// Финальная проверка "Глубокого мышления" перед отправкой
await this.finalDeepThinkingCheck();
await this.sendMessage();
}
async finalDeepThinkingCheck() {
console.log('🔍 Final check: Ensuring Deep Thinking is disabled before sending...');
const deepThinkingButton = this.findDeepThinkingButton();
if (deepThinkingButton && this.isDeepThinkingEnabled(deepThinkingButton)) {
console.log('⚠️ Deep Thinking was re-enabled! Disabling again...');
deepThinkingButton.click();
await this.delay(1000);
// Проверяем еще раз
if (this.isDeepThinkingEnabled(deepThinkingButton)) {
console.log('🔄 Deep Thinking still enabled, one more click...');
deepThinkingButton.click();
await this.delay(1000);
}
console.log('✅ Deep Thinking disabled before sending');
} else {
console.log('✅ Deep Thinking is properly disabled');
}
}
findInputField() {
const selectors = [
'textarea[placeholder*="Message"]',
'textarea[placeholder*="message"]',
'textarea',
'div[contenteditable="true"]',
'div[role="textbox"]'
];
for (const selector of selectors) {
const element = document.querySelector(selector);
if (element && this.isVisible(element)) {
return element;
}
}
return null;
}
clearInputField(element) {
if (element.tagName === 'TEXTAREA' || element.tagName === 'INPUT') {
element.value = '';
} else if (element.isContentEditable) {
element.textContent = '';
}
element.dispatchEvent(new Event('input', { bubbles: true }));
}
async sendMessage() {
console.log('📤 Sending message...');
const sendButtonSelectors = [
'.ds-icon-button',
'button[type="submit"]',
'button:has(svg)',
'textarea ~ button'
];
for (const selector of sendButtonSelectors) {
const element = document.querySelector(selector);
if (element && this.isVisible(element) && !element.disabled && this.isSendButton(element)) {
console.log('✅ Found send button');
element.click();
return;
}
}
console.log('⌨️ Using Enter key');
const event = new KeyboardEvent('keydown', {
key: 'Enter',
code: 'Enter',
keyCode: 13,
which: 13,
bubbles: true
});
const textarea = this.findInputField();
if (textarea) {
textarea.dispatchEvent(event);
}
}
isSendButton(element) {
const svg = element.querySelector('svg');
if (!svg) return false;
const svgHTML = svg.innerHTML || '';
return /path.*d=.*M8\.3125.*Z/.test(svgHTML) || /path.*d=.*arrow/i.test(svgHTML);
}
async waitForResponse() {
console.log('⏳ Waiting for response...');
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
observer.disconnect();
stopButtonMonitor();
reject(new Error('Timeout waiting for response'));
}, 180000);
let lastResponse = '';
let emptyChecks = 0;
const maxEmptyChecks = 10;
const stopButtonFound = this.monitorStopButton(() => {
console.log('🛑 Stop button detected - response complete');
clearTimeout(timeout);
observer.disconnect();
stopButtonMonitor();
setTimeout(() => {
const finalResponse = this.extractLatestResponse();
if (finalResponse && finalResponse.length > 10) {
resolve(finalResponse);
} else {
reject(new Error('Empty response after stop button'));
}
}, 2000);
});
const observer = new MutationObserver(() => {
const currentResponse = this.extractLatestResponse();
const isTyping = this.isStillTyping();
if (currentResponse && currentResponse !== lastResponse) {
lastResponse = currentResponse;
emptyChecks = 0;
} else if (currentResponse === lastResponse && !isTyping) {
emptyChecks++;
if (emptyChecks >= 3) {
clearTimeout(timeout);
observer.disconnect();
stopButtonMonitor();
resolve(currentResponse);
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
characterData: true
});
function stopButtonMonitor() {
if (stopButtonFound.interval) {
clearInterval(stopButtonFound.interval);
}
}
});
}
monitorStopButton(callback) {
const checkInterval = setInterval(() => {
if (this.findStopButton()) {
callback();
}
}, 500);
return { interval: checkInterval };
}
findStopButton() {
const selectors = ['.ds-icon-button.db183363', '.ds-icon-button'];
for (const selector of selectors) {
const element = document.querySelector(selector);
if (element && this.isVisible(element) && this.isStopButton(element)) {
return element;
}
}
return null;
}
isStopButton(element) {
const svg = element.querySelector('svg');
return svg && /M15\.7484.*Z/.test(svg.innerHTML || '');
}
isStillTyping() {
return this.findStopButton() ||
document.querySelector('.typing-indicator') ||
document.querySelector('.streaming');
}
extractLatestResponse() {
console.log('🔍 Extracting latest response...');
// Сначала ищем последнее сообщение ассистента (AI ответ)
const assistantMessages = document.querySelectorAll('.ds-message._63c77b1');
let latestAssistantResponse = null;
// Проходим по всем сообщениям в обратном порядке чтобы найти последний ответ AI
for (let i = assistantMessages.length - 1; i >= 0; i--) {
const message = assistantMessages[i];
// Пропускаем сообщения пользователя (они обычно содержат классы типа fbb737a4)
if (message.querySelector('.fbb737a4')) {
continue;
}
// Ищем финальный ответ AI в ds-markdown (без "Думал" секции)
const finalAnswer = message.querySelector('.ds-markdown:not(.e1675d8b .ds-markdown)');
if (finalAnswer && this.isVisible(finalAnswer)) {
// ИСПРАВЛЕНИЕ: сохраняем переносы строк из HTML
const text = this.cleanResponseText(this.getTextWithLineBreaks(finalAnswer));
if (text && text.length > 20) {
console.log(`✅ Found final AI response: ${text.length} characters`);
latestAssistantResponse = text;
break;
}
}
// Если не нашли финальный ответ, ищем любой текст в сообщении ассистента
const allText = this.getTextWithLineBreaks(message);
if (allText && allText.length > 50 && !allText.includes('Думал')) {
const text = this.cleanResponseText(allText);
if (text && text.length > 20) {
console.log(`✅ Found AI response text: ${text.length} characters`);
latestAssistantResponse = text;
break;
}
}
}
if (latestAssistantResponse) {
return latestAssistantResponse;
}
// Альтернативный поиск: ищем последний ds-markdown который не внутри "Думал" секции
const allMarkdowns = document.querySelectorAll('.ds-markdown');
for (let i = allMarkdowns.length - 1; i >= 0; i--) {
const markdown = allMarkdowns[i];
// Пропускаем markdown внутри "Думал" секции
if (markdown.closest('.e1675d8b')) {
continue;
}
if (this.isVisible(markdown)) {
// ИСПРАВЛЕНИЕ: сохраняем переносы строк
const text = this.cleanResponseText(this.getTextWithLineBreaks(markdown));
if (text && text.length > 20) {
console.log(`✅ Found response in ds-markdown: ${text.length} characters`);
return text;
}
}
}
// Запасной вариант: ищем по структуре сообщений
const messageContainers = document.querySelectorAll('div[class*="message"]');
for (let i = messageContainers.length - 1; i >= 0; i--) {
const container = messageContainers[i];
// Пропускаем контейнеры с вопросами пользователя
if (container.querySelector('.fbb737a4')) {
continue;
}
// ИСПРАВЛЕНИЕ: сохраняем переносы строк
const text = this.cleanResponseText(this.getTextWithLineBreaks(container));
if (text && text.length > 50 && !text.includes('Думал')) {
console.log(`✅ Found response in message container: ${text.length} characters`);
return text;
}
}
console.log('❌ No AI response found');
return null;
}
// НОВЫЙ МЕТОД: извлекает текст с сохранением переносов строк
getTextWithLineBreaks(element) {
if (!element) return '';
// Клонируем элемент чтобы не повредить оригинал
const clone = element.cloneNode(true);
// Заменяем блочные элементы на переносы строк
const blockElements = clone.querySelectorAll('div, p, br, li');
blockElements.forEach(el => {
if (el.tagName === 'BR') {
el.replaceWith('\n');
} else {
// Для блочных элементов добавляем переносы до и после
if (el.previousSibling && el.previousSibling.nodeType === Node.TEXT_NODE) {
el.previousSibling.textContent += '\n';
}
if (el.nextSibling && el.nextSibling.nodeType === Node.TEXT_NODE) {
el.nextSibling.textContent = '\n' + el.nextSibling.textContent;
}
}
});
// Также обрабатываем непосредственные дочерние блочные элементы
const children = Array.from(clone.children);
children.forEach((child, index) => {
if (['DIV', 'P', 'LI'].includes(child.tagName)) {
if (index > 0) {
clone.insertBefore(document.createTextNode('\n'), child);
}
if (index < children.length - 1) {
clone.insertBefore(document.createTextNode('\n'), children[index + 1]);
}
}
});
// Получаем текст с переносами
let text = clone.textContent || '';
// Очищаем множественные переносы (оставляем максимум 2 подряд)
text = text.replace(/\n{3,}/g, '\n\n');
// Убираем переносы в начале и конце
text = text.trim();
return text;
}
cleanResponseText(text) {
if (!text) return '';
// Сохраняем переносы строк, убираем только лишнее
let cleaned = text
.replace(/||||/gi, '')
.replace(/\*\*/g, '') // убираем но сохраняем переносы
.trim();
// Убеждаемся что есть хотя бы один перенос если текст длинный
if (cleaned.length > 100 && !cleaned.includes('\n')) {
// Попробуем добавить переносы после точек для длинных текстов
cleaned = cleaned.replace(/\.\s+/g, '.\n\n');
}
return cleaned;
}
isVisible(element) {
if (!element) return false;
const style = window.getComputedStyle(element);
return !!(element.offsetWidth || element.offsetHeight) &&
style.display !== 'none' &&
style.visibility !== 'hidden';
}
setValue(element, value) {
if (element.tagName === 'TEXTAREA' || element.tagName === 'INPUT') {
element.value = value;
} else if (element.isContentEditable) {
element.textContent = value;
}
element.dispatchEvent(new Event('input', { bubbles: true }));
}
getValue(element) {
if (element.tagName === 'TEXTAREA' || element.tagName === 'INPUT') {
return element.value;
} else if (element.isContentEditable) {
return element.textContent;
}
return '';
}
isRetryableError(error) {
const retryableErrors = ['timeout', 'network', 'not found', 'not visible'];
return retryableErrors.some(retryable => error.message.toLowerCase().includes(retryable));
}
async sendResultToBackground(taskId, result) {
// Важная проверка: убеждаемся что отправляем результат для текущей задачи
if (this.currentTaskId !== taskId) {
console.error(`❌ Task ID mismatch in content script! Current: ${this.currentTaskId}, Sending for: ${taskId}`);
return;
}
try {
console.log(`📤 Sending result to background for task: ${taskId}`);
await chrome.runtime.sendMessage({
type: 'TASK_RESULT',
taskId: taskId,
result: result
});
console.log('✅ Result sent to background script');
// Останавливаем обработку задачи после отправки результата
this.completeTaskProcessing();
} catch (error) {
console.error('❌ Failed to send result to background:', error);
this.completeTaskProcessing(); // УБРАТЬ stopShareButtonMonitoring отсюда
}
}
async sendErrorToBackground(taskId, error) {
// Проверяем что ошибка для текущей задачи
if (this.currentTaskId !== taskId) {
console.error(`❌ Task ID mismatch for error! Current: ${this.currentTaskId}, Error for: ${taskId}`);
return;
}
try {
await chrome.runtime.sendMessage({
type: 'TASK_ERROR',
taskId: taskId,
error: error
});
console.log('✅ Error sent to background script');
this.completeTaskProcessing(); // УБРАТЬ stopShareButtonMonitoring отсюда
} catch (error) {
console.error('❌ Failed to send error to background:', error);
this.completeTaskProcessing(); // УБРАТЬ stopShareButtonMonitoring отсюда
}
}
completeTaskProcessing() {
console.log(`✅ Completing task processing in content script: ${this.currentTaskId}`);
this.isProcessing = false;
this.currentTask = null;
this.currentTaskId = null;
this.retryCount = 0;
// УБРАТЬ: this.stopShareButtonMonitoring(); - этого метода больше нет
}
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// Инициализация
if (!window.deepSeekContentScript) {
window.deepSeekContentScript = new DeepSeekContentScript();
}
}
Основные исправления:
Убрал все вызовы stopShareButtonMonitoring - этого метода больше нетУлучшил метод getTextWithLineBreaks - теперь он правильно извлекает полный текстДобавил обработку блочных элементов - чтобы не обрезать текстУлучшил очистку текста - сохраняет структуру но убирает лишнее
Теперь текст должен приходить полностью, без обрезки! 📝✨
Девушка с двухлетним ребёнком попала под колёса иномарки в Шпаковском округе https://partygorsk.com/news/67204-devushka_s_dvuhletnim_rebenkom_popala_pod_kolesa_inomarki_v_
Поделиться новостью