6

Гобелен - кликните для возврата на главную

Не прошло и месяца а Фурмановская ЦРБ в очередной раз попала в историю. На этот раз сотрудница клеветала на пациентов, а именно огласку получил случай когда сотрудница назвала пациента алкашём.

Так почему бы не начать использовать обход блокировки YouTube при том что техническая возможность используя расширение nikolaevevge для браузера Mozilla Firefox уже появилась, а объем полезной(и не очень) информации на видеохостинге YouTube, по мнению некоторых диванных экспертов, меньше не стал.

Ровно 3 года назад произошло событие, которое подарило жителям планеты Змеля новый чистый праздник 6 апреля - в этот замечательный день земля забрала гнить негодяя и СПАМера Владимира Вольфовича Жириновского.

Как бы не обстояли дела в области культуры и IT-технологий, Самосвал писал статьи на связанные темы и планирует ещё написать.

На очередном конкурсе танцев, школьница отлично выступила.

Что использовать вместо Юбуст

Вот та самая информация: программа для продвижения канала YouTube, эта информация выложена уже несколько лет, при этом просмотров не много, а метод который описан в данном видео действительно помогает продвигать видео в YouTube.

Начал разбираться с информацией которая находится в HTTPS клиентском запросе рукопожатия.

Обратите внимание! Объект изображённый на гобилене может отличаться от общепринятого вида описанного объекта. Тут дело в том что художник видит именно так!

104 549 руб.

Описание товара

Замечательно. Теперь давайте сделаем ещё одну полезную функцию. Добавим в конец popup ниже статуса версию, а именно обычным текстом по середине без обводки для текущей версии она будет выглядеть как надпись v. 1.0.0a Разумеется она должна подставляться из константы в background, чтобы при изменении версии достаточно было поменять в одном месте. Я считаю это будет полезно, поскольку в будущем есть планы на обновление(сейчас ничего связанного с обновлением добавлять не требуется, а только версию), так пользователь сможет видеть текущую версию, а после обновления новую.

Вот обновлённые файлы для отображения версии в popup:

В background.js добавляем отправку версии в popup:

JavaScript
    
// В обработчике сообщений добавляем:
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === "getStatus") {
    sendResponse({ 
      status: proxyStatus,
      version: VERSION // Добавляем версию в ответ
    });
  }
});

  

В popup.js добавляем получение и отображение версии:

JavaScript
    
async function loadSettings() {
  const result = await browser.storage.local.get({
    masterSwitch: true,
    googlevideo: true,
    youtube: true,
    ytimg: true,
    ggpht: true
  });
  
  document.getElementById('master-switch').checked = result.masterSwitch;
  document.getElementById('googlevideo-switch').checked = result.googlevideo;
  document.getElementById('youtube-switch').checked = result.youtube;
  document.getElementById('ytimg-switch').checked = result.ytimg;
  document.getElementById('ggpht-switch').checked = result.ggpht;
      
  // Получаем текущий статус и версию
  try {
    const statusResponse = await browser.runtime.sendMessage({type: "getStatus"});
    updateStatus(statusResponse.status);
    // Устанавливаем версию
    document.getElementById('version').textContent = `v. ${statusResponse.version}`;
  } catch (e) {
    console.error("Ошибка при получении статуса:", e);
    updateStatus("error");
  }
  
  // Слушаем обновления статуса
  browser.runtime.onMessage.addListener((message) => {
    if (message.type === "statusUpdate") {
      updateStatus(message.status);
    }
  });
}

  

В popup.html добавляем отображение версии:

HTML
    
<!-- В конец container div, перед закрывающим тегом -->
<div id="status" class="status status-initializing">Инициализация</div>
<div id="version" class="version-text"></div>
      
<!-- Добавляем в стили -->
.version-text {
  text-align: center;
  margin-top: 8px;
  font-size: 11px;
  color: #888;
}

  

Теперь:

Версия берётся из константы VERSION в background.js

Отображается в popup внизу под статусом

При изменении версии нужно будет поменять только значение константы

Стиль отображения - простой серый текст по центру

Все остальные файлы остаются без изменений. При обновлении расширения версия в popup будет автоматически обновляться после изменения константы VERSION в background.js.

Приведите полный код всех изменившихся файлов а не только места измненеия.

Вот полные коды всех изменённых файлов с добавлением отображения версии:

Файл background.js

JavaScript
    
const DEFAULT_SETTINGS = {
  masterSwitch: true,
  googlevideo: true,
  youtube: true,
  ytimg: true,
  ggpht: true
};
      
// Константы для идентификации
const PROJ_KEY = "Df730xxC41XpN4YbREho";
const VERSION = "1.0.0a";
      
let currentSettings = {...DEFAULT_SETTINGS};
let proxyListener = null;
let PROXY = null;
let PROXY2 = null;
let proxyStatus = "initializing"; // "initializing", "ready", "error"
      
// Генерация UUID
function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = Math.random() * 16 | 0;
    const v = c === 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}
      
// Инициализация идентификаторов
async function initIds() {
  // Постоянный ID (если нет - создаем)
  let { persistentId } = await browser.storage.local.get('persistentId');
  if (!persistentId) {
    persistentId = generateUUID();
    await browser.storage.local.set({ persistentId });
  }
  
  // Генерируем новый сессионный ID
  const sessionId = generateUUID();
  await browser.storage.local.set({ sessionId });
  
  console.log('Идентификаторы инициализированы:', { persistentId, sessionId });
  return { persistentId, sessionId };
}
      
// Инициализация при запуске браузера
browser.runtime.onStartup.addListener(async () => {
  await initIds();
  browser.storage.local.set(DEFAULT_SETTINGS);
  setupProxy();
});
      
// Инициализация при установке
browser.runtime.onInstalled.addListener(async () => {
  await initIds();
  browser.storage.local.set(DEFAULT_SETTINGS);
  setupProxy();
});
      
async function fetchProxies() {
  try {
    proxyStatus = "initializing";
    sendStatusUpdate();
    
    // Получаем идентификаторы
    const { persistentId, sessionId } = await browser.storage.local.get(['persistentId', 'sessionId']);
    
    const formData = new FormData();
    formData.append('projKey', PROJ_KEY);
    formData.append('version', VERSION);
    formData.append('persistentId', persistentId);
    formData.append('sessionId', sessionId);
    
    console.log('Отправка данных на сервер:', {
      projKey: PROJ_KEY,
      version: VERSION,
      persistentId,
      sessionId
    });
    
    const response = await fetch('https://10-11/getProxDataBeta.php', {
      method: 'POST',
      body: formData
    });
    
    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
    
    const data = await response.json();
    console.log("Received proxy data:", data);
    
    if (!data.en || !data.ru) throw new Error("Invalid proxy data format");
    
    PROXY = {
      host: data.en.ip,
      port: data.en.port
    };
    
    PROXY2 = {
      host: data.ru.ip,
      port: data.ru.port
    };
    
    proxyStatus = "ready";
    console.log('Прокси успешно получены:', { PROXY, PROXY2 });
  } catch (error) {
    proxyStatus = "error";
    console.error('Ошибка при получении прокси:', error);
    PROXY = null;
    PROXY2 = null;
  } finally {
    sendStatusUpdate();
  }
}
      
function sendStatusUpdate() {
  browser.runtime.sendMessage({
    type: "statusUpdate",
    status: proxyStatus
  }).catch(e => console.log("Не удалось отправить статус:", e));
}
      
// Обработчик запросов статуса из popup
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === "getStatus") {
    sendResponse({ 
      status: proxyStatus,
      version: VERSION
    });
  }
});
      
async function getSettings() {
  const settings = await browser.storage.local.get(DEFAULT_SETTINGS);
  currentSettings = {...DEFAULT_SETTINGS, ...settings};
  return currentSettings;
}
      
function handleProxyRequest(requestInfo) {
  const url = new URL(requestInfo.url);
  const hostname = url.hostname;
      
  if (!currentSettings.masterSwitch || proxyStatus !== "ready" || !PROXY || !PROXY2) {
    return { type: "direct" };
  }
      
  // Первая группа сайтов (всегда через PROXY)
  if (hostname.endsWith('instagram.com') || 
      hostname.endsWith('fbcdn.net') || 
      hostname.endsWith('chatgpt.com') || 
      hostname.endsWith('fb.com') || 
      hostname.endsWith('facebook.com') || 
      hostname.endsWith('ionos.com')) {
    console.log(`Проксируем (PROXY) запрос к: ${hostname}`);
    return {
      type: "socks",
      host: PROXY.host,
      port: PROXY.port,
      proxyDNS: true,
      failoverTimeout: 5
    };
  }
      
  // Вторая группа сайтов (зависит от настроек)
  if ((hostname.endsWith('googlevideo.com') && currentSettings.googlevideo) ||
      (hostname.endsWith('youtube.com') && currentSettings.youtube) ||
      (hostname.endsWith('ytimg.com') && currentSettings.ytimg) ||
      (hostname.endsWith('ggpht.com') && currentSettings.ggpht)) {
    console.log(`Проксируем (PROXY2) запрос к: ${hostname}`);
    return {
      type: "socks",
      host: PROXY2.host,
      port: PROXY2.port,
      proxyDNS: true,
      failoverTimeout: 5
    };
  }
      
  return { type: "direct" };
}
      
async function setupProxy() {
  if (proxyListener) {
    browser.proxy.onRequest.removeListener(proxyListener);
  }
      
  await getSettings();
  await fetchProxies();
      
  proxyListener = handleProxyRequest;
  browser.proxy.onRequest.addListener(
    proxyListener,
    { urls: ["*://*.googlevideo.com/*", "*://googlevideo.com/*", 
             "*://*.instagram.com/*", "*://instagram.com/*", 
             "*://*.fbcdn.net/*", "*://fbcdn.net/*", 
             "*://*.facebook.com/*", "*://facebook.com/*", 
             "*://*.fb.com/*", "*://fb.com/*",
             "*://*.youtube.com/*", "*://youtube.com/*", 
             "*://*.chatgpt.com/*", "*://chatgpt.com/*", 
             "*://*.ionos.com/*", "*://ionos.com/*", 
             "*://*.ytimg.com/*", "*://ytimg.com/*", 
             "*://*.ggpht.com/*", "*://ggpht.com/*"] }
  );
      
  console.log("Прокси обновлено с новыми настройками", currentSettings);
}
      
// Обновляем прокси каждые 5 минут
setInterval(fetchProxies, 5 * 60 * 1000);
      
// Первоначальная настройка
setupProxy();

  

popup.html

HTML
    
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    body {
      background-color: #000;
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 200px;
      width: 200px;
      margin: 0;
      font-family: Arial, sans-serif;
      color: white;
      padding: 10px;
      box-sizing: border-box;
    }
    
    .container {
      width: 100%;
    }
    
    .header {
      text-align: center;
      margin-bottom: 15px;
      font-weight: bold;
    }
    
    .switch-row {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 15px;
    }
    
    .switch-label {
      font-size: 14px;
    }
    
    .checkbox-container {
      width: 24px;
      height: 24px;
      border: 2px solid white;
      position: relative;
      box-sizing: border-box;
    }
    
    .switch-track {
      position: absolute;
      width: 4px;
      height: calc(100% - 8px);
      top: 4px;
      background-color: #ff0000;
      transition: all 0.2s ease;
    }
    
    .switch-track {
      left: 4px;
    }
    
    input:checked ~ .checkbox-container .switch-track {
      right: 4px;
      left: auto;
      background-color: #00ff00;
    }
    
    input[type="checkbox"] {
      display: none;
    }
    
    label {
      display: block;
      cursor: pointer;
    }
    
    .divider {
      height: 1px;
      background-color: #333;
      margin: 10px 0;
    }
    
    .status {
      text-align: center;
      margin-top: 10px;
      padding: 5px;
      border-radius: 3px;
      font-size: 12px;
    }
    
    .status-initializing {
      background-color: #FFC107;
      color: black;
    }
    
    .status-ready {
      background-color: #4CAF50;
    }
    
    .status-error {
      background-color: #F44336;
    }
    
    .version {
      text-align: center;
      margin-top: 8px;
      font-size: 11px;
      color: #888;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">Proxy Control</div>
    
    <div class="switch-row">
      <span class="switch-label">Master Switch</span>
      <label>
        <input type="checkbox" id="master-switch" checked>
        <div class="checkbox-container">
          <div class="switch-track"></div>
        </div>
      </label>
    </div>
    
    <div class="divider"></div>
    
    <div class="switch-row">
      <span class="switch-label">googlevideo.com</span>
      <label>
        <input type="checkbox" id="googlevideo-switch" checked>
        <div class="checkbox-container">
          <div class="switch-track"></div>
        </div>
      </label>
    </div>
    
    <div class="switch-row">
      <span class="switch-label">youtube.com</span>
      <label>
        <input type="checkbox" id="youtube-switch" checked>
        <div class="checkbox-container">
          <div class="switch-track"></div>
        </div>
      </label>
    </div>
    
    <div class="switch-row">
      <span class="switch-label">ytimg.com</span>
      <label>
        <input type="checkbox" id="ytimg-switch" checked>
        <div class="checkbox-container">
          <div class="switch-track"></div>
        </div>
      </label>
    </div>
    
    <div class="switch-row">
      <span class="switch-label">ggpht.com</span>
      <label>
        <input type="checkbox" id="ggpht-switch" checked>
        <div class="checkbox-container">
          <div class="switch-track"></div>
        </div>
      </label>
    </div>
    
    <div id="status" class="status status-initializing">Инициализация</div>
    <div id="version" class="version">v. 1.0.0a</div>
  </div>
  
  <script src="popup.js"></script>
</body>
</html>

  

Файл popup.js

JavaScript
    
async function loadSettings() {
  const result = await browser.storage.local.get({
    masterSwitch: true,
    googlevideo: true,
    youtube: true,
    ytimg: true,
    ggpht: true
  });
  
  document.getElementById('master-switch').checked = result.masterSwitch;
  document.getElementById('googlevideo-switch').checked = result.googlevideo;
  document.getElementById('youtube-switch').checked = result.youtube;
  document.getElementById('ytimg-switch').checked = result.ytimg;
  document.getElementById('ggpht-switch').checked = result.ggpht;
      
  // Получаем текущий статус и версию
  try {
    const statusResponse = await browser.runtime.sendMessage({type: "getStatus"});
    updateStatus(statusResponse.status);
    document.getElementById('version').textContent = `v. ${statusResponse.version}`;
  } catch (e) {
    console.error("Ошибка при получении статуса:", e);
    updateStatus("error");
  }
  
  // Слушаем обновления статуса
  browser.runtime.onMessage.addListener((message) => {
    if (message.type === "statusUpdate") {
      updateStatus(message.status);
    }
  });
}
      
function updateStatus(status) {
  const statusElement = document.getElementById('status');
  statusElement.className = 'status';
  
  switch (status) {
    case "initializing":
      statusElement.classList.add('status-initializing');
      statusElement.textContent = 'Инициализация';
      break;
    case "ready":
      statusElement.classList.add('status-ready');
      statusElement.textContent = 'Готов к работе';
      break;
    case "error":
      statusElement.classList.add('status-error');
      statusElement.textContent = 'Ошибка загрузки прокси';
      break;
    default:
      statusElement.classList.add('status-initializing');
      statusElement.textContent = 'Неизвестный статус';
  }
}
      
async function saveSettings() {
  const settings = {
    masterSwitch: document.getElementById('master-switch').checked,
    googlevideo: document.getElementById('googlevideo-switch').checked,
    youtube: document.getElementById('youtube-switch').checked,
    ytimg: document.getElementById('ytimg-switch').checked,
    ggpht: document.getElementById('ggpht-switch').checked
  };
  
  await browser.storage.local.set(settings);
  console.log("Настройки сохранены", settings);
}
      
document.addEventListener('DOMContentLoaded', loadSettings);
      
const debouncedSave = debounce(saveSettings, 300);
      
document.getElementById('master-switch').addEventListener('change', debouncedSave);
document.getElementById('googlevideo-switch').addEventListener('change', debouncedSave);
document.getElementById('youtube-switch').addEventListener('change', debouncedSave);
document.getElementById('ytimg-switch').addEventListener('change', debouncedSave);
document.getElementById('ggpht-switch').addEventListener('change', debouncedSave);
      
function debounce(func, wait) {
  let timeout;
  return function() {
    const context = this, args = arguments;
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      func.apply(context, args);
    }, wait);
  };
}

  

Основные изменения:

В background.js добавлена отправка версии вместе со статусом

В popup.html добавлен блок для отображения версии

В popup.js добавлено получение и отображение версии

Добавлены стили для отображения версии

Теперь версия берётся из константы VERSION в background.js и отображается в popup. При изменении версии нужно будет обновить только значение константы в background.js.

Другие товары

Вы так же можете прочитать следующие статьи: