From a11134f303453fb0228c75d96199e72ed4df9477 Mon Sep 17 00:00:00 2001 From: dv Date: Mon, 23 Mar 2026 15:36:40 +0300 Subject: [PATCH] ok1 --- $remote | 27 ++++ DEPLOY.md | 289 ++++++++++++++++++++++++++++++++++++++ auto-update.bat | 41 ++++++ js/background.js | 47 +++++++ manifest.json | 6 +- pack-crx.bat | 46 ++++++ server/caps-enhancer.zip | Bin 0 -> 55599 bytes server/deploy.sh | 38 +++++ server/install-client.ps1 | 38 +++++ server/install-client.reg | 13 ++ server/nginx.conf | 40 ++++++ server/pack-zip.bat | 40 ++++++ server/update.xml | 19 +++ server/version.json | 1 + 14 files changed, 644 insertions(+), 1 deletion(-) create mode 100644 $remote create mode 100644 DEPLOY.md create mode 100644 auto-update.bat create mode 100644 js/background.js create mode 100644 pack-crx.bat create mode 100644 server/caps-enhancer.zip create mode 100644 server/deploy.sh create mode 100644 server/install-client.ps1 create mode 100644 server/install-client.reg create mode 100644 server/nginx.conf create mode 100644 server/pack-zip.bat create mode 100644 server/update.xml create mode 100644 server/version.json diff --git a/$remote b/$remote new file mode 100644 index 0000000..3840320 --- /dev/null +++ b/$remote @@ -0,0 +1,27 @@ +Split-Path : Cannot bind argument to parameter 'Path' because it is null. +At line:1 char:177 ++ ... ; $EXT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path; $manif ... ++ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + CategoryInfo : InvalidData: (:) [Split-Path], ParameterBindingValidationException + + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.SplitPathCo + mmand + +Join-Path : Cannot bind argument to parameter 'Path' because it is null. +At line:1 char:242 ++ ... n.MyCommand.Path; $manifest = Get-Content (Join-Path $EXT_DIR 'manife ... ++ ~~~~~~~~ + + CategoryInfo : InvalidData: (:) [Join-Path], ParameterBindingValidationException + + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.JoinPathCom + mand + +Local: Remote: 2.7 +[INFO] Updating - ... +Expand-Archive : Cannot validate argument on parameter 'DestinationPath'. The argument is null or empty. Provide an arg +ument that is not null or empty, and then try the command again. +At line:1 char:756 ++ ... OutFile $tmp; Expand-Archive $tmp -DestinationPath $EXT_DIR -Force; ... ++ ~~~~~~~~ + + CategoryInfo : InvalidData: (:) [Expand-Archive], ParameterBindingValidationException + + FullyQualifiedErrorId : ParameterArgumentValidationError,Expand-Archive + +[OK] Done. Reload extension in chrome://extensions diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..f5ed0a8 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,289 @@ +# Деплой CAPS Enhancer — Self-Hosted Auto-Update + +## Как это работает + +``` +[Сервер] [Браузер пользователя] + update.xml <── Chrome опрашивает каждые ~5 часов + caps-enhancer.crx <── Chrome скачивает при новой версии +``` + +Chrome сравнивает `version` в `update.xml` с версией установленного расширения. +Если версия на сервере выше — скачивает `.crx` и устанавливает обновление автоматически. + +Пользователь устанавливает расширение **один раз** через реестр Windows — дальше всё автоматически. + +--- + +## Часть 1: Первоначальная упаковка (делается один раз) + +### Шаг 1. Прописать URL обновления в manifest.json + +Открой `manifest.json` и замени `YOUR_DOMAIN` на реальный домен: + +```json +"update_url": "https://updates.example.com/caps-enhancer/update.xml", +``` + +### Шаг 2. Упаковать расширение в .crx + +**Способ A — через bat-скрипт (рекомендуется):** + +Запусти `pack-crx.bat` из папки проекта. Скрипт сам найдёт Chrome и упакует расширение. + +**Способ B — вручную через Chrome:** + +1. Открой `chrome://extensions` +2. Включи "Режим разработчика" (правый верхний угол) +3. Нажми "Упаковать расширение" +4. В поле "Корневой каталог расширения" укажи папку `caps-enhancer` +5. Поле "Файл закрытого ключа" оставь пустым при первой упаковке +6. Нажми "Упаковать расширение" + +Chrome создаст два файла **в папке рядом с `caps-enhancer`**: +- `caps-enhancer.crx` — файл расширения +- `caps-enhancer.pem` — приватный ключ + +> **КРИТИЧНО:** Сохрани `caps-enhancer.pem` в надёжное место! +> Этот ключ определяет ID расширения. Если потеряешь — ID изменится, +> и все установленные у пользователей копии придётся переустанавливать вручную. + +### Шаг 3. Узнать ID расширения + +**После первой упаковки:** + +1. Открой `chrome://extensions` +2. Нажми "Загрузить распакованное расширение" → выбери папку `caps-enhancer` +3. Скопируй ID расширения (длинная строка из 32 символов, например `abcdefghijklmnopqrstuvwxyzabcdef`) + +**Или через файл ключа (если Chrome уже закрыт):** + +```bash +# На Linux/Mac: +openssl rsa -in caps-enhancer.pem -pubout | openssl dgst -sha256 -binary | base32 | head -c 32 | tr '[:upper:]' '[:lower:]' +``` + +### Шаг 4. Обновить update.xml + +Открой `server/update.xml` и замени: +- `EXTENSION_ID` — ID из предыдущего шага +- `YOUR_DOMAIN` — твой домен +- `version` — текущая версия (из manifest.json) + +```xml + + + + + +``` + +--- + +## Часть 2: Настройка сервера + +### Требования к серверу + +- Любой веб-сервер (nginx, Apache, Caddy, даже GitHub Pages) +- **HTTPS обязателен** — Chrome отказывается скачивать `.crx` по HTTP +- Корректные MIME-типы (см. ниже) + +### Вариант A: nginx + +Скопируй `server/nginx.conf` на сервер и замени `YOUR_DOMAIN`: + +```bash +sudo cp server/nginx.conf /etc/nginx/sites-available/caps-enhancer +sudo ln -s /etc/nginx/sites-available/caps-enhancer /etc/nginx/sites-enabled/ +sudo nginx -t && sudo systemctl reload nginx +``` + +Структура файлов на сервере: +``` +/var/www/caps-enhancer/ +└── caps-enhancer/ + ├── update.xml + └── caps-enhancer.crx +``` + +### Вариант B: Apache + +Добавь в `.htaccess` или конфиг: + +```apache + + AddType application/x-chrome-extension .crx + AddType application/xml .xml + + + Header set Cache-Control "no-cache, no-store, must-revalidate" + Header set Pragma "no-cache" + Header set Expires 0 + + +``` + +### Вариант C: Caddy (самый простой, HTTPS автоматически) + +``` +updates.example.com { + root * /var/www/caps-enhancer + file_server + + @xml path *.xml + header @xml Cache-Control "no-cache, no-store, must-revalidate" +} +``` + +### Вариант D: GitHub Pages / любой статический хостинг + +Положи `update.xml` и `caps-enhancer.crx` в репозиторий. +GitHub Pages раздаёт файлы по HTTPS автоматически. + +> Убедись что хостинг отдаёт `.crx` с типом `application/x-chrome-extension` +> или `application/octet-stream`. GitHub Pages обычно справляется. + +### Загрузка файлов на сервер + +```bash +# С локальной машины через scp +scp server/caps-enhancer.crx server/update.xml user@your-server:/var/www/caps-enhancer/caps-enhancer/ + +# Или через rsync +rsync -av server/caps-enhancer.crx server/update.xml user@your-server:/var/www/caps-enhancer/caps-enhancer/ +``` + +### Проверка сервера + +После загрузки проверь: + +```bash +# update.xml должен вернуть XML с версией +curl -I https://updates.example.com/caps-enhancer/update.xml + +# .crx должен вернуть 200 и Content-Type: application/x-chrome-extension +curl -I https://updates.example.com/caps-enhancer/caps-enhancer.crx +``` + +--- + +## Часть 3: Установка на компьютеры пользователей + +Chrome не позволяет устанавливать сторонние расширения вручную через stable-канал. +Единственный способ — через **Windows Policy (реестр)**. + +### Способ A: .reg файл (для ручной установки) + +1. Открой `server/install-client.reg` +2. Замени `EXTENSION_ID` и `YOUR_DOMAIN` +3. Дай пользователю этот файл +4. Пользователь дважды кликает на `.reg` → соглашается → перезапускает Chrome + +```reg +[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist] +"1"="abcdefghijklmnopqrstuvwxyzabcdef;https://updates.example.com/caps-enhancer/update.xml" +``` + +> Требует прав администратора (HKLM). +> Для установки без прав — использовать HKCU (только для текущего пользователя). + +### Способ B: PowerShell скрипт + +Отредактируй `server/install-client.ps1` (замени ID и домен), запусти от имени администратора: + +```powershell +# Запуск от имени администратора: +Start-Process powershell -Verb RunAs -ArgumentList "-File C:\path\to\install-client.ps1" +``` + +### Способ C: Групповые политики (GPO) — для домена + +1. Открой **Group Policy Management Console** (gpmc.msc) +2. Создай или отредактируй GPO +3. Перейди: `Computer Configuration` → `Administrative Templates` → `Google` → `Google Chrome` → `Extensions` +4. Включи политику **"Configure the list of force-installed apps and extensions"** +5. Добавь строку: `abcdefghijklmnopqrstuvwxyzabcdef;https://updates.example.com/caps-enhancer/update.xml` + +> Если шаблонов Google нет — скачай ADMX: https://chromeenterprise.google/intl/ru/browser/download/ + +### Что видит пользователь после установки + +- Chrome автоматически устанавливает расширение при следующем запуске +- Иконка появляется в панели расширений +- Пользователь **не может удалить** принудительно установленное расширение (managed) + +--- + +## Часть 4: Выпуск обновления + +При каждом обновлении расширения: + +### 1. Обнови версию в manifest.json + +```json +"version": "2.8" +``` + +### 2. Упакуй расширение с тем же ключом + +Запусти `pack-crx.bat` — скрипт автоматически использует существующий `caps-enhancer.pem`. + +### 3. Обнови update.xml + +```xml + +``` + +### 4. Загрузи на сервер + +```bash +scp caps-enhancer.crx update.xml user@your-server:/var/www/caps-enhancer/caps-enhancer/ +``` + +### 5. Готово + +Chrome проверяет обновления примерно каждые **5 часов** в фоне. +Обновление применяется при следующем перезапуске браузера (или при перезагрузке расширения). + +Форсировать проверку обновлений вручную можно в `chrome://extensions` → "Обновить расширения". + +--- + +## Итоговая структура файлов + +``` +caps-enhancer/ +├── manifest.json ← update_url прописан +├── pack-crx.bat ← запускать для упаковки +├── caps-enhancer.pem ← ХРАНИТЬ В БЕЗОПАСНОМ МЕСТЕ (создаётся при первой упаковке) +├── DEPLOY.md ← эта инструкция +├── ...остальные файлы расширения... +└── server/ + ├── update.xml ← загружать на сервер при каждом обновлении + ├── caps-enhancer.crx ← загружать на сервер при каждом обновлении + ├── nginx.conf ← конфиг для nginx (один раз) + ├── deploy.sh ← скрипт деплоя на сервере + ├── install-client.reg ← раздать пользователям для установки + └── install-client.ps1 ← альтернатива .reg файлу +``` + +--- + +## Troubleshooting + +| Проблема | Причина | Решение | +|----------|---------|---------| +| Chrome не устанавливает расширение | Нет ключа реестра | Проверь `HKLM\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist` | +| "Extension not from Chrome Web Store" | Расширение установлено не через policy | Используй реестр, не ручную установку | +| Обновление не прилетает | update.xml закэширован или неверный ID | Очисти кэш, проверь EXTENSION_ID в update.xml | +| Chrome отказывается качать .crx | HTTP вместо HTTPS | Настрой SSL на сервере | +| .crx не скачивается | Неверный MIME-тип | Добавь `application/x-chrome-extension` для `.crx` | +| ID расширения изменился | Потерян .pem файл | Перераспространить .reg с новым ID | diff --git a/auto-update.bat b/auto-update.bat new file mode 100644 index 0000000..c09cfaf --- /dev/null +++ b/auto-update.bat @@ -0,0 +1,41 @@ +@echo off +setlocal + +set VERSION_URL=https://git.ihateamerica.ru/caps_enhancer/version.json +set ZIP_URL=https://git.ihateamerica.ru/caps_enhancer/caps-enhancer.zip +set EXT_DIR=%~dp0 + +:: Читаем локальную версию из manifest.json +for /f "delims=" %%v in ('powershell -NoProfile -Command "(Get-Content '%EXT_DIR%manifest.json' | ConvertFrom-Json).version"') do set LOCAL_VER=%%v + +:: Читаем удалённую версию +for /f "delims=" %%v in ('curl -sf "%VERSION_URL%"') do set REMOTE_JSON=%%v +for /f "delims=" %%v in ('powershell -NoProfile -Command "'%REMOTE_JSON%' | ConvertFrom-Json | Select-Object -ExpandProperty version"') do set REMOTE_VER=%%v + +if not defined REMOTE_VER ( + echo [ОШИБКА] Не удалось получить версию с сервера. + goto :end +) + +if "%LOCAL_VER%"=="%REMOTE_VER%" ( + echo [OK] Версия актуальная: %LOCAL_VER% + goto :end +) + +echo [INFO] Обновление: %LOCAL_VER% --^> %REMOTE_VER% + +set TMP_ZIP=%TEMP%\caps-enhancer-update.zip +curl -f "%ZIP_URL%" -o "%TMP_ZIP%" +if errorlevel 1 ( + echo [ОШИБКА] Не удалось скачать ZIP. + goto :end +) + +tar -xf "%TMP_ZIP%" -C "%EXT_DIR%" --overwrite +del "%TMP_ZIP%" + +echo [OK] Обновлено до версии %REMOTE_VER%. Перезагрузи расширение в Chrome. + +:end +endlocal +pause diff --git a/js/background.js b/js/background.js new file mode 100644 index 0000000..0430802 --- /dev/null +++ b/js/background.js @@ -0,0 +1,47 @@ +// Фоновый service worker — проверка обновлений расширения +// Работает только в режиме "Load unpacked" (Developer Mode) + +const VERSION_URL = 'https://git.ihateamerica.ru/caps_enhancer/version.json'; +const CHECK_INTERVAL_MINUTES = 60; + +chrome.runtime.onInstalled.addListener(() => { + chrome.alarms.create('updateCheck', { + delayInMinutes: 1, + periodInMinutes: CHECK_INTERVAL_MINUTES + }); +}); + +chrome.alarms.onAlarm.addListener((alarm) => { + if (alarm.name === 'updateCheck') { + checkForUpdates(); + } +}); + +async function checkForUpdates() { + try { + const res = await fetch(VERSION_URL + '?t=' + Date.now()); + if (!res.ok) return; + + const { version: remote } = await res.json(); + const local = chrome.runtime.getManifest().version; + + if (isNewer(remote, local)) { + console.log(`[CAPS Enhancer] Обновление: ${local} → ${remote}. Перезагружаю...`); + // Небольшая задержка — дать scheduled task время распаковать файлы + await new Promise(r => setTimeout(r, 3000)); + chrome.runtime.reload(); + } + } catch { + // Нет соединения или сервер недоступен — молча игнорируем + } +} + +function isNewer(remote, local) { + const r = remote.split('.').map(Number); + const l = local.split('.').map(Number); + for (let i = 0; i < Math.max(r.length, l.length); i++) { + if ((r[i] || 0) > (l[i] || 0)) return true; + if ((r[i] || 0) < (l[i] || 0)) return false; + } + return false; +} diff --git a/manifest.json b/manifest.json index bd160c9..5676255 100644 --- a/manifest.json +++ b/manifest.json @@ -3,12 +3,16 @@ "name": "CAPS Enhancer", "version": "2.7", "description": "Добавляет всякие фичи для УТП в CAPS", + "update_url": "https://git.ihateamerica.ru/caps_enhancer/update.xml", "icons": { "16": "icons/icon16.png", "48": "icons/icon48.png", "128": "icons/icon128.png" }, - "permissions": ["activeTab", "storage", "tabs"], + "background": { + "service_worker": "js/background.js" + }, + "permissions": ["activeTab", "storage", "tabs", "alarms"], "host_permissions": [""], "action": { "default_popup": "popup.html", diff --git a/pack-crx.bat b/pack-crx.bat new file mode 100644 index 0000000..1adb949 --- /dev/null +++ b/pack-crx.bat @@ -0,0 +1,46 @@ +@echo off +:: Скрипт упаковки расширения в .crx +:: Запускать из папки caps-enhancer +:: Требует: Google Chrome установлен + +setlocal + +:: Путь к Chrome (проверяем оба варианта) +set CHROME="C:\Program Files\Google\Chrome\Application\chrome.exe" +if not exist %CHROME% set CHROME="C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" + +:: Текущая директория (где лежит manifest.json) +set EXT_DIR=%~dp0 + +:: Файл ключа (генерируется при первой упаковке, сохранять!) +set KEY_FILE=%~dp0caps-enhancer.pem + +echo === CAPS Enhancer - Упаковка расширения === +echo. + +if exist %KEY_FILE% ( + echo [INFO] Используется существующий ключ: %KEY_FILE% + %CHROME% --pack-extension="%EXT_DIR%" --pack-extension-key="%KEY_FILE%" --no-message-box +) else ( + echo [INFO] Ключ не найден. Будет создан новый ключ. + echo [WARN] ПЕРВЫЙ РАЗ: сохраните caps-enhancer.pem - он нужен для всех обновлений! + %CHROME% --pack-extension="%EXT_DIR%" --no-message-box +) + +echo. +if exist "%~dp0..\caps-enhancer.crx" ( + copy "%~dp0..\caps-enhancer.crx" "%~dp0server\caps-enhancer.crx" >nul + echo [OK] caps-enhancer.crx скопирован в server\ +) else ( + echo [WARN] .crx не найден. Chrome мог создать его на уровень выше. + echo Проверьте папку рядом с caps-enhancer\ +) + +echo. +echo === Готово! === +echo Следующие шаги: +echo 1. Проверь ID расширения в chrome://extensions +echo 2. Обнови server\update.xml (EXTENSION_ID и version) +echo 3. Загрузи server\caps-enhancer.crx и server\update.xml на сервер +echo. +pause diff --git a/server/caps-enhancer.zip b/server/caps-enhancer.zip new file mode 100644 index 0000000000000000000000000000000000000000..74b91e976746290c75f87d136071d78814af4c29 GIT binary patch literal 55599 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ℜtnniuc7&agt7 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 literal 0 HcmV?d00001 diff --git a/server/deploy.sh b/server/deploy.sh new file mode 100644 index 0000000..0c31156 --- /dev/null +++ b/server/deploy.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Скрипт деплоя на сервер. +# Запускать на сервере после загрузки новых файлов. +# Использование: ./deploy.sh + +set -e + +DEPLOY_DIR="/var/www/caps-enhancer/caps-enhancer" +CRX_FILE="caps-enhancer.crx" +UPDATE_XML="update.xml" + +echo "=== CAPS Enhancer Deploy ===" + +# Создаём директорию если не существует +mkdir -p "$DEPLOY_DIR" + +# Копируем файлы (запускать из папки где лежат .crx и update.xml) +if [ -f "$CRX_FILE" ]; then + cp "$CRX_FILE" "$DEPLOY_DIR/" + echo "[OK] $CRX_FILE скопирован" +else + echo "[WARN] $CRX_FILE не найден в текущей директории" +fi + +if [ -f "$UPDATE_XML" ]; then + cp "$UPDATE_XML" "$DEPLOY_DIR/" + echo "[OK] $UPDATE_XML скопирован" +else + echo "[WARN] $UPDATE_XML не найден в текущей директории" +fi + +# Права доступа +chown -R www-data:www-data "$DEPLOY_DIR" +chmod -R 755 "$DEPLOY_DIR" +echo "[OK] Права выставлены" + +echo "=== Деплой завершён ===" +echo "Проверь: https://YOUR_DOMAIN/caps-enhancer/update.xml" diff --git a/server/install-client.ps1 b/server/install-client.ps1 new file mode 100644 index 0000000..3708ccc --- /dev/null +++ b/server/install-client.ps1 @@ -0,0 +1,38 @@ +# Скрипт установки расширения через PowerShell (альтернатива .reg файлу) +# Запускать с правами администратора: +# Right Click -> "Запустить от имени администратора" +# или: Start-Process powershell -Verb RunAs -ArgumentList "-File install-client.ps1" + +param( + [string]$ExtensionId = "EXTENSION_ID", + [string]$UpdateUrl = "https://YOUR_DOMAIN/caps-enhancer/update.xml" +) + +$registryPath = "HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist" +$value = "$ExtensionId;$UpdateUrl" + +# Создаём ключ если не существует +if (-not (Test-Path $registryPath)) { + New-Item -Path $registryPath -Force | Out-Null + Write-Host "[OK] Создан ключ реестра: $registryPath" +} + +# Ищем свободный номер (1, 2, 3, ...) +$index = 1 +while (Get-ItemProperty -Path $registryPath -Name "$index" -ErrorAction SilentlyContinue) { + # Проверяем, вдруг расширение уже добавлено + $existing = (Get-ItemProperty -Path $registryPath -Name "$index")."$index" + if ($existing -like "$ExtensionId;*") { + Write-Host "[INFO] Расширение уже установлено (запись $index)." + Write-Host " Значение: $existing" + exit 0 + } + $index++ +} + +Set-ItemProperty -Path $registryPath -Name "$index" -Value $value -Type String +Write-Host "[OK] Расширение добавлено в реестр (запись $index):" +Write-Host " $value" +Write-Host "" +Write-Host "Chrome автоматически установит расширение при следующем запуске." +Write-Host "Если Chrome уже открыт — перезапустите его." diff --git a/server/install-client.reg b/server/install-client.reg new file mode 100644 index 0000000..b2ce863 --- /dev/null +++ b/server/install-client.reg @@ -0,0 +1,13 @@ +Windows Registry Editor Version 5.00 + +; ============================================================ +; Принудительная установка CAPS Enhancer через Windows Registry +; ============================================================ + +; Для всех пользователей компьютера (требует прав администратора) +[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist] +"1"="hpjnlbenmhmigajedbgmonmnediljbfa;https://git.ihateamerica.ru/caps_enhancer/update.xml" + +; --- ИЛИ только для текущего пользователя (без прав админа) --- +; [HKEY_CURRENT_USER\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist] +; "1"="hpjnlbenmhmigajedbgmonmnediljbfa;https://git.ihateamerica.ru/caps_enhancer/update.xml" diff --git a/server/nginx.conf b/server/nginx.conf new file mode 100644 index 0000000..9e43c81 --- /dev/null +++ b/server/nginx.conf @@ -0,0 +1,40 @@ +server { + listen 80; + listen 443 ssl; + server_name YOUR_DOMAIN; + + # SSL (рекомендуется — Chrome требует HTTPS для update_url) + # ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem; + # ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem; + + root /var/www/caps-enhancer; + index index.html; + + # Директория с файлами расширения + location /caps-enhancer/ { + # MIME-тип для .crx — обязателен, иначе Chrome откажется качать + types { + application/x-chrome-extension crx; + application/xml xml; + text/plain txt; + } + + # Разрешаем скачивание + add_header Content-Disposition 'attachment' always; + + # CORS — если сервер и расширение на разных доменах + add_header Access-Control-Allow-Origin '*' always; + + # Кэш для update.xml — не кэшировать (чтобы обновления прилетали быстро) + location ~* \.xml$ { + add_header Cache-Control 'no-cache, no-store, must-revalidate' always; + add_header Pragma 'no-cache' always; + expires 0; + } + + # .crx можно кэшировать (файл меняется только при новой версии) + location ~* \.crx$ { + add_header Cache-Control 'public, max-age=86400' always; + } + } +} diff --git a/server/pack-zip.bat b/server/pack-zip.bat new file mode 100644 index 0000000..6d258af --- /dev/null +++ b/server/pack-zip.bat @@ -0,0 +1,40 @@ +@echo off +setlocal +set ROOT=%~dp0.. + +:: Читаем версию из manifest.json +for /f "delims=" %%v in ('powershell -NoProfile -Command "(Get-Content '%ROOT%\manifest.json' | ConvertFrom-Json).version"') do set VERSION=%%v +echo Упаковка версии %VERSION%... + +:: Временная папка +set TMP=%TEMP%\caps-enhancer-pack +if exist "%TMP%" rd /s /q "%TMP%" +md "%TMP%" + +:: Копируем файлы расширения +copy "%ROOT%\manifest.json" "%TMP%\" >nul +copy "%ROOT%\popup.html" "%TMP%\" >nul +copy "%ROOT%\popup.css" "%TMP%\" >nul +copy "%ROOT%\options.html" "%TMP%\" >nul +copy "%ROOT%\auto-update.bat" "%TMP%\" >nul +xcopy "%ROOT%\js" "%TMP%\js\" /e /q >nul +xcopy "%ROOT%\css" "%TMP%\css\" /e /q >nul +xcopy "%ROOT%\modules" "%TMP%\modules\" /e /q >nul +xcopy "%ROOT%\icons" "%TMP%\icons\" /e /q >nul + +:: Создаём ZIP +set OUT=%~dp0caps-enhancer.zip +if exist "%OUT%" del "%OUT%" +powershell -NoProfile -Command "Compress-Archive -Path '%TMP%\*' -DestinationPath '%OUT%'" +rd /s /q "%TMP%" + +:: Обновляем version.json +echo {"version": "%VERSION%"} > "%~dp0version.json" + +echo. +echo [OK] server\caps-enhancer.zip +echo [OK] server\version.json (v%VERSION%) +echo. +echo Залей оба файла на сервер: /var/www/caps_enhancer/ +pause +endlocal diff --git a/server/update.xml b/server/update.xml new file mode 100644 index 0000000..56d3807 --- /dev/null +++ b/server/update.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/server/version.json b/server/version.json new file mode 100644 index 0000000..fb01bc4 --- /dev/null +++ b/server/version.json @@ -0,0 +1 @@ +{"version": "2.7"}