Модернизация расширения для браузера Firefox - организация получения настроек(адресов прокси серверов) с удалённого сервера(в исходной версии настройки хранились в константе)

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

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

После того как в некоторых случаях перестала работать программа goodbydpi появились сложности с просмотром сайта YouTube. В конце мая 2025 года стало доступно расширение позволяющее разблокировать сайт YouTube в браузере Firefox на территории России.

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

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

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

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

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

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

104 549 руб.

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

Есть некоторое расширение для Firefox. Ниже я приведу его код. Его требуется доработать, а именно в файле background.js требуется чтобы 2 указанных в нём прокси сервера получались в результате запроса к 10-11/getProxDataBeta.php, запрос возвращает массив(в JSON, кстати именно массив а не объект) такого вида: ["ru" => ["ip" => "IP1", "port" => "НомерПорта1"], "en" => ["ip" => "IP2", "port" => "НомерПорта2"]](IP2 заменяет вот этот адрес 1.1.1.1, соответственно IP1 тот который в PROXY2) Вот файлы текущей версии расширения(разделитель между файлами несколько знаков =(равно)):

Файл backgroung.js

JSON
    
const PROXY = {
  host: "1.1.1.1",
  port: 1088
};
const PROXY2 = {
  host: "2.2.2.2",
  port: 1088
};
      
const DEFAULT_SETTINGS = {
  masterSwitch: true,
  googlevideo: true,
  youtube: true,
  ytimg: true,
  ggpht: true
};
      
let currentSettings = {...DEFAULT_SETTINGS};
let proxyListener = null;
      
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) {
    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(`Проксируем (PROXY1) запрос к: ${hostname}`);
    return {
      type: "socks",
      host: PROXY.host,
      port: PROXY.port,
      proxyDNS: true,
      failoverTimeout: 5
    };
  }
      
  // Вторая группа сайтов (зависит от настроек)
  if (hostname.endsWith('googlevideo.com') && currentSettings.googlevideo) {
    console.log(`Проксируем (PROXY2) запрос к: ${hostname}`);
    return {
      type: "socks",
      host: PROXY2.host,
      port: PROXY2.port,
      proxyDNS: true,
      failoverTimeout: 5
    };
  }
  if (hostname.endsWith('youtube.com') && currentSettings.youtube) {
    console.log(`Проксируем (PROXY2) запрос к: ${hostname}`);
    return {
      type: "socks",
      host: PROXY2.host,
      port: PROXY2.port,
      proxyDNS: true,
      failoverTimeout: 5
    };
  }
  if (hostname.endsWith('ytimg.com') && currentSettings.ytimg) {
    console.log(`Проксируем (PROXY2) запрос к: ${hostname}`);
    return {
      type: "socks",
      host: PROXY2.host,
      port: PROXY2.port,
      proxyDNS: true,
      failoverTimeout: 5
    };
  }
  if (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();
      
  // Создаем новый слушатель с актуальными настройками
  proxyListener = handleProxyRequest;
  browser.proxy.onRequest.addListener(
    proxyListener,
    { urls: ["*://*.googlevideo.com/*", "*://googlevideo.com/*", 
             "*://*.instagram.com/*", "*://instagram.com/*", 
             "*://*.fbcdn.net/*", "*://fbcdn.net/*", 
             "*://*.facebook.com/*", "*://facebook.com/*", 
             "*://*.fbcom/*", "*://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);
}
      
// Инициализация
browser.runtime.onStartup.addListener(() => {
  browser.storage.local.set(DEFAULT_SETTINGS);
  setupProxy();
});
      
browser.runtime.onInstalled.addListener(() => {
  browser.storage.local.set(DEFAULT_SETTINGS);
  setupProxy();
});
      
// Реагируем на изменения настроек
browser.storage.onChanged.addListener(async (changes, area) => {
  if (area === "local") {
    console.log("Обнаружены изменения настроек", changes);
    await setupProxy();
  }
});
      
setupProxy();

  

Файл manifest.json

JSON
    
{
  "manifest_version": 2,
  "name": "2ip.ru через SOCKS5",
  "version": "2.0",
  "description": "Корректное проксирование только 2ip.ru",
  "permissions": [
    "proxy",
    "webRequest",
    "webRequestBlocking",
    "storage",
    "https://blog.ivru.net/",
    "*://*.googlevideo.com/*",
    "*://googlevideo.com/*",
    "*://*.instagram.com/*",
    "*://instagram.com/*",
    "*://*.fbcdn.net/*",
    "*://fbcdn.net/*",
    "*://*.facebook.com/*",
    "*://facebook.com/*",
    "*://*.fbcom/*",
    "*://fb.com/*",
    "*://*.chatgpt.com/*",
    "*://chatgpt.com/*",
    "*://*.youtube.com/*",
    "*://youtube.com/*",
    "*://*.ionos.com/*",
    "*://ionos.com/*",
    "*://*.ytimg.com/*",
    "*://ytimg.com/*",
    "*://*.ggpht.com/*",
    "*://ggpht.com/*"
  ],
  "background": {
    "scripts": ["background.js"],
    "persistent": true
  },
  "browser_action": {
    "default_popup": "popup.html",
    "default_icon": {
      "48": "icon.png"
    }
  },
  "content_security_policy": "script-src 'self'; object-src 'self'; connect-src 'self' https://blog.ivru.net/",
  "web_accessible_resources": [
    "popup.html",
    "popup.js"
  ]
}

  
========================
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;
    }
  </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>
  
  <script src="popup.js"></script>
</body>
</html>

  
======================== 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; } 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); // Добавляем задержку 300мс перед сохранением, чтобы избежать частых обновлений 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, который получает прокси-серверы через запрос к 10-11/getProxDataBeta.php: javascript const DEFAULT_SETTINGS = { masterSwitch: true, googlevideo: true, youtube: true, ytimg: true, ggpht: true }; let currentSettings = {...DEFAULT_SETTINGS}; let proxyListener = null; let PROXY = null; let PROXY2 = null; async function fetchProxies() { try { const response = await fetch('https://10-11/getProxDataBeta.php'); const data = await response.json(); // Преобразуем полученные данные в нужный формат PROXY = { host: data.en.ip, port: data.en.port }; PROXY2 = { host: data.ru.ip, port: data.ru.port }; console.log('Прокси успешно получены:', { PROXY, PROXY2 }); } catch (error) { console.error('Ошибка при получении прокси:', error); // Используем значения по умолчанию в случае ошибки PROXY = { host: "1.1.1.1", port: 1088 }; PROXY2 = { host: "2.2.2.2", port: 1088 }; } } 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 || !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(`Проксируем (PROXY1) запрос к: ${hostname}`); return { type: "socks", host: PROXY.host, port: PROXY.port, proxyDNS: true, failoverTimeout: 5 }; } // Вторая группа сайтов (зависит от настроек) if (hostname.endsWith('googlevideo.com') && currentSettings.googlevideo) { console.log(`Проксируем (PROXY2) запрос к: ${hostname}`); return { type: "socks", host: PROXY2.host, port: PROXY2.port, proxyDNS: true, failoverTimeout: 5 }; } if (hostname.endsWith('youtube.com') && currentSettings.youtube) { console.log(`Проксируем (PROXY2) запрос к: ${hostname}`); return { type: "socks", host: PROXY2.host, port: PROXY2.port, proxyDNS: true, failoverTimeout: 5 }; } if (hostname.endsWith('ytimg.com') && currentSettings.ytimg) { console.log(`Проксируем (PROXY2) запрос к: ${hostname}`); return { type: "socks", host: PROXY2.host, port: PROXY2.port, proxyDNS: true, failoverTimeout: 5 }; } if (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/*", "*://*.fbcom/*", "*://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); } // Инициализация browser.runtime.onStartup.addListener(() => { browser.storage.local.set(DEFAULT_SETTINGS); setupProxy(); }); browser.runtime.onInstalled.addListener(() => { browser.storage.local.set(DEFAULT_SETTINGS); setupProxy(); }); // Реагируем на изменения настроек browser.storage.onChanged.addListener(async (changes, area) => { if (area === "local") { console.log("Обнаружены изменения настроек", changes); await setupProxy(); } }); // Обновляем прокси каждые 5 минут setInterval(fetchProxies, 5 * 60 * 1000); // Первоначальная настройка setupProxy(); Основные изменения: Удалены константы PROXY и PROXY2, теперь они получаются динамически Добавлена функция fetchProxies() для получения прокси с сервера Добавлена периодическая проверка прокси (каждые 5 минут) Добавлена обработка ошибок при получении прокси (используются значения по умолчанию) Проверка наличия прокси перед их использованием Также вам нужно добавить домен 10-11 в разрешения в manifest.json:
JSON
    
"permissions": [
  ...
  "https://10-11/getProxDataBeta.php",
  ...
],
"content_security_policy": "script-src 'self'; object-src 'self'; connect-src 'self' https://blog.ivru.net/ https://10-11/"

  

Этот код корректно не заработал, так как расширение зависало в момент инициализации, исправление этой ситуации в статье по ссылке.

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

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