### Install subs-check on Linux
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Use these commands to install the application on Linux systems, including options for wget and proxy usage.
```bash
# 默认安装
bash <(curl -fsSL https://raw.githubusercontent.com/beck-8/subs-check/master/install.sh)
# 使用 wget
bash <(wget -qO- https://raw.githubusercontent.com/beck-8/subs-check/master/install.sh)
# 如果无法访问 GitHub,可使用代理
bash <(curl -fsSL https://ghfast.top/https://raw.githubusercontent.com/beck-8/subs-check/master/install.sh) https://ghfast.top/
# Alpine 等无 bash 环境
wget -qO /tmp/install.sh https://raw.githubusercontent.com/beck-8/subs-check/master/install.sh && sh /tmp/install.sh && rm -f /tmp/install.sh
```
--------------------------------
### Install dependencies in Termux
Source: https://github.com/beck-8/subs-check/blob/master/doc/android.md
Installs Node.js and necessary system utilities required for the application.
```bash
pkg update && pkg add nodejs ca-certificates which proot termux-exec -y
```
--------------------------------
### Status Polling and Initialization
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Handles periodic status updates from the API and initial application setup.
```javascript
function updateStatus() { fetch('/api/status', { headers: addApiKeyHeader() }) .then(response => { if (handleUnauthorized(response, false)) return; return response.json(); }) .then(data => { if (data) { if (data.checking) { dom.statusContainer.className = 'text-primary'; dom.statusIcon.className = 'bi bi-arrow-repeat me-1 rotate-animation'; dom.statusText.textContent = '正在检测中...'; if (data.pipeline) { updatePipelineBar(data.pipeline, !!data.hasSpeedTest); updatePipelineSteps(data.pipeline, !!data.hasSpeedTest); } else { // legacy fallback (older server) updateProgressBar(data.proxyCount, data.progress, data.available, data.phase, data.phaseResults); } } else { dom.statusContainer.className = 'text-success'; dom.statusIcon.className = 'bi bi-check-circle me-1'; dom.statusText.textContent = '空闲'; updatePhaseSteps(0, 0, 0, data.phaseResults); resetProgress(); } } }) .catch(error => { console.error('获取状态失败:', error); dom.statusContainer.className = 'text-danger'; dom.statusIcon.className = 'bi bi-exclamation-triangle me-1'; dom.statusText.textContent = '获取状态失败'; resetProgress(); }); } // 初始加载 updateStatus(); loadLogs(); // 检查API密钥 const apiKey = localStorage.getItem('apiKey'); if (!apiKey) { alert('请先输入API密钥以使用本系统'); dom.apiKey.focus(); } // 定时刷新 setInterval(loadLogs, 10000); setInterval(updateStatus, 3000);
```
--------------------------------
### Initialize Linux environment and DNS
Source: https://github.com/beck-8/subs-check/blob/master/doc/android.md
Enters the proot environment and configures DNS settings if resolution issues occur.
```bash
# 目的是为了让subs-check有个完整的Linux环境
termux-chroot
# 如遇到DNS问题,请自行更改/etc/resolv.conf
echo "nameserver 223.5.5.5" > /etc/resolv.conf
```
--------------------------------
### Run from Source
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Execute the application directly from source code using the Go toolchain.
```bash
go run . -f ./config/config.yaml
```
--------------------------------
### Run with Docker
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Commands to deploy the application using Docker, with or without proxy settings.
```bash
# 基础运行
docker run -d \
--name subs-check \
-p 8299:8299 \
-p 8199:8199 \
-v ./config:/app/config \
-v ./output:/app/output \
--restart always \
ghcr.io/beck-8/subs-check:latest
# 使用代理运行
docker run -d \
--name subs-check \
-p 8299:8299 \
-p 8199:8199 \
-e HTTP_PROXY=http://192.168.1.1:7890 \
-e HTTPS_PROXY=http://192.168.1.1:7890 \
-v ./config:/app/config \
-v ./output:/app/output \
--restart always \
ghcr.io/beck-8/subs-check:latest
```
--------------------------------
### Execute the program
Source: https://github.com/beck-8/subs-check/blob/master/doc/android.md
Runs the subs-check binary.
```bash
./subs-check
```
--------------------------------
### Configure environment variables
Source: https://github.com/beck-8/subs-check/blob/master/doc/android.md
Sets SSL certificate paths and Node.js binary locations, either temporarily or persistently.
```bash
# 临时设置环境变量
# 无Root权限的手机设置,有Root权限应该授权后无需设置
export SSL_CERT_FILE="/data/data/com.termux/files/usr/etc/tls/cert.pem"
export NODEBIN_PATH="$(which node)"
```
```bash
# 设置持久环境变量,重新打开终端无需再次设置
echo 'export SSL_CERT_FILE="/data/data/com.termux/files/usr/etc/tls/cert.pem"' >> ~/.bashrc
echo 'export NODEBIN_PATH="$(which node)"' >> ~/.bashrc
source ~/.bashrc
```
--------------------------------
### Admin Interface Initialization Script
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
JavaScript logic for initializing the Monaco editor, managing API keys via localStorage, and handling UI interactions.
```javascript
var require = { paths: { 'vs': '/static/monaco/vs' } }; let editor; const PHASE_LABELS = { 1: { name: '测活', countLabel: '存活' }, 2: { name: '流媒体+重命名', countLabel: '完成' }, 3: { name: '测速', countLabel: '通过' } }; // 缓存高频访问的 DOM 元素 const dom = { apiKey: document.getElementById('apiKey'), toggleApiKey: document.getElementById('toggleApiKey'), saveApiKey: document.getElementById('saveApiKey'), logs: document.getElementById('logs'), phaseSteps: document.getElementById('phaseSteps'), progressText: document.getElementById('progressText'), progressPercent: document.getElementById('progressPercent'), processPercent: document.getElementById('processPercent'), progressBarTotal: document.getElementById('progressBarTotal'), progressBarSuccess: document.getElementById('progressBarSuccess'), successLabel: document.getElementById('successLabel'), successText: document.getElementById('successText'), statusContainer: document.getElementById('statusContainer'), statusIcon: document.getElementById('statusIcon'), statusText: document.getElementById('nextCheckTime'), versionInfo: document.getElementById('versionInfo'), }; // 初始化API密钥 const storedApiKey = localStorage.getItem('apiKey') || ''; dom.apiKey.value = storedApiKey; // 切换API密钥可见性 dom.toggleApiKey.addEventListener('click', function() { const icon = this.querySelector('i'); if (dom.apiKey.type === 'password') { dom.apiKey.type = 'text'; icon.className = 'bi bi-eye'; } else { dom.apiKey.type = 'password'; icon.className = 'bi bi-eye-slash'; } }); // 保存API密钥到本地存储 dom.saveApiKey.addEventListener('click', function() { const apiKey = dom.apiKey.value.trim(); localStorage.setItem('apiKey', apiKey); const button = this; const originalText = button.textContent; button.disabled = true; button.textContent = '验证中...'; fetch('/api/status', { headers: { 'X-API-Key': apiKey } }) .then(response => { if (response.status === 401) { alert('API密钥无效,请检查后重试'); return
```
--------------------------------
### Configure Proxy Settings
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Environment variables to route traffic through HTTP, SOCKS5, or SOCKS5H proxies.
```bash
# HTTP 代理示例
export HTTP_PROXY=http://username:password@192.168.1.1:7890
export HTTPS_PROXY=http://username:password@192.168.1.1:7890
# SOCKS5 代理示例
export HTTP_PROXY=socks5://username:password@192.168.1.1:7890
export HTTPS_PROXY=socks5://username:password@192.168.1.1:7890
# SOCKS5H 代理示例
export HTTP_PROXY=socks5h://username:password@192.168.1.1:7890
export HTTPS_PROXY=socks5h://username:password@192.168.1.1:7890
```
--------------------------------
### Deploy Apprise using Docker
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Commands to run the Apprise notification server in a Docker container, with options for basic deployment or using an HTTP proxy.
```bash
# 基础运行
docker run --name apprise -p 8000:8000 --restart always -d caronc/apprise:latest
# 使用代理运行
docker run --name apprise \
-p 8000:8000 \
-e HTTP_PROXY=http://192.168.1.1:7890 \
-e HTTPS_PROXY=http://192.168.1.1:7890 \
--restart always \
-d caronc/apprise:latest
```
--------------------------------
### Monaco Editor Initialization
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Configures the Monaco editor with YAML syntax highlighting and custom UI overlay toggling.
```javascript
// 初始化编辑器 require(['vs/editor/editor.main'], function() { monaco.languages.register({ id: 'yaml' }); monaco.languages.setMonarchTokensProvider('yaml', { tokenizer: { root: [ [/^\s*#.*$/, 'comment'], [/^\s*[\w\-]+:/, 'keyword'], [/^\s*-/, 'keyword'], [/"*?"/, 'string'], [/'*?'/, 'string'], ] } }); editor = monaco.editor.create(document.getElementById('editor'), { language: 'yaml', theme: 'vs', automaticLayout: true, minimap: { enabled: false }, fontSize: 13, lineHeight: 20, padding: { top: 10 }, scrollBeyondLastLine: false, renderLineHighlight: 'gutter', }); loadConfig(); const toggleConfigBtn = document.getElementById('toggleConfig'); const editorOverlay = document.getElementById('editorOverlay'); editorOverlay.style.display = 'flex'; toggleConfigBtn.addEventListener('click', function() { const isHidden = editorOverlay.style.display === 'flex'; editorOverlay.style.display = isHidden ? 'none' : 'flex'; const icon = toggleConfigBtn.querySelector('i'); icon.className = isHidden ? 'bi bi-eye' : 'bi bi-eye-slash'; }); editorOverlay.addEventListener('click', function() { editorOverlay.style.display = 'none'; const icon = toggleConfigBtn.querySelector('i'); icon.className = 'bi bi-eye'; }); });
```
--------------------------------
### Retrieve Version Information
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Fetches and displays the current system version from the API.
```javascript
function getVersionInfo() { fetch('/api/version', { headers: addApiKeyHeader() }) .then(response => response.json()) .then(data => { if (data && data.version) { dom.versionInfo.textContent = '版本: ' + data.version; } }) .catch(error => { console.error('获取版本信息失败:', error); dom.versionInfo.textContent = '版本: 未知'; }); } getVersionInfo();
```
--------------------------------
### 配置自定义访问路径
Source: https://github.com/beck-8/subs-check/blob/master/doc/sub-store.md
通过修改配置文件中的 sub-store-path 来设置自定义访问路径,增强安全性。
```bash
# sub-store自定义访问路径,必须以/开头,后续访问订阅也要带上此路径
# 设置path之后,还可以开启订阅分享功能,无需暴露真实的path
# sub-store-path: "/path"
sub-store-path: "/diypath"
```
--------------------------------
### Deploy with Docker Compose
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Configuration file for deploying the application using Docker Compose.
```yaml
version: "3"
services:
subs-check:
image: ghcr.io/beck-8/subs-check:latest
container_name: subs-check
volumes:
- ./config:/app/config
- ./output:/app/output
ports:
- "8299:8299"
- "8199:8199"
environment:
- TZ=Asia/Shanghai
# - HTTP_PROXY=http://192.168.1.1:7890
# - HTTPS_PROXY=http://192.168.1.1:7890
# - API_KEY=subs-check
restart: always
network_mode: bridge
```
--------------------------------
### Access Mihomo/Clash Subscription with Rules
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Endpoint for retrieving Mihomo/Clash subscription files with default rule overrides applied.
```bash
http://127.0.0.1:8299/api/file/mihomo
```
--------------------------------
### Uninstall subs-check
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Commands to stop, disable, and remove the application files and service configuration.
```bash
systemctl stop subs-check
systemctl disable subs-check
rm -rf /opt/subs-check /etc/systemd/system/subs-check.service
systemctl daemon-reload
```
--------------------------------
### Access Subscription Links
Source: https://github.com/beck-8/subs-check/blob/master/README.md
List of URL endpoints for downloading subscription files in various formats supported by proxy clients.
```bash
# 通用订阅
http://127.0.0.1:8299/download/sub
# URI 订阅
http://127.0.0.1:8299/download/sub?target=URI
# Mihomo/ClashMeta
http://127.0.0.1:8299/download/sub?target=ClashMeta
# Clash
http://127.0.0.1:8299/download/sub?target=Clash
# V2Ray
http://127.0.0.1:8299/download/sub?target=V2Ray
# ShadowRocket
http://127.0.0.1:8299/download/sub?target=ShadowRocket
# Quantumult
http://127.0.0.1:8299/download/sub?target=QX
# Sing-Box
http://127.0.0.1:8299/download/sub?target=sing-box
# Surge
http://127.0.0.1:8299/download/sub?target=Surge
# Surfboard
http://127.0.0.1:8299/download/sub?target=Surfboard
```
--------------------------------
### System Architecture Diagram
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Visual representation of the data flow from subscription links through processing, storage, and final distribution.
```mermaid
graph TD
A[订阅链接] -->|获取订阅链接| B[subs-check]
subgraph subs-check 处理流程
B -->|转成 YAML 格式| B1[节点去重]
B1 -->|去除冗余节点| B2[测活]
B2 -->|节点可用| B3[流媒体+重命名]
B2 -->|节点不可用| X[丢弃]
B3 -->|filter 通过| B4[测速]
B3 -->|filter 不通过| X[丢弃]
B4 -->|测速达标| B5[生成 all.yaml]
B4 -->|测速不达标| X[丢弃]
end
B5 -->|保存到 output 目录| C[output 目录]
B5 -->|上传 all.yaml| D[sub-store]
C -->|保存到各位置| H1[R2/Gist/WebDAV/S3]
H1 -->|存储完成| H2[发送消息通知]
D -->|提供订阅转换服务| E[sub-store 转换服务]
subgraph sub-store 独立功能
E -->|生成配置文件| E1[mihomo.yaml, base64.txt]
E -->|其他格式转换| E2[Clash, V2Ray, ShadowRocket 等]
E -->|订阅分享| E3[分享订阅链接]
end
E1 -->|保存到 output 目录| C
C -->|文件服务| F[8199 端口: /sub]
B -->|Web 管理| G[8199 端口: /admin]
```
--------------------------------
### Fix Configuration File Permissions
Source: https://github.com/beck-8/subs-check/blob/master/_autodocs/errors.md
Use this command to resolve file permission issues when the application fails to load the configuration file.
```bash
chmod 644 config/config.yaml
```
--------------------------------
### Responsive Media Queries
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Adjusts layout behavior for desktop, tablet, and mobile screen widths.
```css
@media (min-width: 992px) { .main-row .card { height: calc(100vh - 300px); min-height: 400px; } } @media (min-width: 1600px) { .main-row .card { height: calc(100vh - 350px); } } @media (max-width: 991px) { body { padding: 12px; } .main-row { display: block; } .main-row .card { height: auto; } .editor-wrapper { flex: none; height: calc(100vh - 285px); } .logs-container { flex: none; height: calc(100vh - 390px); } .card-header { padding: 0.5rem 0.75rem; } .card-body { padding: 0.75rem; } .card { margin-bottom: 15px; } } @media (max-width: 768px) { body { padding: 8px; } .editor-wrapper { flex: none; height: 420px; } .logs-container { flex: none; height: 350px; } .status-item { margin-bottom: 8px; } .config-path { max-width: 100%; white-space: normal; word-break: break-all; font-size: 0.85em; } .card { margin-bottom: 12px; } .progress-section { padding: 10px; } .phase-steps { flex-wrap: wrap; gap: 6px; } }
```
--------------------------------
### Configuration and Status API Handlers
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Functions to load, save, and trigger system actions via API endpoints with authorization checks.
```javascript
// 处理未授权响应 function handleUnauthorized(response, showAlert = true) { if (response.status === 401) { if (showAlert) { alert('API密钥无效或未提供,请检查您的API密钥'); } return true; } return false; } // 加载配置 function loadConfig() { return fetch('/api/config', { headers: addApiKeyHeader() }) .then(response => { if (handleUnauthorized(response, false)) return; if (!response.ok) throw new Error('加载配置失败'); return response.json(); }) .then(data => { if (editor && data) editor.setValue(data.content); return data; }) .catch(error => { console.error('加载配置失败:', error); }); } // 保存配置 document.getElementById('saveConfig').addEventListener('click', function() { const content = editor.getValue(); fetch('/api/config', { method: 'POST', headers: addApiKeyHeader({ 'Content-Type': 'application/json' }), body: JSON.stringify({ content }) }) .then(response => { if (handleUnauthorized(response, true)) throw new Error('未授权'); return response.json(); }) .then(data => { if (data.error) { alert('保存失败: ' + data.error); } else { alert(data.message); updateStatus(); } }) .catch(error => { if (error.message !== '未授权') alert('保存失败: ' + error.message); }); }); // 重新加载配置 document.getElementById('reloadConfig').addEventListener('click', function() { const button = this; const icon = button.querySelector('i'); icon.classList.add('rotate-animation'); button.disabled = true; loadConfig().finally(() => { setTimeout(() => { icon.classList.remove('rotate-animation'); button.disabled = false; }, 500); }); }); // 强制关闭 document.getElementById('forceClose').addEventListener('click', function() { if (!confirm('确定要强制停止当前阶段吗?已有结果将被保留。')) return; const button = this; const icon = button.querySelector('i'); const originalIcon = icon.className; icon.className = 'bi bi-arrow-repeat me-1 rotate-animation'; button.disabled = true; fetch('/api/force-close', { method: 'POST', headers: addApiKeyHeader() }) .then(response => { if (handleUnauthorized(response, true)) throw new Error('未授权'); return response.json(); }) .catch(error => { if (error.message !== '未授权') { console.error('强制停止失败:', error); alert('强制停止失败: ' + error.message); } }) .finally(() => { setTimeout(() => { icon.className = originalIcon; button.disabled = false; }, 500); }); }); // 立即检测 document.getElementById('triggerCheck').addEventListener('click', function() { const button = this; const icon = button.querySelector('i'); const originalIcon = icon.className; icon.className = 'bi bi-arrow-repeat me-1 rotate-animation'; button.disabled = true; fetch('/api/trigger-check', { method: 'POST', headers: addApiKeyHeader() }) .then(response => { if (handleUnauthorized(response, true)) throw new Error('未授权'); return response.json(); }) .then(data => { loadLogs(); }) .catch(error => { if (error.message !== '未授权') console.error('触发检测失败:', error); }) .finally(() => { setTimeout(() => { icon.className = originalIcon; button.disabled = false; }, 500); }); }); // 加载日志 function loadLogs() { return fetch('/api/logs', { headers: addApiKeyHeader() }) .then(response => { if (handleUnauthorized(response, false)) throw new Error('未授权'); return response.json(); }) .then(data => { if (data.error) { dom.logs.textContent = '加载日志失败: ' + data.error; } else { const isScrolledToBottom =
```
--------------------------------
### Increase Inotify Watch Limit
Source: https://github.com/beck-8/subs-check/blob/master/_autodocs/errors.md
Run this command on Linux systems to resolve configuration watcher initialization failures caused by exceeding the inotify limit.
```bash
sysctl fs.inotify.max_user_watches=524288
```
--------------------------------
### 配置 GitHub API 镜像地址
Source: https://github.com/beck-8/subs-check/blob/master/doc/gist.md
在配置文件中设置 GitHub API 的反代地址。
```yaml
github-api-mirror: "https://your-worker-url/github"
```
--------------------------------
### Configure Notification Settings
Source: https://github.com/beck-8/subs-check/blob/master/README.md
YAML configuration snippet for setting the Apprise API server address, recipient URLs, and custom notification titles.
```yaml
# 填写搭建的apprise API server 地址
# https://notify.xxxx.us.kg/notify
apprise-api-server: "https://diydomain.com/notify"
# 填写通知目标
# 支持100+ 个通知渠道,详细格式请参照 https://github.com/caronc/apprise
recipient-url:
# telegram格式:tgram://{bot_token}/{chat_id}
# - tgram://xxxxxx/-1002149239223
# 钉钉格式:dingtalk://{Secret}@{ApiKey}
# - dingtalk://xxxxxx@xxxxxxx
# 自定义通知标题
notify-title: "🔔 节点状态更新"
```
--------------------------------
### 获取不同格式的订阅链接
Source: https://github.com/beck-8/subs-check/blob/master/doc/gist.md
根据存储在 Gist 中的文件类型获取对应的订阅地址。
```text
https://gist.githubusercontent.com/YOUR_GITHUB_USERNAME/YOUR_GIST_ID/raw/all.yaml
```
```text
https://gist.githubusercontent.com/YOUR_GITHUB_USERNAME/YOUR_GIST_ID/raw/base64.txt
```
```text
https://gist.githubusercontent.com/YOUR_GITHUB_USERNAME/YOUR_GIST_ID/raw/mihomo.yaml
```
--------------------------------
### Component and Utility Styles
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Styles for cards, buttons, alerts, and log-specific color coding.
```css
.card { margin-bottom: 16px; border: 1px solid var(--border-color); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; } .card-header { background-color: var(--bg-card); border-bottom: 1px solid var(--border-color); font-weight: 600; font-size: 0.9rem; } .log-info { color: #a6e3a1; } .log-error { color: #f38ba8; } .log-warn { color: #f9e2af; } .log-debug { color: #89b4fa; } .log-time { color: #7f849c; } .status-bar { background-color: var(--bg-card); padding: 12px 16px; margin-bottom: 16px; border-radius: var(--radius); border: 1px solid var(--border-color); box-shadow: var(--shadow-sm); } .config-path { white-space: normal; word-break: break-all; color: var(--text-secondary); font-size: 0.85em; } .api-key-form { margin-bottom: 16px; } .btn { padding: 6px 14px; font-size: 0.85rem; border-radius: 8px; font-weight: 500; transition: all 0.2s ease; } .btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); } .btn:active { transform: translateY(0); } .btn-sm { padding: 4px 10px; font-size: 0.78rem; } .btn-primary { background-color: var(--accent-blue); border-color: var(--accent-blue); } .btn-danger { background-color: var(--accent-red); border-color: var(--accent-red); } .btn-success { background-color: var(--accent-green); border-color: var(--accent-green); } .alert { padding: 0.75rem 1rem; margin-bottom: 16px; border: none; border-radius: var(--radius); box-shadow: var(--shadow-sm); } .alert-info { background-color: #eef2ff; color: #3730a3; } .alert-info a { color: #3730a3; text-decoration: underline; font-weight: 500; } .form-control { border-radius: 8px; border: 1px solid var(--border-color); transition: border-color 0.2s ease, box-shadow 0.2s ease; } .form-control:focus { border-color: var(--accent-blue); box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.15); } h1 { color: var(--text-primary); font-size: 1.6rem; font-weight: 700; margin-bottom: 0.5rem; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .rotate-animation { animation:
```
--------------------------------
### Configure GitHub Proxy
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Set the proxy URL for GitHub requests in the configuration file.
```yaml
# Github Proxy,获取订阅使用,结尾要带的 /
# github-proxy: "https://ghfast.top/"
github-proxy: "https://custom-domain/raw/"
```
--------------------------------
### Configure WebDAV Storage
Source: https://github.com/beck-8/subs-check/blob/master/_autodocs/errors.md
Required configuration fields for WebDAV storage method.
```yaml
save-method: webdav
webdav-url: "https://..."
webdav-username: "..."
webdav-password: "..."
```
--------------------------------
### Configure GitHub Gist Storage
Source: https://github.com/beck-8/subs-check/blob/master/_autodocs/errors.md
Required configuration fields for GitHub Gist storage method.
```yaml
save-method: gist
github-token: "ghp_..."
github-gist-id: "..."
```
--------------------------------
### Manage subs-check Service
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Standard systemd commands to control the subs-check service.
```bash
systemctl start subs-check # 启动
systemctl stop subs-check # 停止
systemctl restart subs-check # 重启
systemctl status subs-check # 状态
journalctl -u subs-check -f # 日志
```
--------------------------------
### Configure R2 Storage
Source: https://github.com/beck-8/subs-check/blob/master/_autodocs/errors.md
Required configuration fields for R2 storage method.
```yaml
save-method: r2
worker-url: "https://..."
worker-token: "..."
```
--------------------------------
### Identify Process Using Port
Source: https://github.com/beck-8/subs-check/blob/master/_autodocs/errors.md
Use this command to find and terminate processes that are blocking the required HTTP server port.
```bash
lsof -i :8199
```
--------------------------------
### Configure HTTP Server Port
Source: https://github.com/beck-8/subs-check/blob/master/_autodocs/errors.md
Update the configuration to use a different port if the default port is already in use.
```yaml
listen-port: ":8200"
```
--------------------------------
### Main Layout and Flexbox Containers
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Layout rules for the main content area, ensuring cards and editors maintain consistent heights.
```css
.main-row { display: flex; flex-wrap: wrap; } .main-row > [class*="col-"] { display: flex; } .main-row .card { display: flex; flex-direction: column; width: 100%; } .main-row .card > .card-body { flex: 1 1 auto; overflow: hidden; display: flex; flex-direction: column; min-height: 0; } .editor-wrapper { position: relative; flex: 1 1 auto; min-height: 0; } #editor { position: absolute; inset: 0; border: none; margin-bottom: 0; }
```
--------------------------------
### Configure S3 Storage
Source: https://github.com/beck-8/subs-check/blob/master/_autodocs/errors.md
Required configuration fields for S3 storage method.
```yaml
save-method: s3
s3-endpoint: "..."
s3-access-id: "..."
s3-secret-key: "..."
s3-bucket: "..."
```
--------------------------------
### Phase and Progress UI Updates
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Manages the visual state of phase indicators and progress bars based on processing status.
```javascript
// 缓存阶段步骤 DOM 元素 const phaseStepEls = [null, document.getElementById('phaseStep1'), document.getElementById('phaseStep2'), document.getElementById('phaseStep3')]; const phaseCountEls = [null, document.getElementById('phaseCount1'), document.getElementById('phaseCount2'), document.getElementById('phaseCount3')]; // 更新阶段步骤指示器 function updatePhaseSteps(phase, available, total, phaseResults) { // 检查是否有任何阶段结果 const hasResults = phaseResults && (phaseResults['1'] || phaseResults['2'] || phaseResults['3']); if (phase === 0 && !hasResults) { dom.phaseSteps.style.display = 'none'; return; } dom.phaseSteps.style.display = 'flex'; for (let i = 1; i <= 3; i++) { const step = phaseStepEls[i]; const count = phaseCountEls[i]; const label = PHASE_LABELS[i] ? PHASE_LABELS[i].countLabel : ''; const result = phaseResults ? phaseResults[String(i)] : null; step.classList.remove('active', 'done'); if (i < phase) { // 已完成的阶段:用后端保存的结果 step.classList.add('done'); if (result) { count.textContent = label + ': ' + result.available + '/' + result.total; } } else if (i === phase) { // 当前阶段:用实时数据 step.classList.add('active'); count.textContent = label + ': ' + available + '/' + total; } else if (phase === 0 && result) { // 空闲时:显示上次结果 step.classList.add('done'); count.textContent = label + ': ' + result.available + '/' + result.total; } else { count.textContent = ''; } } } // 更新进度条 function updateProgressBar(total, processed, available, phase, phaseResults) { const percentTotal = total > 0 ? (processed / total * 100).toFixed(1) : 0; dom.progressText.textContent = processed + '/' + total; dom.progressPercent.textContent = percentTotal + '%'; dom.progressBarTotal.style.width = percentTotal + '%'; const percentSuccess = total > 0 ? (available / total * 100).toFixed(1) : 0; dom.processPercent.textContent = percentSuccess + '%'; // 显示阶段对应的标签 const label = (phase && PHASE_LABELS[phase]) ? PHASE_LABELS[phase].countLabel : '成功节点'; if (dom.successLabel && dom.successText) { dom.successLabel.childNodes[0].textContent = label + ': '; if (available > 0) { dom.successText.innerHTML = '' + available + '/' + total; } else { dom.successText.textContent = available + '/' + total; } } dom.progressBarSuccess.style.width = percentSuccess + '%'; // 更新阶段指示器 updatePhaseSteps(phase, available, total, phaseResults); } // 重置进度条到初始状态 function resetProgress() { dom.progressText.textContent = 'N/A'; dom.progressPercent.textContent = 'N/A'; dom.processPercent.textContent = 'N/A'; dom.progressBarTotal.style.width = '0%'; dom.progressBarSuccess.style.width = '0%'; if (dom.successLabel) { dom.successLabel.childNodes[0].textContent = '成功节点: '; dom.successText.textContent = 'N/A'; } }
```
--------------------------------
### Log Processing and Display
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Handles log retrieval, HTML escaping, and color-coding based on log levels.
```javascript
dom.logs.scrollHeight - dom.logs.clientHeight <= dom.logs.scrollTop + 1; const fragment = document.createDocumentFragment(); data.logs.forEach(log => { const logLine = document.createElement('div'); logLine.innerHTML = colorizeLog(log); fragment.appendChild(logLine); }); dom.logs.innerHTML = ''; dom.logs.appendChild(fragment); if (isScrolledToBottom) { dom.logs.scrollTop = dom.logs.scrollHeight; } } return data; }) .catch(error => { if (error.message !== '未授权') { dom.logs.textContent = '加载日志失败: ' + error.message; } }); } function escapeHtml(str) { return str.replace(/&/g,'&').replace(//g,'>'); } // 为日志添加颜色 const LOG_LEVEL_CLASS = { INF: 'log-info', ERR: 'log-error', WRN: 'log-warn', DBG: 'log-debug' }; function colorizeLog(log) { log = escapeHtml(log); log = log.replace(/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/, '$1'); log = log.replace(/\b(INF|ERR|WRN|DBG)\b/, (m) => '' + m + ''); return log; } // 刷新日志 document.getElementById('refreshLogs').addEventListener('click', function() { const button = this; const icon = button.querySelector('i'); icon.classList.add('rotate-animation'); button.disabled = true; loadLogs().finally(() => { setTimeout(() => { icon.classList.remove('rotate-animation'); button.disabled = false; }, 500); }); });
```
--------------------------------
### Set Custom Speed Test URL
Source: https://github.com/beck-8/subs-check/blob/master/README.md
Define the speed test endpoint in the configuration file.
```yaml
# 100MB
speed-test-url: https://custom-domain/speedtest?bytes=104857600
# 1GB
speed-test-url: https://custom-domain/speedtest?bytes=1073741824
```
--------------------------------
### CSS Variables and Base Styles
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Defines the color palette, spacing, and typography used throughout the admin interface.
```css
:root { --bg-primary: #f0f2f5; --bg-card: #ffffff; --border-color: #e8ecf1; --text-primary: #1a1a2e; --text-secondary: #6c757d; --accent-blue: #4361ee; --accent-green: #2ec4b6; --accent-red: #e63946; --accent-yellow: #f4a261; --accent-cyan: #4cc9f0; --shadow-sm: 0 1px 3px rgba(0,0,0,0.08); --shadow-md: 0 4px 12px rgba(0,0,0,0.1); --radius: 10px; } body { padding: 20px; background-color: var(--bg-primary); color: var(--text-primary); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
```
--------------------------------
### Admin Interface CSS Styles
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
CSS definitions for UI components including editor overlays, phase indicators, progress bars, and scrollbar customization.
```css
spin 1s linear infinite; display: inline-block; } /* 配置编辑器蒙版 */ .editor-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(240, 242, 245, 0.92); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); z-index: 10; display: flex; justify-content: center; align-items: center; cursor: pointer; } .editor-overlay-message { background-color: var(--bg-card); color: var(--text-secondary); padding: 16px 24px; border-radius: var(--radius); box-shadow: var(--shadow-md); text-align: center; } /* 阶段步骤指示器 */ .phase-steps { display: flex; gap: 8px; margin-bottom: 10px; } .phase-step { flex: 1; text-align: center; padding: 6px 8px; border-radius: 8px; font-size: 0.78rem; font-weight: 600; background-color: #f0f2f5; color: var(--text-secondary); border: 1px solid var(--border-color); transition: all 0.3s ease; } .phase-step.active { background-color: var(--accent-blue); color: white; border-color: var(--accent-blue); box-shadow: 0 2px 8px rgba(67, 97, 238, 0.3); } .phase-step.done { background-color: #d1fae5; color: #065f46; border-color: #a7f3d0; } .phase-step .phase-icon { margin-right: 4px; } .phase-step .phase-count { display: block; font-size: 0.7rem; font-weight: 400; opacity: 0.85; margin-top: 2px; } /* 进度条样式 */ .progress-section { padding: 14px; background-color: var(--bg-card); border-top: 1px solid var(--border-color); } .progress-info { display: flex; justify-content: space-between; margin-bottom: 6px; font-size: 13px; color: var(--text-secondary); } .progress { height: 12px; position: relative; background-color: #e9ecef; border-radius: 6px; overflow: hidden; } .progress-bar { transition: width 0.5s ease; border-radius: 6px; } .progress-bar-success { background: linear-gradient(90deg, #2ec4b6, #28a745); position: absolute; height: 100%; left: 0; top: 0; z-index: 10; box-shadow: 0 0 10px rgba(46, 196, 182, 0.4); } .progress-bar-total { background-color: rgba(67, 97, 238, 0.25); position: absolute; height: 100%; left: 0; top: 0; z-index: 5; } /* 闪烁效果 */ @keyframes pulse { 0% { opacity: 0.7; } 50% { opacity: 1; } 100% { opacity: 0.7; } } .success-highlight { animation: pulse 1.5s infinite; font-weight: bold; color: var(--accent-green); padding: 1px 4px; border-radius: 4px; background-color: rgba(46, 196, 182, 0.1); } /* 版本标签 */ .version-badge { display: inline-block; padding: 2px 10px; border-radius: 20px; background-color: #eef2ff; color: var(--accent-blue); font-size: 0.78rem; font-weight: 500; } /* 日志容器滚动条 */ .logs-container::-webkit-scrollbar { width: 6px; } .logs-container::-webkit-scrollbar-track { background: transparent; } .logs-container::-webkit-scrollbar-thumb { background: #45475a; border-radius: 3px; } .logs-container::-webkit-scrollbar-thumb:hover { background: #585b70; }
```
--------------------------------
### Log Container Styling
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Specific styling for the log output area, including font and color schemes.
```css
.logs-container { flex: 1 1 auto; min-height: 0; overflow-y: auto; background-color: #1e1e2e; padding: 14px; font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; font-size: 12px; white-space: pre-wrap; border: none; margin-bottom: 0; color: #cdd6f4; border-radius: 0; }
```
--------------------------------
### 获取订阅文件 URL
Source: https://github.com/beck-8/subs-check/blob/master/doc/r2.md
通过 Worker URL 获取存储在 R2 中的订阅文件,需提供文件名和访问令牌。
```text
https://your-worker-url/storage?filename=all.yaml&token=AUTH_TOKEN
```
```text
https://your-worker-url/storage?filename=base64.txt&token=AUTH_TOKEN
```
```text
https://your-worker-url/storage?filename=mihomo.yaml&token=AUTH_TOKEN
```
--------------------------------
### Update Pipeline UI Components
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Functions to update the visual pipeline steps and progress bars based on current processing data.
```javascript
function updatePipelineSteps(p, hasSpeed) { dom.phaseSteps.style.display = 'flex'; const rows = [ { idx: 1, label: '存活', pass: p.alivePass, total: p.total, active: true }, { idx: 2, label: '通过', pass: p.filterPass, total: p.alivePass, active: true }, { idx: 3, label: '通过', pass: p.speedPass, total: p.filterPass, active: hasSpeed }, ]; for (const r of rows) { const step = phaseStepEls[r.idx]; const count = phaseCountEls[r.idx]; step.classList.remove('active', 'done'); if (r.active) { step.classList.add('active'); count.textContent = r.label + ': ' + r.pass + '/' + r.total; } else { count.textContent = ''; } } } function updatePipelineBar(p, hasSpeed) { const total = p.total; const processed = p.aliveDone; // how far through input const success = hasSpeed ? p.speedPass : p.filterPass; // end-to-end pass count const pctProcessed = total > 0 ? (processed / total * 100).toFixed(1) : 0; dom.progressText.textContent = processed + '/' + total; dom.progressPercent.textContent = pctProcessed + '%'; dom.progressBarTotal.style.width = pctProcessed + '%'; const pctSuccess = total > 0 ? (success / total * 100).toFixed(1) : 0; dom.processPercent.textContent = pctSuccess + '%'; dom.progressBarSuccess.style.width = pctSuccess + '%'; if (dom.successLabel && dom.successText) { dom.successLabel.childNodes[0].textContent = '通过: '; dom.successText.innerHTML = success > 0 ? '' + success + '/' + total : success + '/' + total; } }
```
--------------------------------
### API Key Management and Request Headers
Source: https://github.com/beck-8/subs-check/blob/master/app/templates/admin.html
Utility functions to retrieve the stored API key and inject it into request headers for authenticated API calls.
```javascript
// 获取API密钥 function getApiKey() { return localStorage.getItem('apiKey') || ''; } // 添加API密钥到请求头 function addApiKeyHeader(headers = {}) { const apiKey = getApiKey(); return { ...headers, 'X-API-Key': apiKey }; }
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.