This commit is contained in:
CrazyJasonwell
2026-10-07 11:07:00 +08:00
parent e88e4de0f5
commit 290ff8984f
96 changed files with 213854 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python 调试程序: 包含参数的当前文件",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"python": "/opt/homebrew/bin/python3",
"args": "${command:pickArgs}"
}
]
}
+11
View File
@@ -0,0 +1,11 @@
{
"python-envs.defaultEnvManager": "ms-python.python:system",
"python.defaultInterpreterPath": "/opt/homebrew/bin/python3",
"terminal.integrated.defaultProfile.osx": "zsh",
"terminal.integrated.env.osx": {
"PATH": "/opt/homebrew/bin:${env:PATH}"
},
"code-runner.executorMap": {
"python": "python3 -u"
}
}
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
# ----------------------------------
# 参数配置(可修改)
# ----------------------------------
SOURCE_DIR="/path/to/your/directory" # 要扫描的目录(网盘映射路径)
OUTPUT_FILE="strm_stats.txt" # 结果输出文件
SLEEP_INTERVAL=0.5 # 扫描间隔(秒,可调节防止风控)
MAX_DEPTH=5 # 最大递归深度(避免扫描过深)
# ----------------------------------
# 检查目录是否存在
# ----------------------------------
if [[ ! -d "$SOURCE_DIR" ]]; then
echo "[ERROR] 目录 $SOURCE_DIR 不存在!"
exit 1
fi
# ----------------------------------
# 初始化统计变量
# ----------------------------------
declare -A dir_counts # 存储各目录的 .strm 文件数
echo "开始扫描 $SOURCE_DIR(子目录深度 $MAX_DEPTH,间隔 $SLEEP_INTERVAL 秒)..."
# ----------------------------------
# 递归遍历目录并统计 .strm 文件
# ----------------------------------
find "$SOURCE_DIR" -type d -print0 | while IFS= read -r -d '' dir; do
# 跳过超过深度的目录
if [[ $(awk -F/ '{print NF-1}' <<< "${dir#$SOURCE_DIR/}") -ge $MAX_DEPTH ]]; then
continue
fi
# 统计当前目录的 .strm 文件数
count=$(find "$dir" -maxdepth 1 -type f -name "*.strm" | wc -l)
if [[ $count -gt 0 ]]; then
dir_counts["${dir#$SOURCE_DIR/}"]=$count
echo "[发现] ${dir#$SOURCE_DIR/}: $count 个 .strm 文件"
fi
# 按需暂停(防止网盘风控)
sleep $SLEEP_INTERVAL
done
# ----------------------------------
# 输出结果
# ----------------------------------
echo "===== 结果统计 =====" > "$OUTPUT_FILE"
for dir in "${!dir_counts[@]}"; do
echo "$dir: ${dir_counts[$dir]} 个文件" >> "$OUTPUT_FILE"
done
echo "扫描完成!结果已保存至 $OUTPUT_FILE。"
+47
View File
@@ -0,0 +1,47 @@
# 与服务端建立连接,跟上面的配置要对应 阿里106.15.121.26 腾讯150.158.120.215 联通云 116.162.100.119
serverAddr = "124.220.30.149"
serverPort = 7000
# 配置Token鉴权,要与服务端一致
auth.method = "token"
auth.token = "admin8466"
# 配置日志信息
#log.level = "warn"
#log.to = "/opt/frpc/frpc.log"
# frpc.toml
webServer.addr = "192.168.1.108"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "admin8466"
[[proxies]]
name = "frp-fnOS-openlist-9161"
type = "tcp"
localIP = "127.0.0.1"
localPort = 7244
remotePort = 9161
#[[proxies]]
#name = "frp-fnOST-alist"
#type = "tcp"
#localIP = "127.0.0.1"
#localPort = 5244
#remotePort = 5644
[[proxies]]
name = "frp-fnOS-cwa"
type = "tcp"
localIP = "127.0.0.1"
localPort = 7083
remotePort = 7083
+30
View File
@@ -0,0 +1,30 @@
# 与服务端建立连接,跟上面的配置要对应
#serverAddr = "106.15.121.26"
#serverPort = 7000
# 配置Token鉴权,要与服务端一致
#auth.method = "token"
#auth.token = "admin8466"
# 配置日志信息
#log.level = "warn"
#log.to = "/opt/frpc/frpc.log"
# frpc.toml
webServer.addr = "127.0.0.1"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "admin8466"
#[[proxies]]
#name = "frp-fnOS-alist"
#type = "tcp"
#localIP = "127.0.0.1"
# fnOS 5244 fnOST 5245 106.15.121.26 放行52445245端口
#localPort = 5244
#remotePort = 5244
+16
View File
@@ -0,0 +1,16 @@
bindAddr = "0.0.0.0"
bindPort = 7000
auth.method = "token"
auth.token = "admin8466"
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "Mayi19b8"
# tls
#transport.tls.force = true
#transport.tls.certFile = "/etc/frp/ssl/server.crt"
#transport.tls.keyFile = "/etc/frp/ssl/server.key"
#transport.tls.trustedCaFile = "/etc/frp/ssl/ca.crt"
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
rclone mount xiaoyastrm: /vol4/1000/USBD2/MediaLibrary/xiaoyastrm --header "Referer:" --multi-thread-streams 6 --buffer-size 512M --vfs-fast-fingerprint --vfs-cache-mode full --no-modtime --file-perms 0777 --copy-links --allow-other --allow-non-empty --umask 000 --cache-dir /vol1/cache/rclone
#rclone mount wd_joycloud_dsm920: /vol4/1000/USBD2/MediaLibrary/Mdsm920 --header "Referer:" --multi-thread-streams 6 --buffer-size 512M --vfs-fast-fingerprint --vfs-cache-mode full --no-modtime --file-perms 0777 --copy-links --allow-other --allow-non-empty --umask 000 --cache-dir /vol1/cache/rclone
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
#!/bin/bash
# ----------------------------------
# 参数配置(可修改)
# ----------------------------------
SOURCE_DIR="/vol4/1000/USBD2/MediaLibrary/Mdsm920/本地磁盘/fnOS/strms/电影/动画电影" # 要扫描的目录(网盘映射路径)
OUTPUT_FILE="/vol4/1000/USBD2/MediaLibrary/strm_stats.txt" # 结果输出文件
SLEEP_INTERVAL=0.5 # 扫描间隔(秒,可调节防止风控)
MAX_DEPTH=5 # 最大递归深度(避免扫描过深)
# ----------------------------------
# 检查目录是否存在
# ----------------------------------
if [[ ! -d "$SOURCE_DIR" ]]; then
echo "[ERROR] 目录 $SOURCE_DIR 不存在!"
exit 1
fi
# ----------------------------------
# 初始化统计变量
# ----------------------------------
declare -A dir_counts # 存储各目录的 .strm 文件数
echo "开始扫描 $SOURCE_DIR(子目录深度 $MAX_DEPTH,间隔 $SLEEP_INTERVAL 秒)..."
# ----------------------------------
# 递归遍历目录并统计 .strm 文件
# ----------------------------------
find "$SOURCE_DIR" -type d -print0 | while IFS= read -r -d '' dir; do
# 跳过超过深度的目录
if [[ $(awk -F/ '{print NF-1}' <<< "${dir#$SOURCE_DIR/}") -ge $MAX_DEPTH ]]; then
continue
fi
# 统计当前目录的 .strm 文件数
count=$(find "$dir" -maxdepth 1 -type f -name "*.strm" | wc -l)
if [[ $count -gt 0 ]]; then
dir_counts["${dir#$SOURCE_DIR/}"]=$count
echo "[发现] ${dir#$SOURCE_DIR/}: $count 个 .strm 文件"
fi
# 按需暂停(防止网盘风控)
sleep $SLEEP_INTERVAL
done
# ----------------------------------
# 输出结果
# ----------------------------------
echo "===== 结果统计 =====" > "$OUTPUT_FILE"
for dir in "${!dir_counts[@]}"; do
echo "$dir: ${dir_counts[$dir]} 个文件" >> "$OUTPUT_FILE"
done
echo "扫描完成!结果已保存至 $OUTPUT_FILE。"
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
# 等待某个容器完全启动(支持健康检查)
CONTAINER_NAME="xiaoya" # 替换为你的容器名
MAX_RETRIES=30
SLEEP_TIME=5
for i in $(seq 1 $MAX_RETRIES); do
if docker inspect --format '{{.State.Running}}' $CONTAINER_NAME 2>/dev/null | grep -q "true"; then
echo "[INFO] Container $CONTAINER_NAME is running."
sleep 30
exit 0
fi
echo "[WAIT] Container $CONTAINER_NAME not ready ($i/$MAX_RETRIES)..."
sleep $SLEEP_TIME
done
echo "[ERROR] Timeout: Container $CONTAINER_NAME did not start!"
exit 1
@@ -0,0 +1,42 @@
#!/bin/bash
# 定义目标目录(可修改为你的路径)
TARGET_DIR="$1"
# 检查是否传入目录参数
if [[ -z "$TARGET_DIR" || ! -d "$TARGET_DIR" ]]; then
echo "[错误] 请指定有效的目录路径!"
echo "用法: $0 /path/to/directory"
exit 1
fi
# 定义目标文件扩展名(视频 + 音频)
FILE_EXTENSIONS=("mp4" "mkv" "flv" "avi" "wmv" "ts" "rmvb" "webm" "mp3" "flac" "aac" "wav" "ogg" "m4a" "wma" "alac")
echo "[INFO] 正在扫描 $TARGET_DIR 下的媒体文件..."
# 遍历所有子目录并匹配目标扩展名
find "$TARGET_DIR" -type f \( \
-iname "*.mp4" -o \
-iname "*.mkv" -o \
-iname "*.flv" -o \
-iname "*.avi" -o \
-iname "*.wmv" -o \
-iname "*.ts" -o \
-iname "*.rmvb" -o \
-iname "*.webm" -o \
-iname "*.mp3" -o \
-iname "*.flac" -o \
-iname "*.aac" -o \
-iname "*.wav" -o \
-iname "*.ogg" -o \
-iname "*.m4a" -o \
-iname "*.wma" -o \
-iname "*.alac" \) -exec ls -la {} \;
# 汇总统计
echo "===== 统计 ====="
for ext in "${FILE_EXTENSIONS[@]}"; do
count=$(find "$TARGET_DIR" -type f -iname "*.$ext" | wc -l)
echo ".$ext: $count 个文件"
done
+94
View File
@@ -0,0 +1,94 @@
{
"file_rules": [
{
"rule_id": "F001",
"order": 1,
"kind": "bracket_pair",
"open": "\\[",
"close": "\\]",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "F002",
"order": 2,
"kind": "bracket_pair",
"open": "【",
"close": "】",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "F003",
"order": 3,
"kind": "string",
"pattern": "2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB\\-DL|HD|4K|REMUX|RMVB|HDR10Plus|10bit|60fps",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "F004",
"order": 4,
"kind": "string",
"pattern": "双语字幕|双语|中英双语|中英双字|双语中字|官方中字|特效中字",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "F005",
"order": 5,
"kind": "string",
"pattern": "CMCT|WiKi|CHD|SiluHD|PublicHD|RARBG|TGx|‑HDHome|52pt|HHWEB|ZmWeb|ADWeb|BT‑PT|‑CHD|‑WiKi|‑RARBG|‑HHWEB|‑ZmWeb|‑PublicHD|‑52pt|‑CiNEFiLE",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "F006",
"order": 6,
"kind": "string",
"pattern": "收藏不迷路|地址发布页|九洲客|tdw9430|6v电影|电影港|www\\.6v123\\.net|www\\.dygang\\.me|www\\.dream2008\\.cn|www\\.6v123\\.com",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "F007",
"order": 7,
"kind": "string",
"pattern": "\\d+\\.5G|\\d+G|MKV|TS",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
}
],
"dir_rules": [
{
"rule_id": "D001",
"order": 1,
"kind": "string",
"pattern": "2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB\\-DL|HD|4K",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "D002",
"order": 2,
"kind": "string",
"pattern": "双语字幕|双语|中英双语|中英双字|双语中字|官方中字|特效中字",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "D003",
"order": 3,
"kind": "string",
"pattern": "收藏不迷路|地址发布页|九洲客|tdw9430|6v电影|电影港|www\\.6v123\\.net|www\\.dygang\\.me|www\\.dream2008\\.cn|www\\.6v123\\.com",
"repl": "",
"safe_guard_empty": true
}
]
}
+142
View File
@@ -0,0 +1,142 @@
{
"file_rules": [
{
"rule_id": "F001",
"order": 1,
"kind": "bracket_pair",
"open": "\\[",
"close": "\\]",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "F002",
"order": 2,
"kind": "bracket_pair",
"open": "【",
"close": "】",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "F003",
"order": 3,
"kind": "string",
"pattern": "2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB\\-DL|HD|4K|REMUX|RMVB|HDR10Plus|10bit|60fps",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "F004",
"order": 4,
"kind": "string",
"pattern": "双语字幕|双语|中英双语|中英双字|双语中字|官方中字|特效中字",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "F005",
"order": 5,
"kind": "string",
"pattern": "CMCT|WiKi|CHD|SiluHD|PublicHD|RARBG|TGx|‑HDHome|52pt|HHWEB|ZmWeb|ADWeb|BT‑PT|‑CHD|‑WiKi|‑RARBG|‑HHWEB|‑ZmWeb|‑PublicHD|‑52pt|‑CiNEFiLE",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "F006",
"order": 6,
"kind": "string",
"pattern": "收藏不迷路|地址发布页|九洲客|tdw9430|6v电影|电影港|www\\.6v123\\.net|www\\.dygang\\.me|www\\.dream2008\\.cn|www\\.6v123\\.com",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "F007",
"order": 7,
"kind": "string",
"pattern": "\\d+\\.5G|\\d+G|MKV|TS",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "F013",
"order": 13,
"kind": "string",
"pattern": "【[^】]*】",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "F014",
"order": 14,
"kind": "string",
"pattern": "\\[\\]",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "F015",
"order": 15,
"kind": "string",
"pattern": "【】",
"repl": "",
"safe_guard_empty": true
}
],
"dir_rules": [
{
"rule_id": "D001",
"order": 1,
"kind": "string",
"pattern": "2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB\\-DL|HD|4K",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "D002",
"order": 2,
"kind": "string",
"pattern": "双语字幕|双语|中英双语|中英双字|双语中字|官方中字|特效中字",
"repl": "",
"safe_guard_empty": true,
"flags": "IGNORECASE"
},
{
"rule_id": "D003",
"order": 3,
"kind": "string",
"pattern": "收藏不迷路|地址发布页|九洲客|tdw9430|6v电影|电影港|www\\.6v123\\.net|www\\.dygang\\.me|www\\.dream2008\\.cn|www\\.6v123\\.com",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "D006",
"order": 6,
"kind": "string",
"pattern": "【[^】]*】",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "D007",
"order": 7,
"kind": "string",
"pattern": "\\[\\]",
"repl": "",
"safe_guard_empty": true
},
{
"rule_id": "D008",
"order": 8,
"kind": "string",
"pattern": "【】",
"repl": "",
"safe_guard_empty": true
}
]
}
+8
View File
@@ -0,0 +1,8 @@
{
"source": "/vol4/1000/USBD2/MediaLibrary/output-two",
"dest": "/vol4/1000/USBD2/MediaLibrary/out-final",
"tmdb_api_key": "",
"mock": false,
"settle": 6,
"language": "zh-CN"
}
+17
View File
@@ -0,0 +1,17 @@
[Unit]
Description=Self Media Scraper Watcher (TMDB)
# 用途:开机自启,监听清理目录,新媒体出现自动刮削并复制落库
After=network.target
[Service]
Type=simple
# ---- 下面 3 行把 /你的项目绝对路径 替换成飞牛上放本项目的真实路径 ----
ExecStart=/你的项目绝对路径/.venv/bin/python /你的项目绝对路径/watcher.py --config /你的项目绝对路径/config.json
WorkingDirectory=/你的项目绝对路径
Restart=always
RestartSec=5
StandardOutput=append:/你的项目绝对路径/scraper.out
StandardError=append:/你的项目绝对路径/scraper.err
[Install]
WantedBy=multi-user.target
+449
View File
@@ -0,0 +1,449 @@
import os
import re
import json
import argparse
import shutil
from datetime import datetime
LOG_FILE = "./rename_log.txt"
ERR_REPORT_JSON = "./report_err_only.json"
SKIP_DIRS = [
"@eaDir",
]
SKIP_FILES = {
".DS_Store",
"Thumbs.db",
"desktop.ini",
}
FULL_ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm", ".flv", ".avi", ".wmv", ".ts", ".rmvb", ".webm", ".mp3", ".flac", ".aac", ".wav", ".ogg", ".m4a", ".wma", ".alac", ".rm", ".iso"}
STRM_ONLY_EXT = {".strm", ".srt", ".ass", ".sub"}
MAX_FILENAME_LEN = 245
def full2half(s: str) -> str:
res = []
for ch in s:
oc = ord(ch)
if oc == 12288:
res.append(chr(32))
elif 65281 <= oc <= 65374:
res.append(chr(oc - 65248))
else:
res.append(ch)
return "".join(res)
def remove_emoji(s: str) -> str:
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F"
u"\U0001F300-\U0001F5FF"
u"\U0001F680-\U0001F6FF"
u"\U0001F1E0-\U0001F1FF"
u"\U00002700-\U000027BF"
u"\U0001F900-\U0001F9FF"
"]+", flags=re.UNICODE)
return emoji_pattern.sub(r'', s)
def post_clean_dot(name: str, is_dir: bool=False) -> str:
"""后置净化:清除连续点、首尾点、首尾下划线;区分目录/文件,保护扩展名"""
if is_dir:
body = name
ext = ""
else:
body, ext = os.path.splitext(name)
body = re.sub(r"\.+", ".", body)
body = body.strip("._")
return body + ext
def stage1_light_clean(name: str, is_dir: bool=False) -> str:
"""阶段一:轻清洗"""
n = name
n = remove_emoji(n)
n = full2half(n)
n = re.sub(r"^[A-Za-z] +", "", n)
n = re.sub(r"\s+", "", n)
n = post_clean_dot(n, is_dir=is_dir)
return n.strip()
def run_rule_list(orig_name: str, rules: list, is_dir: bool=False):
hit_ids = []
cur = orig_name
safeguard_trigger = False
for r in sorted(rules, key=lambda x: x.get("order", 9999)):
rid = r["rule_id"]
kind = r["kind"]
repl = r["repl"]
safe_guard = r.get("safe_guard_empty", False)
rule_flags = r.get("flags", "")
prev = cur
re_flags = 0
if rule_flags == "IGNORECASE":
re_flags = re.IGNORECASE
if kind == "string":
cur = re.sub(r["pattern"], repl, cur, flags=re_flags)
elif kind == "bracket_pair":
o_pat = r["open"]
c_pat = r["close"]
# bracket_pair额外开启DOTALL,.可匹配中文、各类符号
while True:
new_val = re.sub(o_pat + ".*?" + c_pat, repl, cur, flags=re_flags | re.DOTALL)
if new_val == cur:
break
cur = new_val
if safe_guard:
body, ext = (cur, "") if is_dir else os.path.splitext(cur)
if len(body.strip()) == 0:
cur = prev
continue
cur = cur.strip()
if safe_guard:
body, ext = (cur, "") if is_dir else os.path.splitext(cur)
if len(body.strip()) == 0:
cur = prev
continue
if cur != prev:
hit_ids.append(rid)
# 全部规则跑完,全局兜底保护
body_final, ext_final = (cur, "") if is_dir else os.path.splitext(cur)
if len(body_final.strip()) == 0:
safeguard_trigger = True
cur = orig_name
# 符号净化
cur = post_clean_dot(cur, is_dir=is_dir)
# 净化之后再次兜底
body2, ext2 = (cur, "") if is_dir else os.path.splitext(cur)
if len(body2.strip()) == 0:
safeguard_trigger = True
cur = orig_name
return cur, hit_ids, safeguard_trigger
def assign_unique_name_group(item_list):
counter = dict()
out = []
for it in item_list:
cand = it["candidate"]
cnt = counter.get(cand, 0)
final = cand if cnt == 0 else f"{cand}({cnt})"
counter[cand] = cnt + 1
ni = dict(it)
ni["final_step1"] = final
out.append(ni)
return out
def assign_dup_suffix(item_list, name_key: str):
counter = dict()
for it in item_list:
nm = it[name_key]
c = counter.get(nm, 0)
if c > 0:
new_nm = f"{nm}_dup({c})"
it[name_key] = new_nm
it["step2_dup_warn"] = True
else:
it["step2_dup_warn"] = False
counter[nm] = c + 1
def write_log(msg: str, log_file: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
try:
with open(log_file, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
except Exception:
print(f"[LOG-WRITE-FAILED] {line}")
def scan_full_tree(root_src, skip_dirs, skip_files, allow_ext):
dir_entries = []
file_entries = []
root_abs = os.path.abspath(root_src)
for src_root, dirs, files in os.walk(root_src, topdown=True):
remove_idx = []
for idx, dname in enumerate(dirs):
if dname in skip_dirs:
remove_idx.append(idx)
for idx in reversed(remove_idx):
del dirs[idx]
dirs[:] = dirs
src_root_abs = os.path.abspath(src_root)
if src_root_abs != root_abs:
bn = os.path.basename(src_root_abs)
c1 = stage1_light_clean(bn, is_dir=True)
dir_entries.append({
"src_abs": src_root_abs,
"src_parent_abs": os.path.dirname(src_root_abs),
"depth": src_root_abs.count(os.sep),
"orig_basename": bn,
"candidate": c1
})
for fname in files:
if fname in skip_files:
continue
ext = os.path.splitext(fname)[1].lower()
if ext not in allow_ext:
continue
c1 = stage1_light_clean(fname, is_dir=False)
file_entries.append({
"src_parent_abs": src_root_abs,
"orig_basename": fname,
"candidate": c1
})
return root_abs, dir_entries, file_entries
def group_by_parent_abs(item_list, key_name):
groups = dict()
for it in item_list:
k = it[key_name]
if k not in groups:
groups[k] = []
groups[k].append(it)
return groups
def main():
parser = argparse.ArgumentParser(description="两阶段媒体清洗【修复括号匹配,DOTALL开启】")
parser.add_argument("--dir", required=True)
parser.add_argument("--output", required=True)
parser.add_argument("--apply", action="store_true")
parser.add_argument("--dry-run", action="store_true")
parser.add_argument("--strm-mode", action="store_true")
parser.add_argument("--rules", default=None, help="外部json规则文件路径")
parser.add_argument("--log", default=LOG_FILE)
args = parser.parse_args()
target_dir = args.dir
out_dir = args.output
log_path = args.log
rules_path = args.rules
DRY_RUN = True
if args.apply:
DRY_RUN = False
if args.dry_run:
DRY_RUN = True
if args.strm_mode:
ALLOW_EXT = STRM_ONLY_EXT
mode_info = "STRM模式【仅strm+字幕】"
else:
ALLOW_EXT = FULL_ALLOW_EXT
mode_info = "完整媒体模式"
if not os.path.isdir(target_dir):
print(f"源目录不存在:{target_dir}")
return
try:
with open(log_path, "w", encoding="utf-8") as f:
f.flush()
except Exception as e:
print(f"日志初始化警告 {e}")
file_rules = []
dir_rules = []
if rules_path is not None and os.path.exists(rules_path):
try:
with open(rules_path, "r", encoding="utf-8") as f:
jdata = json.load(f)
file_rules = jdata.get("file_rules", [])
dir_rules = jdata.get("dir_rules", [])
write_log(f"成功加载外部规则文件 {rules_path},file_rules={len(file_rules)},dir_rules={len(dir_rules)}", log_path)
except json.JSONDecodeError as e:
write_log(f"规则文件JSON格式错误(第{e.lineno}行第{e.colno}列):{e.msg}", log_path)
write_log("提示:键和字符串值必须用英文双引号,正则中的反斜杠必须写成双反斜杠\\\\", log_path)
return
except Exception as e:
write_log(f"加载规则文件失败:{e}", log_path)
return
else:
write_log("未提供--rules或文件不存在,跳过第二阶段深度清洗", log_path)
write_log("===== 两阶段媒体清洗【修复括号匹配DOTALL】 =====", log_path)
write_log(f"源目录:{target_dir}", log_path)
write_log(f"输出:{out_dir}", log_path)
write_log(f"模式:{mode_info} DRY_RUN={DRY_RUN}", log_path)
stat = {
"src_dir_total":0,
"src_file_total":0,
"dir_success":0,
"dir_fail":0,
"file_success":0,
"file_fail":0
}
report_entries = []
root_src_abs, dir_entries, file_entries = scan_full_tree(target_dir, SKIP_DIRS, SKIP_FILES, ALLOW_EXT)
stat["src_dir_total"] = len(dir_entries)
stat["src_file_total"] = len(file_entries)
write_log(f"采集统计:目录节点 {stat['src_dir_total']},媒体文件 {stat['src_file_total']}", log_path)
dir_groups = group_by_parent_abs(dir_entries, "src_parent_abs")
dir_final = []
for p_abs, items in dir_groups.items():
assigned = assign_unique_name_group(items)
for it in assigned:
step1_name = it["final_step1"]
if len(dir_rules) > 0:
step2_name, hit_rids, safe_trig = run_rule_list(step1_name, dir_rules, is_dir=True)
else:
step2_name = step1_name
hit_rids = []
safe_trig = False
it["step2_name"] = step2_name
it["hit_rule_ids"] = hit_rids
it["safe_guard_trigger"] = safe_trig
dir_final.append(it)
dir_g2_groups = group_by_parent_abs(dir_final, "src_parent_abs")
for _, items in dir_g2_groups.items():
assign_dup_suffix(items, "step2_name")
file_groups = group_by_parent_abs(file_entries, "src_parent_abs")
file_final = []
for p_abs, items in file_groups.items():
assigned = assign_unique_name_group(items)
for it in assigned:
step1_name = it["final_step1"]
if len(file_rules) > 0:
step2_name, hit_rids, safe_trig = run_rule_list(step1_name, file_rules, is_dir=False)
else:
step2_name = step1_name
hit_rids = []
safe_trig = False
it["step2_name"] = step2_name
it["hit_rule_ids"] = hit_rids
it["safe_guard_trigger"] = safe_trig
file_final.append(it)
file_g2_groups = group_by_parent_abs(file_final, "src_parent_abs")
for _, items in file_g2_groups.items():
assign_dup_suffix(items, "step2_name")
src_to_out = dict()
src_to_out[root_src_abs] = out_dir
dir_final_sorted = sorted(dir_final, key=lambda x: x["depth"])
for d in dir_final_sorted:
p_abs = d["src_parent_abs"]
parent_out = src_to_out.get(p_abs)
if parent_out is None:
write_log(f"【警告】父目录映射缺失:{p_abs}", log_path)
continue
child_out = os.path.join(parent_out, d["step2_name"])
src_to_out[d["src_abs"]] = child_out
for d in dir_final:
report_entries.append({
"type":"dir",
"src_abs":d["src_abs"],
"orig_basename":d["orig_basename"],
"step1_name":d["final_step1"],
"step2_name":d["step2_name"],
"hit_rule_ids":d["hit_rule_ids"],
"safe_guard_trigger":d["safe_guard_trigger"],
"step2_dup_warn":d.get("step2_dup_warn", False),
"final_out_path": src_to_out.get(d["src_abs"], "")
})
for f in file_final:
src_file = os.path.join(f["src_parent_abs"], f["orig_basename"])
parent_out = src_to_out.get(f["src_parent_abs"])
dst_file = os.path.join(parent_out, f["step2_name"]) if parent_out else ""
report_entries.append({
"type":"file",
"src_abs":src_file,
"orig_basename":f["orig_basename"],
"step1_name":f["final_step1"],
"step2_name":f["step2_name"],
"hit_rule_ids":f["hit_rule_ids"],
"safe_guard_trigger":f["safe_guard_trigger"],
"step2_dup_warn":f.get("step2_dup_warn", False),
"final_out_path": dst_file
})
# 仅输出异常报告,丢弃完整大JSON
err_list = []
for entry in report_entries:
dup = entry.get("step2_dup_warn", False)
safe = entry.get("safe_guard_trigger", False)
if dup or safe:
err_list.append({
"type": entry.get("type"),
"orig_basename": entry.get("orig_basename"),
"step1_name": entry.get("step1_name"),
"step2_name": entry.get("step2_name"),
"step2_dup_warn": dup,
"safe_guard_trigger": safe,
"hit_rule_ids": entry.get("hit_rule_ids", [])
})
try:
with open(ERR_REPORT_JSON, "w", encoding="utf-8") as fw:
json.dump(err_list, fw, ensure_ascii=False, indent=2)
write_log(f"异常报告已输出:{ERR_REPORT_JSON},异常条目数量:{len(err_list)}", log_path)
except Exception as e:
write_log(f"异常报告写入失败 {e}", log_path)
for ent in report_entries:
ot = ent["orig_basename"]
s1 = ent["step1_name"]
s2 = ent["step2_name"]
parts = []
if ot != s1:
parts.append(f"原始→step1:{ot} → {s1}")
if s1 != s2:
parts.append(f"step1→step2:{s1} → {s2}")
if ent["step2_dup_warn"]:
parts.append("[告警:step2重名追加_dup标记]")
if ent["safe_guard_trigger"]:
parts.append("[安全保护触发,放弃部分规则]")
if len(parts) > 0:
write_log(" | ".join(parts), log_path)
del report_entries
if DRY_RUN:
write_log("===== DRY-RUN预览模式结束,未执行磁盘IO =====", log_path)
return
for d in dir_final_sorted:
full_out = src_to_out.get(d["src_abs"])
if not full_out:
continue
try:
os.makedirs(full_out, exist_ok=True)
stat["dir_success"] +=1
except OSError as e:
stat["dir_fail"] +=1
write_log(f"【目录创建失败】{full_out} | {e}", log_path)
for f in file_final:
src_fp = os.path.join(f["src_parent_abs"], f["orig_basename"])
parent_out = src_to_out.get(f["src_parent_abs"])
if not parent_out:
stat["file_fail"] +=1
write_log(f"【文件复制失败】父目录映射缺失:{src_fp}", log_path)
continue
dst_fp = os.path.join(parent_out, f["step2_name"])
try:
shutil.copy2(src_fp, dst_fp)
stat["file_success"] +=1
except OSError as e:
stat["file_fail"] +=1
write_log(f"【文件复制失败】src:{src_fp} dst:{dst_fp} | {e}", log_path)
write_log("----------任务统计汇总----------", log_path)
write_log(f"源采集目录节点总数量:{stat['src_dir_total']},源媒体文件总数量:{stat['src_file_total']}", log_path)
write_log(f"目录:成功 {stat['dir_success']},失败 {stat['dir_fail']}", log_path)
write_log(f"文件:成功 {stat['file_success']},失败 {stat['file_fail']}", log_path)
write_log(f"【校验】预期目录输出={stat['src_dir_total']},实际成功={stat['dir_success']}", log_path)
write_log(f"【校验】预期文件输出={stat['src_file_total']},实际成功={stat['file_success']}", log_path)
write_log("============================================================", log_path)
if __name__ == "__main__":
main()
+597
View File
@@ -0,0 +1,597 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
media_scraper.py —— 自研媒体刮削器(核心库 + 命令行)
流程:接收一个媒体单元(单个电影文件 / 电影目录 / 剧集目录)
1. 从文件名/目录名解析标题、年份、类型(电影/剧集)、季/集
2. 查询 TMDB(电影 search/movie,剧集 search/tv)
3. 把媒体文件「复制」到成品目录(落库)
4. 在成品目录就地生成 Kodi 规范的 nfo + 下载海报/背景图
命令行用法:
./media_scraper.py --source <路径> --dest <成品目录> [--config config.json] [--mock] [--dry-run] [--recurse]
依赖:requests(TMDB 调用)。TMDB API Key 通过 config.json 或环境变量 TMDB_API_KEY 提供。
未配置 Key 时可用 --mock 模式跑通整条管线(用模拟元数据,验证 nfo 生成 + 复制落库)。
"""
import argparse
import json
import os
import re
import shutil
import sys
import time
import xml.etree.ElementTree as ET
from datetime import datetime
from urllib.parse import quote
import requests
# ---------------------------------------------------------------------------
# 常量与配置
# ---------------------------------------------------------------------------
VIDEO_EXTS = {".mkv", ".mp4", ".mov", ".avi", ".wmv", ".flv", ".ts", ".webm",
".rmvb", ".iso", ".m2ts", ".mts"}
SUB_EXTS = {".srt", ".ass", ".sub", ".ssa"}
TMDB_IMAGE_BASE = "https://image.tmdb.org/t/p/w500"
TMDB_IMAGE_ORIG = "https://image.tmdb.org/t/p/original"
DEFAULT_LANGUAGE = "zh-CN" # 刮削文案语言,可按需改
FALLBACK_LANGUAGE = "en-US"
class Config:
"""从 config.json / 环境变量读取配置。"""
def __init__(self, path=None):
self.tmdb_api_key = os.environ.get("TMDB_API_KEY", "")
self.language = DEFAULT_LANGUAGE
self.mock = False
self.timeout = 20
if path and os.path.isfile(path):
data = json.load(open(path, encoding="utf-8"))
self.tmdb_api_key = data.get("tmdb_api_key", self.tmdb_api_key)
self.language = data.get("language", self.language)
self.mock = data.get("mock", self.mock)
self.timeout = data.get("timeout", self.timeout)
# ---------------------------------------------------------------------------
# 文件名解析
# ---------------------------------------------------------------------------
def clean_ext(name):
return os.path.splitext(name)[1].lower()
def parse_media_name(name):
"""从单个文件名或目录名解析媒体信息。
返回 dict:
kind: "movie" | "tv"
title: 标题(尽量去除年份/季集标记)
year: 年份(int) 或 None
season/episode: 剧集时存在
"""
base = os.path.basename(name)
base = os.path.splitext(base)[0]
info = {"kind": "movie", "title": base, "year": None,
"season": None, "episode": None}
# 剧集标记:S01E02 / s1e2 / 第01集 / E01 / 第 1 季 第 2 集
m = re.search(r"[Ss](\d{1,2})[Ee](\d{1,3})", base) # SxxExx
if m:
info["kind"] = "tv"
info["season"] = int(m.group(1))
info["episode"] = int(m.group(2))
else:
m = re.search(r"第\s*(\d{1,2})\s*[集話话]", base) # 第01集
if m:
info["kind"] = "tv"
info["season"] = 1
info["episode"] = int(m.group(1))
else:
m2 = re.search(r"[Ee](\d{1,3})", base) # E01
if m2:
info["kind"] = "tv"
info["season"] = 1
info["episode"] = int(m2.group(1))
# 年份
m = re.search(r"\((\d{4})\)", base) or re.search(r"(\b19\d{2}\b|\b20\d{2}\b)", base)
if m:
info["year"] = int(m.group(1))
base = base.replace(f"({m.group(1)})", "")
# 去除季集标记,得到标题
base = re.sub(r"[Ss]\d{1,2}[Ee]\d{1,3}", "", base)
base = re.sub(r"第\s*\d{1,2}\s*[集話话]", "", base)
base = re.sub(r"[Ee]\d{1,3}", "", base)
base = re.sub(r"\((\d{4})\)", "", base)
base = re.sub(r"(\b19\d{2}\b|\b20\d{2}\b)", "", base)
base = re.sub(r"[\s._\-]+", " ", base).strip()
info["title"] = base if base else info["title"]
return info
# ---------------------------------------------------------------------------
# TMDB 客户端
# ---------------------------------------------------------------------------
class TMDBApi:
def __init__(self, config):
self.cfg = config
self.sess = requests.Session()
self.sess.headers.update({
"Authorization": f"Bearer {config.tmdb_api_key}",
"Content-Type": "application/json;charset=utf-8",
})
self.base = "https://api.themoviedb.org/3"
def _get(self, path, params):
if not self.cfg.tmdb_api_key:
raise RuntimeError("未配置 TMDB API Key(config.json 或环境变量 TMDB_API_KEY)")
r = self.sess.get(f"{self.base}/{path}", params=params, timeout=self.cfg.timeout)
r.raise_for_status()
return r.json()
def search(self, kind, title, year=None):
path = "search/movie" if kind == "movie" else "search/tv"
params = {"query": title, "language": self.cfg.language}
if year:
params["year" if kind == "movie" else "first_air_date_year"] = year
data = self._get(path, params)
results = data.get("results") or []
# 优先标题精确匹配 + 年份匹配
exact = [r for r in results
if r.get("title" if kind == "movie" else "name", "").lower()
== title.lower()]
if year and exact:
exact = [r for r in exact
if str(r.get("release_date" if kind == "movie" else "first_air_date", "") or "")
.startswith(str(year))]
if exact:
return exact[0]
if results:
return results[0]
return None
def get_details(self, kind, tmdb_id):
path = f"movie/{tmdb_id}" if kind == "movie" else f"tv/{tmdb_id}"
return self._get(path, {"language": self.cfg.language})
def get_credits(self, kind, tmdb_id):
"""电影 cast/crew;剧集 cast。用于 nfo 的演员、导演、制片厂字段。"""
path = f"movie/{tmdb_id}/credits" if kind == "movie" else f"tv/{tmdb_id}/credits"
return self._get(path, {"language": self.cfg.language})
def image_url(self, path, size="w500"):
if not path:
return None
base = TMDB_IMAGE_BASE if size == "w500" else TMDB_IMAGE_ORIG
return f"{base}{path}"
# ---------------------------------------------------------------------------
# nfo 生成
# ---------------------------------------------------------------------------
def _esc(s):
if s is None:
return ""
return str(s).replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
def _txt(node, tag, value):
if value is not None and str(value).strip():
ET.SubElement(node, tag).text = str(value).strip()
def build_movie_nfo(meta):
"""meta: TMDB movie details 的整理字段。返回 movie.nfo XML 字符串。"""
root = ET.Element("movie")
_txt(root, "title", meta.get("title"))
_txt(root, "originaltitle", meta.get("original_title"))
_txt(root, "year", meta.get("year"))
_txt(root, "rating", meta.get("vote_average"))
_txt(root, "votes", meta.get("vote_count"))
_txt(root, "runtime", meta.get("runtime"))
_txt(root, "plot", meta.get("overview"))
_txt(root, "tagline", meta.get("tagline"))
_txt(root, "premiered", meta.get("release_date"))
_txt(root, "release", meta.get("release_date"))
for g in meta.get("genres", []) or []:
_txt(root, "genre", g)
for d in meta.get("directors", []) or []:
_txt(root, "director", d)
for s in meta.get("studios", []) or []:
_txt(root, "studio", s)
_txt(root, "mpaa", meta.get("certification"))
if meta.get("tmdb_id"):
ET.SubElement(root, "uniqueid", attrib={"type": "tmdb"}).text = str(meta["tmdb_id"])
if meta.get("imdb_id"):
ET.SubElement(root, "uniqueid", attrib={"type": "imdb"}).text = str(meta["imdb_id"])
if meta.get("poster_path"):
ET.SubElement(root, "thumb").text = TMDB_IMAGE_BASE + meta["poster_path"]
if meta.get("fanart_path"):
f = ET.SubElement(root, "fanart")
ET.SubElement(f, "thumb").text = TMDB_IMAGE_ORIG + meta["fanart_path"]
for a in meta.get("cast", []) or []:
ac = ET.SubElement(root, "actor")
_txt(ac, "name", a.get("name"))
_txt(ac, "role", a.get("role"))
if a.get("thumb"):
_txt(ac, "thumb", TMDB_IMAGE_BASE + a["thumb"])
return '<?xml version="1.0" encoding="UTF-8"?>\n' + ET.tostring(root, encoding="unicode")
def build_tvshow_nfo(meta):
root = ET.Element("tvshow")
_txt(root, "title", meta.get("name"))
_txt(root, "originaltitle", meta.get("original_name"))
_txt(root, "year", meta.get("year"))
_txt(root, "rating", meta.get("vote_average"))
_txt(root, "votes", meta.get("vote_count"))
_txt(root, "plot", meta.get("overview"))
_txt(root, "premiered", meta.get("first_air_date"))
_txt(root, "status", meta.get("status"))
for g in meta.get("genres", []) or []:
_txt(root, "genre", g)
for s in meta.get("studios", []) or []:
_txt(root, "studio", s)
if meta.get("tmdb_id"):
ET.SubElement(root, "uniqueid", attrib={"type": "tmdb"}).text = str(meta["tmdb_id"])
if meta.get("imdb_id"):
ET.SubElement(root, "uniqueid", attrib={"type": "imdb"}).text = str(meta["imdb_id"])
if meta.get("poster_path"):
ET.SubElement(root, "thumb").text = TMDB_IMAGE_BASE + meta["poster_path"]
for a in meta.get("cast", []) or []:
ac = ET.SubElement(root, "actor")
_txt(ac, "name", a.get("name"))
_txt(ac, "role", a.get("role"))
if a.get("thumb"):
_txt(ac, "thumb", TMDB_IMAGE_BASE + a["thumb"])
return '<?xml version="1.0" encoding="UTF-8"?>\n' + ET.tostring(root, encoding="unicode")
def build_episode_nfo(meta):
root = ET.Element("episodedetails")
_txt(root, "title", meta.get("name"))
_txt(root, "season", meta.get("season_number"))
_txt(root, "episode", meta.get("episode_number"))
_txt(root, "plot", meta.get("overview"))
_txt(root, "aired", meta.get("air_date"))
_txt(root, "rating", meta.get("vote_average"))
if meta.get("still_path"):
ET.SubElement(root, "thumb").text = TMDB_IMAGE_BASE + meta["still_path"]
return '<?xml version="1.0" encoding="UTF-8"?>\n' + ET.tostring(root, encoding="unicode")
# ---------------------------------------------------------------------------
# 刮削器
# ---------------------------------------------------------------------------
class Scraper:
def __init__(self, config, dest, source_root=None, dry_run=False, log=None):
self.cfg = config
self.dest = os.path.abspath(dest)
self.source_root = os.path.abspath(source_root) if source_root else None
self.dry_run = dry_run
self.log = log or (lambda msg: print(msg))
self.api = None if config.mock else TMDBApi(config)
def logi(self, msg):
ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.log(f"[{ts}] {msg}")
# ---- 复制媒体到成品目录 ----
def _relative(self, path):
"""以源根为基准计算相对路径;不在源根下则退回 basename。"""
path = os.path.abspath(path)
if self.source_root and os.path.commonpath([path, self.source_root]) == self.source_root:
return os.path.relpath(path, self.source_root)
return os.path.basename(path)
def _copy_media(self, src_path, rel_src):
"""把源媒体文件/目录复制到成品目录,返回成品里的完整路径。
安全保护:目标路径绝不允许等于源路径,否则直接报错,绝不误删源。
"""
dst = os.path.join(self.dest, rel_src)
if os.path.abspath(dst) == os.path.abspath(src_path):
raise RuntimeError(f"目标路径与源路径相同,已终止以防误删: {src_path}")
if self.dry_run:
self.logi(f"[DRY] 将复制 {src_path} -> {dst}")
return dst
os.makedirs(os.path.dirname(dst), exist_ok=True)
if os.path.isdir(src_path):
if os.path.exists(dst):
shutil.rmtree(dst)
shutil.copytree(src_path, dst)
else:
shutil.copy2(src_path, dst)
return dst
# ---- 电影刮削(单文件或电影目录)----
def scrape_movie(self, src):
info = parse_media_name(src)
rel = self._relative(src)
dst = self._copy_media(src, rel)
base = os.path.basename(dst)
base_noext = os.path.splitext(base)[0]
if self.cfg.mock:
meta = self._mock_movie_meta(info)
else:
found = self.api.search("movie", info["title"], info.get("year"))
if not found:
raise RuntimeError(f"TMDB 未匹配到电影: {info['title']}")
details = self.api.get_details("movie", found["id"])
try:
credits = self.api.get_credits("movie", found["id"])
except Exception:
credits = {}
meta = self._shape_movie_meta(details, credits)
if self.dry_run:
self.logi(f"[DRY] 电影 {base} 匹配 TMDB id={meta.get('tmdb_id')} "
f"《{meta.get('title')}》({meta.get('year')})")
return
media_file = self._find_media_file(dst)
out_dir = os.path.dirname(media_file) if media_file else dst
nfo_name = os.path.splitext(os.path.basename(media_file))[0] if media_file else base_noext
nfo_path = os.path.join(out_dir, nfo_name + ".nfo")
with open(nfo_path, "w", encoding="utf-8") as f:
f.write(build_movie_nfo(meta))
self.logi(f"生成 {nfo_path}")
self._download_art(meta, out_dir, nfo_name, base_noext)
# ---- 剧集刮削(剧集目录)----
def scrape_tv(self, src):
info = parse_media_name(src)
rel = self._relative(src)
dst = self._copy_media(src, rel)
if self.cfg.mock:
meta = self._mock_tv_meta(info)
else:
found = self.api.search("tv", info["title"], info.get("year"))
if not found:
raise RuntimeError(f"TMDB 未匹配到剧集: {info['title']}")
details = self.api.get_details("tv", found["id"])
try:
credits = self.api.get_credits("tv", found["id"])
except Exception:
credits = {}
meta = self._shape_tv_meta(details, credits)
if self.dry_run:
self.logi(f"[DRY] 剧集 {os.path.basename(src)} 匹配 TMDB id={meta.get('tmdb_id')} "
f"《{meta.get('name')}》")
return
# 剧集目录:在目录根生成 tvshow.nfo + poster;对每个视频文件生成 {文件}.nfo
root_dir = dst if os.path.isdir(dst) else os.path.dirname(dst)
with open(os.path.join(root_dir, "tvshow.nfo"), "w", encoding="utf-8") as f:
f.write(build_tvshow_nfo(meta))
self.logi(f"生成 {root_dir}/tvshow.nfo")
self._download_art(meta, root_dir, "poster", "poster")
for vf in self._find_video_files(root_dir):
if info.get("season") is not None and info.get("episode") is not None:
ep_meta = self._episode_meta(meta, info["season"], info["episode"])
else:
ep_meta = self._episode_meta_from_filename(vf)
vbase = os.path.splitext(os.path.basename(vf))[0]
with open(os.path.join(root_dir, vbase + ".nfo"), "w", encoding="utf-8") as f:
f.write(build_episode_nfo(ep_meta))
self.logi(f"生成 {os.path.join(root_dir, vbase + '.nfo')}")
# ---- 工具方法 ----
def _find_media_file(self, path):
if os.path.isfile(path):
return path
for root, _, files in os.walk(path):
for fn in sorted(files):
if clean_ext(fn) in VIDEO_EXTS:
return os.path.join(root, fn)
return None
def _find_video_files(self, root):
out = []
for root2, _, files in os.walk(root):
for fn in sorted(files):
if clean_ext(fn) in VIDEO_EXTS:
out.append(os.path.join(root2, fn))
return out
def _download_art(self, meta, out_dir, prefix, poster_prefix=None):
"""下载海报/背景图(Kodi/Emby 兼容命名)。"""
poster_prefix = poster_prefix or prefix
poster = meta.get("poster_path")
fanart = meta.get("fanart_path")
if poster:
url = TMDB_IMAGE_BASE + poster
self._dl(url, os.path.join(out_dir, f"{poster_prefix}-poster.jpg"))
if fanart:
url = TMDB_IMAGE_ORIG + fanart
self._dl(url, os.path.join(out_dir, f"{prefix}-fanart.jpg"))
def _dl(self, url, out_path):
if self.dry_run or self.cfg.mock:
self.logi(f"[DRY/MOCK] 下载图片 {url} -> {out_path}")
return
try:
r = requests.get(url, timeout=self.cfg.timeout)
r.raise_for_status()
with open(out_path, "wb") as f:
f.write(r.content)
self.logi(f"下载图片 {out_path}")
except Exception as e:
self.logi(f"下载图片失败 {url}: {e}")
# ---- meta 整形 ----
def _shape_movie_meta(self, d, credits=None):
credits = credits or {}
return {
"title": d.get("title") or d.get("original_title"),
"original_title": d.get("original_title"),
"year": (d.get("release_date") or "")[:4],
"vote_average": d.get("vote_average"),
"vote_count": d.get("vote_count"),
"runtime": d.get("runtime"),
"overview": d.get("overview"),
"tagline": d.get("tagline"),
"release_date": d.get("release_date"),
"genres": [g.get("name") for g in (d.get("genres") or [])],
"certification": None,
"tmdb_id": d.get("id"),
"imdb_id": d.get("imdb_id"),
"poster_path": d.get("poster_path"),
"fanart_path": (d.get("backdrop_path")),
"directors": [c.get("name") for c in (credits.get("crew") or [])
if c.get("job") == "Director"][:3],
"studios": [c.get("name") for c in (d.get("production_companies") or [])],
"cast": [{"name": c.get("name"), "role": c.get("character"),
"thumb": c.get("profile_path")}
for c in (credits.get("cast") or [])[:12]],
}
def _shape_tv_meta(self, d, credits=None):
credits = credits or {}
return {
"name": d.get("name") or d.get("original_name"),
"original_name": d.get("original_name"),
"year": (d.get("first_air_date") or "")[:4],
"vote_average": d.get("vote_average"),
"vote_count": d.get("vote_count"),
"overview": d.get("overview"),
"first_air_date": d.get("first_air_date"),
"status": d.get("status"),
"genres": [g.get("name") for g in (d.get("genres") or [])],
"tmdb_id": d.get("id"),
"imdb_id": None,
"poster_path": d.get("poster_path"),
"fanart_path": (d.get("backdrop_path")),
"studios": [c.get("name") for c in (d.get("production_companies") or [])],
"cast": [{"name": c.get("name"), "role": c.get("character"),
"thumb": c.get("profile_path")}
for c in (credits.get("cast") or [])[:12]],
}
def _episode_meta(self, tv_meta, season, episode):
return {
"name": f"第 {episode} 集",
"season_number": season,
"episode_number": episode,
"overview": None,
"air_date": None,
"vote_average": None,
"still_path": None,
}
def _episode_meta_from_filename(self, vf):
info = parse_media_name(vf)
return self._episode_meta({}, info.get("season") or 1, info.get("episode") or 1)
# ---- mock 元数据(无 Key 时验证管线用)----
def _mock_movie_meta(self, info):
return {
"title": info["title"], "original_title": info["title"],
"year": info.get("year") or 2024, "vote_average": 8.5,
"vote_count": 100, "runtime": 120, "overview": f"(MOCK)电影《{info['title']}》简介",
"tagline": "", "release_date": f"{info.get('year') or 2024}-01-01",
"genres": ["剧情"], "certification": None,
"tmdb_id": 1000, "imdb_id": "tt0000000",
"poster_path": None, "fanart_path": None,
}
def _mock_tv_meta(self, info):
return {
"name": info["title"], "original_name": info["title"],
"year": info.get("year") or 2024, "vote_average": 8.8,
"vote_count": 200, "overview": f"(MOCK)剧集《{info['title']}》简介",
"first_air_date": f"{info.get('year') or 2024}-01-01",
"status": "Returning Series", "genres": ["剧情"],
"tmdb_id": 2000, "imdb_id": None,
"poster_path": None, "fanart_path": None,
}
# ---------------------------------------------------------------------------
# 命令行入口
# ---------------------------------------------------------------------------
def scan_and_scrape(source, dest, scraper):
"""处理一个源路径:文件直接刮,目录则识别为电影/剧集目录。"""
source = os.path.abspath(source)
if os.path.isfile(source):
info = parse_media_name(source)
if info["kind"] == "tv":
scraper.scrape_tv(source)
else:
scraper.scrape_movie(source)
elif os.path.isdir(source):
# 判断是剧集目录(含 SxxExx / 季结构)还是电影目录
vids = [f for f in _walk_files(source) if clean_ext(f) in VIDEO_EXTS]
tv_mark = any(re.search(r"[Ss]\d{1,2}[Ee]\d{1,3}|第\s*\d{1,2}\s*[集話话]", f)
for f in _walk_files(source))
subdir_seasons = any(re.match(r"[Ss]eason\s*\d+|第\s*\d+\s*季", d)
for d in os.listdir(source))
if tv_mark or subdir_seasons or len(vids) > 1:
scraper.scrape_tv(source)
else:
scraper.scrape_movie(source)
else:
raise RuntimeError(f"源路径不存在: {source}")
def _walk_files(root):
out = []
for r, _, files in os.walk(root):
for fn in files:
out.append(os.path.join(r, fn))
return out
def main():
ap = argparse.ArgumentParser(description="自研媒体刮削器(TMDB)")
ap.add_argument("--source", required=True, help="媒体文件/目录(可重复,或 --recurse 扫整目录)")
ap.add_argument("--dest", required=True, help="成品落库目录")
ap.add_argument("--config", default=None, help="config.json 路径")
ap.add_argument("--mock", action="store_true", help="无 Key 时用模拟元数据跑通管线")
ap.add_argument("--dry-run", action="store_true", help="只打印计划不落盘")
ap.add_argument("--recurse", action="store_true", help="递归处理 --source 下所有新媒体单元")
ap.add_argument("--log", default=None, help="日志文件路径(默认 stdout)")
args = ap.parse_args()
cfg = Config(args.config)
if args.mock:
cfg.mock = True
log = (lambda msg: open(args.log, "a", encoding="utf-8").write(msg + "\n")
and print(msg)) if args.log else print
if args.recurse:
source_root = os.path.abspath(args.source)
else:
source_root = os.path.abspath(os.path.dirname(args.source))
scraper = Scraper(cfg, args.dest, source_root=source_root,
dry_run=args.dry_run, log=log)
os.makedirs(args.dest, exist_ok=True)
if args.recurse:
targets = _walk_files(args.source)
# 只处理视频文件,交给 parse 判定
targets = [t for t in targets if clean_ext(t) in VIDEO_EXTS]
else:
targets = [args.source]
for t in targets:
try:
scan_and_scrape(t, args.dest, scraper)
except Exception as e:
scraper.logi(f"跳过 {t}: {e}")
scraper.logi("全部处理完成")
if __name__ == "__main__":
main()
+23
View File
@@ -0,0 +1,23 @@
# =====================================================================
# nas-tools (NAStool) 部署配置 —— 飞牛 fnOS Docker
# 用途:监听「清理后媒体目录」→ 自动识别并刮削 → 复制落库到「成品媒体库」
# 用法:飞牛 → 应用中心/Docker → 添加项目(Compose) → 粘贴本文件 → 启动
# 说明:把下面三个 /vol1/... 路径改成你飞牛上的真实路径再粘贴
# =====================================================================
services:
nas-tools:
image: jxxghp/nas-tools:latest # 也可换 hsuyelin/nas-tools:latest 或 diluka/nas-tools:2.9.1
container_name: nas-tools
restart: unless-stopped
ports:
- "3000:3000" # Web 管理界面
volumes:
- /vol1/docker/nas-tools/config:/config # 配置持久化(必须)
- /vol1/media/cleaned:/media/source # 【你的清理后媒体目录】(media_final.py 的输出)
- /vol1/media/library:/media/library # 【成品媒体库】(刮削+复制后的落库目录)
environment:
- PUID=0
- PGID=0
- TZ=Asia/Shanghai
- NASTOOL_AUTO_UPDATE=false # 关闭自动更新,避免拉不动 github
- NASTOOL_CN_UPDATE=true # 使用国内源加速依赖安装
+37
View File
@@ -0,0 +1,37 @@
# nas-tools 部署与配置说明(飞牛 fnOS)
目标流程:`media_final.py` 清理后的媒体目录 → nas-tools 自动监听 → 刮削 → **复制**落库到成品媒体库。
## 一、部署(飞牛 Docker)
1. 飞牛后台 → **应用中心 → Docker**(或直接 Docker 应用)→ 新建项目 / Compose。
2. 粘贴 `nastools-docker-compose.yml` 内容,把 `/vol1/media/cleaned`、`/vol1/media/library`、`/vol1/docker/nas-tools/config` 三处改成你飞牛上的真实路径。
3. 保存并启动,等待镜像拉取完成。
4. 浏览器打开 `http://<飞牛IP>:3000`,默认账号 `admin` / 密码 `password`(首次登录后改掉)。
> 镜像拉不动时:确认环境变量 `NASTOOL_AUTO_UPDATE=false`、`NASTOOL_CN_UPDATE=true` 已设置。
## 二、Web 里必须配的点
| 配置项 | 位置 | 说明 |
|---|---|---|
| **TMDB API Key** | 设置 → 媒体库 | 必填,TMDB 官网免费申请(themoviedb.org/settings/api)。没有它无法刮削海报/简介 |
| **目录同步:复制模式** | 设置 → 目录同步 | 添加「源目录 = /media/source、目的目录 = /media/library」,传输方式选**复制**(对应你定的落库方式) |
| **媒体库识别** | 设置 → 媒体库 | 电影/剧集命名规则保持默认即可,识别率高 |
| **联动 Jellyfin/Emby** | 设置 → 媒体服务器 | 可选。填入 Jellyfin/Emby 地址和 API Key,nas-tools 刮削完会通知它刷新海报墙 |
## 三、关键行为确认
- nas-tools **默认会监控源目录**,文件新增/变更后自动识别媒体真实名称 → 刮削 → 复制到成品目录。
- 「复制」= 源目录保留,成品目录得到一份完整的刮削后副本(含 nfo、海报、背景图)。
- 如果你想省空间、源和成品在同一文件系统,可把「复制」换成「硬链接」——效果等同但几乎不占额外空间(自愿切换)。
## 四、验证
- 往 `/vol1/media/cleaned` 丢一个清理后的影片,几秒后到 `/vol1/media/library` 检查是否出现了刮削好的副本(含 `.nfo`、`-poster.jpg`)。
- 若配合 Jellyfin/Emby,刷新后应出现海报墙。
## 常见问题
- **海报刮不出来**:多半是 TMDB Key 没配,或无法访问 TMDB(国内网络需在媒体库设置里配代理/TMDB 备用源)。
- **没自动触发**:确认源目录路径和目录同步里的监控路径一致;看容器日志 `docker logs nas-tools`。
Binary file not shown.
+124
View File
@@ -0,0 +1,124 @@
import os
import re
from datetime import datetime
# ====================== 【配置区】 ======================
MEDIA_FOLDER = "/Volumes/JoyDisk/myMedia/olstrms/电影/未分类/2024"
DRY_RUN = True # True=预览不修改;False=实际重命名
SKIP_PROCESSED = False
LOG_FILE = "./rename_log.txt"
# 清洗规则
RULES = [
(r"^[A-Za-z] ", ""), #1.移除开头单个字母+空格
(r"\[.*?\]", ""), #2.移除英文方括号及内部内容
(r"【.*?】", ""), #3.移除中文【】及内部内容
(r"丨", ""), #清除汉字竖线 丨
(r"\b(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|中英双语|双语字幕)\b", "", re.IGNORECASE),
(r"\.+", ""), #删除连续的点
(r"\s", ""), #删除全部空格
# 保留:汉字、半角英文、数字、半角 () . : + -
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+-]", ""),
]
# 加入strm
ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm"}
# =======================================================
def clean_filename(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
# 全角转半角
def full2half(s):
result = []
for char in s:
code = ord(char)
if code == 12288:
char = chr(32)
elif 65281 <= code <= 65374:
char = chr(code - 65248)
result.append(char)
return "".join(result)
name_no_ext = full2half(name_no_ext)
for item in RULES:
if len(item) == 3:
pat, repl, flag = item
name_no_ext = re.sub(pat, repl, name_no_ext, flags=flag)
else:
pat, repl = item
name_no_ext = re.sub(pat, repl, name_no_ext)
name_no_ext = name_no_ext.strip()
return name_no_ext + ext
def write_log(msg: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
# 增加flush,强制写入磁盘,解决日志文件不更新
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
if __name__ == "__main__":
# 每次运行前清空日志文件
with open(LOG_FILE, "w", encoding="utf-8") as f:
f.flush()
write_log("===== 文件名+文件夹清洗(移除开头A 中文片名前缀) =====")
write_log(f"根目录:{MEDIA_FOLDER}")
write_log(f"预览模式 DRY_RUN = {DRY_RUN}")
file_rename_list = []
dir_rename_list = []
total_scan_dirs = 0
total_all_files = 0 # 全部扫描到的文件(所有后缀)
total_media_files = 0 # 媒体文件(ALLOW_EXT后缀)
for root, dirs, files in os.walk(MEDIA_FOLDER, topdown=False):
total_scan_dirs += 1
for fname in files:
total_all_files +=1 # 任何文件都计入总扫描文件
ext = os.path.splitext(fname)[1].lower()
if ext in ALLOW_EXT:
total_media_files += 1
# 调试:打印所有扫描到的媒体文件(无论是否修改)
write_log(f"[扫描媒体] {fname}")
new_name = clean_filename(fname)
if new_name != fname:
if SKIP_PROCESSED and re.search(r"\(\d{4}\)", new_name):
write_log(f"【跳过文件】{fname},检测年份括号")
continue
old_path = os.path.join(root, fname)
new_path = os.path.join(root, new_name)
file_rename_list.append((old_path, new_path))
write_log(f"待修改文件-> {fname} → {new_name}")
# 处理文件夹
for dname in dirs:
new_name = clean_filename(dname)
if new_name != dname:
if SKIP_PROCESSED and re.search(r"\(\d{4}\)", new_name):
write_log(f"【跳过文件夹】{dname},检测年份括号")
continue
old_path = os.path.join(root, dname)
new_path = os.path.join(root, new_name)
dir_rename_list.append((old_path, new_name))
write_log(f"待修改文件夹-> {dname} → {new_name}")
# ========== 执行阶段 ==========
if not DRY_RUN:
# 先文件
for old, new in file_rename_list:
try:
os.rename(old, new)
except Exception as e:
write_log(f"【文件重命名失败】{old} -> {new} | 错误:{e}")
# 后文件夹
for old, new in dir_rename_list:
try:
os.rename(old, new)
except Exception as e:
write_log(f"【文件夹重命名失败】{old} -> {new} | 错误:{e}")
# 最终汇总输出
write_log(f"任务完成,总扫描目录:{total_scan_dirs},待修改文件夹:{len(dir_rename_list)}")
write_log(f"总扫描文件:{total_all_files},媒体文件:{total_media_files},待修改文件:{len(file_rename_list)}")
write_log("============================================================")
+100
View File
@@ -0,0 +1,100 @@
import os
import re
from datetime import datetime
# ====================== 【配置区,请修改】 ======================
MEDIA_FOLDER = "/Volumes/JoyDisk/myMedia/olstrms/电影/未分类/2025" # Mac挂载NAS路径
# MEDIA_FOLDER = "/media/movies" # 飞牛容器内运行用这个
DRY_RUN = True # True=预览,不修改;确认无误改为False执行改名
SKIP_PROCESSED = False # True=跳过已处理(文件名含(20xx)年份)
LOG_FILE = "./rename_log.txt"
# =================================================================
# 清洗正则规则(文件夹、文件共用一套)
RULES = [
(r"^[A-Za-z] ", ""), # 【新增】移除开头单个英文字母+空格:A 流浪地球 → 流浪地球
(r"(?<=[a-zA-Z0-9])\.(?=[a-zA-Z0-9])", " "), # Dune.Part → Dune Part
(r"\[.*?\]", ""), # 删除全部 [xxx] 方括号内容
(r"\s*(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD)\b", ""),
(r"\.+", " "), # 剩下连续多个点替换成空格
]
# 支持的文件后缀
ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub"}
def clean_name(name: str) -> str:
"""统一清洗函数,文件夹名、文件名共用"""
name_no_ext, ext = os.path.splitext(name)
# 处理 A . B . C 这种「字母 空格 . 空格 字母」
while re.search(r"(\w) \. (\w)", name_no_ext):
name_no_ext = re.sub(r"(\w) \. (\w)", r"\1\2", name_no_ext)
# 执行所有正则替换规则
for pattern, repl in RULES:
name_no_ext = re.sub(pattern, repl, name_no_ext)
# 合并连续空格,去除首尾空格
name_no_ext = re.sub(r"\s+", " ", name_no_ext).strip()
return name_no_ext + ext
def write_log(msg: str):
time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{time_str}] {msg}"
print(line)
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + "\n")
if __name__ == "__main__":
write_log("===== 文件名+文件夹清洗(移除开头A 中文片名前缀) =====")
write_log(f"根目录:{MEDIA_FOLDER}")
write_log(f"预览模式 DRY_RUN = {DRY_RUN}")
dir_rename_list = []
file_rename_list = []
# 遍历收集(自底向上,防止目录路径错乱)
for root, dirs, files in os.walk(MEDIA_FOLDER, topdown=False):
# 文件
for fname in files:
ext = os.path.splitext(fname)[1].lower()
if ext not in ALLOW_EXT:
continue
new_name = clean_name(fname)
if new_name != fname:
if SKIP_PROCESSED and re.search(r"\(\d{4}\)", new_name):
write_log(f"跳过文件(疑似已处理): {fname}")
continue
old_path = os.path.join(root, fname)
new_path = os.path.join(root, new_name)
file_rename_list.append((old_path, new_path))
# 文件夹
for dname in dirs:
new_name = clean_name(dname)
if new_name != dname:
if SKIP_PROCESSED and re.search(r"\(\d{4}\)", new_name):
write_log(f"跳过文件夹(疑似已处理): {dname}")
continue
old_path = os.path.join(root, dname)
new_path = os.path.join(root, new_name)
dir_rename_list.append((old_path, new_name))
# 先改文件夹,再改文件
dir_count = 0
for old, new in dir_rename_list:
write_log(f"【文件夹】{os.path.basename(old)} → {os.path.basename(new)}")
dir_count +=1
if not DRY_RUN:
os.rename(old, new)
file_count =0
for old, new in file_rename_list:
write_log(f"【文件】{os.path.basename(old)} → {os.path.basename(new)}")
file_count +=1
if not DRY_RUN:
os.rename(old, new)
write_log(f"任务完成,待修改文件夹:{dir_count},待修改文件:{file_count}")
write_log("="*60 + "\n")
+92
View File
@@ -0,0 +1,92 @@
import os
import re
from datetime import datetime
# ====================== 【配置区,请修改】 ======================
MEDIA_FOLDER = "/Volumes/JoyDisk/myMedia/olstrms/电影/未分类/2024"
DRY_RUN = True # True预览不修改;确认后改为False
SKIP_PROCESSED = False
LOG_FILE = "./rename_log.txt"
# =================================================================
RULES = [
(r"^[A-Za-z] ", ""), #1.开头单个字母+空格
(r"\[.*?\]", ""), #2.英文方括号
(r"【.*?】", ""), #2.中文方括号
(r"\b(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|中英双语)\b", "", re.IGNORECASE),
(r"\.+", ""), #4.连续多点删除
(r"\s", ""), #5.删除全部空格
]
ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub"}
def clean_name(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
for item in RULES:
if len(item) == 3:
pattern, repl, flag = item
name_no_ext = re.sub(pattern, repl, name_no_ext, flags=flag)
else:
pattern, repl = item
name_no_ext = re.sub(pattern, repl, name_no_ext)
name_no_ext = re.sub(r"\s+", " ", name_no_ext).strip()
return name_no_ext + ext
def write_log(msg: str):
time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{time_str}] {msg}"
print(line)
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + "\n")
if __name__ == "__main__":
write_log("===== 文件名+文件夹清洗【递归处理全部下级子目录】 =====")
write_log(f"根目录:{MEDIA_FOLDER}")
write_log(f"预览模式 DRY_RUN = {DRY_RUN}")
write_log("说明:递归扫描全部子目录,先收集所有待改,执行时【先文件、后文件夹】避免路径失效")
dir_rename_list = []
file_rename_list = []
for root, dirs, files in os.walk(MEDIA_FOLDER, topdown=False):
write_log(f"\n==== 扫描目录:{root} | 当前目录文件数量:{len(files)} ====")
# 处理文件
for fname in files:
ext = os.path.splitext(fname)[1].lower()
if ext not in ALLOW_EXT:
continue
new_name = clean_name(fname)
if new_name != fname:
if SKIP_PROCESSED and re.search(r"\(\d{4}\)", new_name):
write_log(f"【跳过文件】{fname},检测年份括号")
continue
old_path = os.path.join(root, fname)
new_path = os.path.join(root, new_name)
file_rename_list.append((old_path, new_path))
write_log(f"【待改文件】{fname} → {new_name}")
# 处理文件夹
for dname in dirs:
new_name = clean_name(dname)
if new_name != dname:
if SKIP_PROCESSED and re.search(r"\(\d{4}\)", new_name):
write_log(f"【跳过文件夹】{dname},检测年份括号")
continue
old_path = os.path.join(root, dname)
new_path = os.path.join(root, new_name)
dir_rename_list.append((old_path, new_name))
write_log(f"【待改文件夹】{dname} → {new_name}")
# 执行顺序:先全部文件,再全部文件夹
file_count = 0
for old, new in file_rename_list:
write_log(f"【执行文件】{os.path.basename(old)} → {os.path.basename(new)}")
file_count +=1
if not DRY_RUN:
os.rename(old, new)
dir_count = 0
for old, new in dir_rename_list:
write_log(f"【执行文件夹】{os.path.basename(old)} → {os.path.basename(new)}")
dir_count +=1
if not DRY_RUN:
os.rename(old, new)
write_log(f"\n任务完成,待修改文件夹:{dir_count},待修改文件:{file_count}")
write_log("="*60 + "\n")
+326
View File
@@ -0,0 +1,326 @@
import os
import re
import argparse
import shutil
from datetime import datetime
LOG_FILE = "./rename_log.txt"
SKIP_DIRS = [
"@eaDir",
]
SKIP_FILES = {
".DS_Store",
"Thumbs.db",
"desktop.ini",
}
RULES_FILE = [
(r"^[A-Za-z] ", ""),
(r"\[.*?\]", ""),
(r"【.*?】", ""),
(r"丨", ""),
(r"(?<!\w)(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB-DL|HD|4K|中英双语|双语字幕|双语|中文|国语|粤语|台语|中英双字|国语中字|繁体中字|简体中字|简繁中字|双语中字|官方中字|特效中字|收藏不迷路|地址发布页|www6v123net|wwwdygangme)(?!\w)", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+\-]", ""),
]
RULES_DIR = [
(r"【.*?】", ""),
(r"^\[(.*)\]$", r"\1"),
(r"\]\[", ""),
(r"^[A-Za-z] ", ""),
(r"丨", ""),
(r"(?<!\w)(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB-DL|HD|4K|中英双语|双语字幕|双语|中文|国语|粤语|台语|中英双字|国语中字|繁体中字|简体中字|简繁中字|双语中字|官方中字|特效中字|收藏不迷路|地址发布页|www6v123net|wwwdygangme)(?!\w)", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"\(\)", ""),
(r"()", ""),
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+\-[\]]", ""),
]
FULL_ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm", ".flv", ".avi", ".wmv", ".ts", ".rmvb", ".webm", ".mp3", ".flac", ".aac", ".wav", ".ogg", ".m4a", ".wma", ".alac", ".rm", ".iso"}
STRM_ONLY_EXT = {".strm", ".srt", ".ass", ".sub"}
MAX_FILENAME_LEN = 245
def full2half(s):
result = []
for char in s:
code = ord(char)
if code == 12288:
char = chr(32)
elif 65281 <= code <= 65374:
char = chr(code - 65248)
result.append(char)
return "".join(result)
def clean_file_name(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
name_no_ext = full2half(name_no_ext)
orig_no_ext = name_no_ext
for item in RULES_FILE:
if len(item) == 3:
pat, repl, flag = item
name_no_ext = re.sub(pat, repl, name_no_ext, flags=flag)
else:
pat, repl = item
name_no_ext = re.sub(pat, repl, name_no_ext)
name_no_ext = name_no_ext.strip()
if len(name_no_ext) == 0:
name_no_ext = orig_no_ext.strip()
if len(name_no_ext) > MAX_FILENAME_LEN:
name_no_ext = name_no_ext[:MAX_FILENAME_LEN]
return name_no_ext + ext
def clean_dir_name(name: str) -> str:
name = full2half(name)
year_match = re.search(r"^\[(\d{4})\]$", name)
year_str = ""
if year_match:
year_str = year_match.group(1)
for item in RULES_DIR:
if len(item) == 3:
pat, repl, flag = item
name = re.sub(pat, repl, name, flags=flag)
else:
pat, repl = item
name = re.sub(pat, repl, name)
name = name.strip()
if year_str and name:
name = f"{name}({year_str})"
if len(name) > MAX_FILENAME_LEN:
name = name[:MAX_FILENAME_LEN]
return name
def assign_unique_names(item_list):
name_counter = dict()
out = []
for it in item_list:
cand = it["candidate"]
cnt = name_counter.get(cand, 0)
if cnt == 0:
final = cand
else:
final = f"{cand}({cnt})"
name_counter[cand] = cnt + 1
new_it = dict(it)
new_it["final_basename"] = final
out.append(new_it)
return out
def write_log(msg: str, log_file: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
try:
with open(log_file, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
except Exception:
print(f"[LOG-WRITE-FAILED] {line}")
def scan_full_tree(root_src, skip_dirs, skip_files, allow_ext):
"""
返回:
dir_nodes: list,每一个文件夹独立节点,包含:
src_abs: 当前文件夹完整源绝对路径
parent_src_abs: 父文件夹完整源绝对路径
orig_basename: 当前文件夹原始名字
candidate: 清洗后的候选basename
depth:目录深度,用于排序父先于子创建
file_nodes: list,媒体文件节点
root_src_abs:源根目录绝对路径
"""
dir_nodes = []
file_nodes = []
root_src_abs = os.path.abspath(root_src)
for src_root, dirs, files in os.walk(root_src, topdown=True):
remove_idx = []
for idx, dname in enumerate(dirs):
if dname in skip_dirs:
remove_idx.append(idx)
for idx in reversed(remove_idx):
del dirs[idx]
dirs[:] = dirs
src_root_abs = os.path.abspath(src_root)
parent_src_abs = os.path.dirname(src_root_abs)
depth = src_root_abs.count(os.sep)
basename = os.path.basename(src_root_abs)
# 每遍历到一个文件夹,就记录为一条dir_nodes(包含所有层级全部目录节点)
if src_root_abs != root_src_abs:
cand = clean_dir_name(basename)
if len(cand) == 0:
cand = basename
dir_nodes.append({
"src_abs": src_root_abs,
"parent_src_abs": parent_src_abs,
"orig_basename": basename,
"candidate": cand,
"depth": depth
})
#收集本目录下媒体文件
for fname in files:
if fname in skip_files:
continue
ext = os.path.splitext(fname)[1].lower()
if ext not in allow_ext:
continue
cand_f = clean_file_name(fname)
file_nodes.append({
"src_parent_abs": src_root_abs,
"orig_basename": fname,
"candidate": cand_f
})
return root_src_abs, dir_nodes, file_nodes
def group_by_parent_src_abs(item_list, key_name):
groups = dict()
for it in item_list:
k = it[key_name]
if k not in groups:
groups[k] = []
groups[k].append(it)
return groups
def main():
parser = argparse.ArgumentParser(description="镜像重命名【完整节点采集,严格1:1目录文件数量】")
parser.add_argument("--dir", required=True)
parser.add_argument("--output", required=True)
parser.add_argument("--apply", action="store_true")
parser.add_argument("--dry-run", action="store_true")
parser.add_argument("--strm-mode", action="store_true")
parser.add_argument("--log", default="./rename_log.txt")
args = parser.parse_args()
target_dir = args.dir
out_dir = args.output
log_path = args.log
DRY_RUN = True
if args.apply:
DRY_RUN = False
if args.dry_run:
DRY_RUN = True
if args.strm_mode:
ALLOW_EXT = STRM_ONLY_EXT
mode_info = "STRM模式【仅strm+字幕】"
else:
ALLOW_EXT = FULL_ALLOW_EXT
mode_info = "完整媒体模式"
if not os.path.isdir(target_dir):
print(f"源目录不存在 {target_dir}")
return
try:
with open(log_path, "w", encoding="utf-8") as f:
f.flush()
except Exception as e:
print(f"日志初始化警告 {e}")
write_log("===== 重构:全节点采集,源输出条目严格1:1 =====", log_path)
write_log(f"源目录:{target_dir}", log_path)
write_log(f"输出镜像目录:{out_dir}", log_path)
write_log(f"运行模式:{mode_info}", log_path)
write_log(f"预览模式 DRY_RUN = {DRY_RUN}", log_path)
stat = {
"src_dir_total":0,
"src_file_total":0,
"dir_success":0,
"dir_fail":0,
"file_success":0,
"file_fail":0
}
#阶段1:完整扫描,每一个文件夹都是独立节点
root_src_abs, dir_nodes, file_nodes = scan_full_tree(target_dir, SKIP_DIRS, SKIP_FILES, ALLOW_EXT)
stat["src_dir_total"] = len(dir_nodes)
stat["src_file_total"] = len(file_nodes)
write_log(f"【采集统计】源全部目录节点总数:{stat['src_dir_total']},源媒体文件总数:{stat['src_file_total']}", log_path)
#阶段2:按父源绝对路径分组,组内分配唯一basename,处理重名冲突
dir_groups = group_by_parent_src_abs(dir_nodes, "parent_src_abs")
dir_final = []
for p_abs, items in dir_groups.items():
assigned = assign_unique_names(items)
dir_final.extend(assigned)
file_groups = group_by_parent_src_abs(file_nodes, "src_parent_abs")
file_final = []
for p_abs, items in file_groups.items():
assigned = assign_unique_names(items)
file_final.extend(assigned)
#构建源绝对路径 → 输出basename映射
src_to_basename = {d["src_abs"]:d["final_basename"] for d in dir_final}
#构建源绝对路径 → 输出完整路径映射
src_to_out = dict()
src_to_out[root_src_abs] = out_dir
#按depth升序排序:浅目录优先,父一定先处理
dir_final_sorted = sorted(dir_final, key=lambda x:x["depth"])
for d in dir_final_sorted:
p_src = d["parent_src_abs"]
p_out = src_to_out[p_src]
child_out = os.path.join(p_out, d["final_basename"])
src_to_out[d["src_abs"]] = child_out
#打印目录日志
for it in dir_final:
orig = it["orig_basename"]
cand = it["candidate"]
final = it["final_basename"]
if cand != final:
write_log(f"【目录重名冲突】源目录[{orig}] 候选[{cand}] → 分配[{final}]", log_path)
else:
if orig != final:
write_log(f"待修改文件夹-> {orig} → {final}", log_path)
#打印文件日志
for it in file_final:
orig = it["orig_basename"]
cand = it["candidate"]
final = it["final_basename"]
if cand != final:
write_log(f"【文件重名冲突】源文件[{orig}] 候选[{cand}] → 分配[{final}]", log_path)
else:
if orig != final:
write_log(f"待修改文件-> {orig} → {final}", log_path)
#阶段3:按深度顺序创建目录,父目录优先
for d in dir_final_sorted:
full_out = src_to_out[d["src_abs"]]
if not DRY_RUN:
try:
os.makedirs(full_out, exist_ok=True)
stat["dir_success"] += 1
except OSError as e:
stat["dir_fail"] += 1
write_log(f"【目录创建失败】{full_out} | {e}", log_path)
#复制全部媒体文件
for it in file_final:
src_file = os.path.join(it["src_parent_abs"], it["orig_basename"])
dst_parent = src_to_out[it["src_parent_abs"]]
dst_file = os.path.join(dst_parent, it["final_basename"])
if not DRY_RUN:
try:
shutil.copy2(src_file, dst_file)
stat["file_success"] += 1
except OSError as e:
stat["file_fail"] +=1
write_log(f"【文件复制失败】src:{src_file} dst:{dst_file} | {e}", log_path)
write_log("----------任务统计汇总----------", log_path)
write_log(f"源采集目录节点总数量:{stat['src_dir_total']},源媒体文件总数量:{stat['src_file_total']}", log_path)
write_log(f"目录:成功 {stat['dir_success']},失败 {stat['dir_fail']}", log_path)
write_log(f"文件:成功 {stat['file_success']},失败 {stat['file_fail']}", log_path)
write_log("【校验】预期目录输出={},实际成功={}".format(stat["src_dir_total"], stat["dir_success"]), log_path)
write_log("【校验】预期文件输出={},实际成功={}".format(stat["src_file_total"], stat["file_success"]), log_path)
write_log("============================================================", log_path)
if __name__ == "__main__":
main()
+291
View File
@@ -0,0 +1,291 @@
import os
import re
import argparse
import shutil
from datetime import datetime
# ====================== 【配置区】 ======================
LOG_FILE = "./rename_log.txt"
# 需要完全跳过的目录名称(basename,大小写敏感)
SKIP_DIRS = [
"@eaDir", # 群晖隐含目录
]
# 需要跳过的隐含文件名称(完整文件名匹配)
SKIP_FILES = {
".DS_Store",
"Thumbs.db",
"desktop.ini",
}
# 文件清洗规则
RULES_FILE = [
(r"^[A-Za-z] ", ""),
(r"\[.*?\]", ""),
(r"【.*?】", ""),
(r"丨", ""),
(r"(?<!\w)(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB-DL|HD|4K|中英双语|双语字幕|双语|中文|国语|粤语|台语|中英双字|国语中字|繁体中字|简体中字|简繁中字|双语中字|官方中字|特效中字)(?!\w)", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+\-]", ""),
]
# 文件夹清洗规则
RULES_DIR = [
(r"【.*?】", ""), # 删除中文全角【】以及内部内容
(r"^\[(.*)\]$", r"\1"), # 整串被[]包裹,只剥外层
(r"\]\[", ""), # 清除中间碎片 ][
(r"^[A-Za-z] ", ""),
(r"丨", ""),
(r"(?<!\w)(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB-DL|HD|4K|中英双语|双语字幕|双语|中文|国语|粤语|台语|中英双字|国语中字|繁体中字|简体中字|简繁中字|双语中字|官方中字|特效中字)(?!\w)", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"\(\)", ""), # 清除英文空括号 ()
(r"()", ""), # 清除中文全角空括号 ()
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+\-[\]]", ""), # 允许文件夹内部保留[]
]
#完整全部媒体后缀(不带--strm-mode时使用)
FULL_ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm", ".flv", ".avi", ".wmv", ".ts", ".rmvb", ".webm", ".mp3", ".flac", ".aac", ".wav", ".ogg", ".m4a", ".wma", ".alac", ".rm", ".iso"}
# strm模式:仅strm+字幕
STRM_ONLY_EXT = {".strm", ".srt", ".ass", ".sub"}
MAX_FILENAME_LEN = 245 # mac文件名最大安全长度,预留扩展名位置
# =======================================================
def full2half(s):
result = []
for char in s:
code = ord(char)
if code == 12288:
char = chr(32)
elif 65281 <= code <= 65374:
char = chr(code - 65248)
result.append(char)
return "".join(result)
def clean_file_name(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
name_no_ext = full2half(name_no_ext)
for item in RULES_FILE:
if len(item) == 3:
pat, repl, flag = item
name_no_ext = re.sub(pat, repl, name_no_ext, flags=flag)
else:
pat, repl = item
name_no_ext = re.sub(pat, repl, name_no_ext)
name_no_ext = name_no_ext.strip()
if len(name_no_ext) > MAX_FILENAME_LEN:
name_no_ext = name_no_ext[:MAX_FILENAME_LEN]
return name_no_ext + ext
def clean_dir_name(name: str) -> str:
name = full2half(name)
year_match = re.search(r"^\[(\d{4})\]$", name)
year_str = ""
if year_match:
year_str = year_match.group(1)
for item in RULES_DIR:
if len(item) == 3:
pat, repl, flag = item
name = re.sub(pat, repl, name, flags=flag)
else:
pat, repl = item
name = re.sub(pat, repl, name)
name = name.strip()
if year_str and name:
name = f"{name}({year_str})"
if len(name) > MAX_FILENAME_LEN:
name = name[:MAX_FILENAME_LEN]
return name
def resolve_dir_path(parent_out_dir: str, want_dir_name: str, orig_src_basename: str, log_file: str):
"""目录冲突处理:父输出目录下,如果want_dir_name已存在,则追加(1)(2)..."""
candidate = want_dir_name
idx = 1
while True:
full_candidate_path = os.path.join(parent_out_dir, candidate)
if not os.path.exists(full_candidate_path):
return candidate
write_log(f"【目录重名冲突】源目录[{orig_src_basename}],输出目录已存在[{candidate}],自动变更为 {want_dir_name}({idx})", log_file)
candidate = f"{want_dir_name}({idx})"
idx += 1
def get_quality_tag(filename:str):
m = re.search(r"(?<!\w)(2160p|1080p|720p)(?!\w)", filename, re.IGNORECASE)
if m:
return m.group(1).lower()
return None
def resolve_conflict(dst_dir:str, base_name:str, ext:str, orig_filename:str):
candidate = base_name + ext
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
qual = get_quality_tag(orig_filename)
if qual:
candidate = f"{base_name}({qual}){ext}"
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
idx = 1
while True:
candidate = f"{base_name}({idx}){ext}"
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
idx +=1
def write_log(msg: str, log_file: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
try:
with open(log_file, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
except Exception:
#日志写入失败降级控制台输出,不打断程序
print(f"[LOG-WRITE-FAILED] {line}")
def main():
parser = argparse.ArgumentParser(description="媒体文件名镜像清洗工具,源目录只读,生成镜像副本")
parser.add_argument("--dir", required=True, help="原始源媒体根目录")
parser.add_argument("--output", required=True, help="输出镜像根目录")
parser.add_argument("--apply", action="store_true", help="加上此参数才执行真实复制生成镜像")
parser.add_argument("--dry-run", action="store_true", help="预览模式(默认就是预览,该参数为显式简写)")
parser.add_argument("--strm-mode", action="store_true", help="开启strm模式:仅处理 .strm .srt .ass .sub;过滤mkv/mp4等视频文件")
parser.add_argument("--log", default="./rename_log.txt", help="日志文件路径,默认 ./rename_log.txt")
args = parser.parse_args()
target_dir = args.dir
out_dir = args.output
log_path = args.log
DRY_RUN = True
if args.apply:
DRY_RUN = False
if args.dry_run:
DRY_RUN = True
if args.strm_mode:
ALLOW_EXT = STRM_ONLY_EXT
mode_info = "STRM模式【仅strm+字幕】"
else:
ALLOW_EXT = FULL_ALLOW_EXT
mode_info = "完整媒体模式【全部媒体后缀】"
if not os.path.isdir(target_dir):
print(f"错误:源目录不存在 -> {target_dir}")
return
#初始化日志
try:
with open(log_path, "w", encoding="utf-8") as f:
f.flush()
except Exception as e:
print(f"警告:无法初始化日志文件 {log_path},后续仅控制台输出日志,异常:{e}")
write_log("===== 文件名+文件夹清洗【目录重名冲突修复|全部标准短横杠参数】 =====", log_path)
write_log(f"源目录:{target_dir}", log_path)
write_log(f"输出镜像目录:{out_dir}", log_path)
write_log(f"运行模式:{mode_info}", log_path)
write_log(f"预览模式 DRY_RUN = {DRY_RUN}", log_path)
if SKIP_DIRS:
write_log(f"配置跳过目录名列表:{SKIP_DIRS}", log_path)
write_log(f"过滤隐含系统文件:{SKIP_FILES}", log_path)
stat = {
"scan_dir_total":0,
"scan_file_total":0,
"media_file_total":0,
"file_success":0,
"file_fail":0,
"dir_success":0,
"dir_fail":0
}
try:
for root, dirs, files in os.walk(target_dir, topdown=False):
#过滤跳过目录:@eaDir、配置SKIP_DIRS
remove_idx = []
for idx, dname in enumerate(dirs):
if dname in SKIP_DIRS:
remove_idx.append(idx)
for idx in reversed(remove_idx):
del dirs[idx]
stat["scan_dir_total"] += 1
rel = os.path.relpath(root, target_dir)
if rel == ".":
#根目录
dst_current_dir = out_dir
else:
src_basename = os.path.basename(root)
parent_src_rel = os.path.dirname(rel)
parent_out_dir = os.path.join(out_dir, parent_src_rel)
new_dir_name = clean_dir_name(src_basename)
if len(new_dir_name) == 0:
write_log(f"【警告】文件夹清洗后名称为空,使用原名保留:{src_basename}", log_path)
new_dir_name = src_basename
# 目录冲突检测,获取最终输出目录名
final_dir_name = resolve_dir_path(parent_out_dir, new_dir_name, src_basename, log_path)
dst_current_dir = os.path.join(parent_out_dir, final_dir_name)
# 创建输出目录
if not DRY_RUN:
try:
os.makedirs(dst_current_dir, exist_ok=True)
stat["dir_success"] +=1
except OSError as e:
stat["dir_fail"] +=1
write_log(f"【目录创建失败】{dst_current_dir} | {e}", log_path)
# 处理本目录全部文件
for fname in files:
if fname in SKIP_FILES:
continue
stat["scan_file_total"] +=1
ext = os.path.splitext(fname)[1].lower()
if ext in ALLOW_EXT:
stat["media_file_total"] += 1
new_name = clean_file_name(fname)
old_path = os.path.join(root, fname)
base, ext_out = os.path.splitext(new_name)
final_fname = resolve_conflict(dst_current_dir, base, ext_out, fname)
dst_file = os.path.join(dst_current_dir, final_fname)
if final_fname != fname:
write_log(f"待修改文件-> {fname} → {final_fname}", log_path)
if not DRY_RUN:
try:
shutil.copy2(old_path, dst_file)
stat["file_success"] +=1
except OSError as e:
stat["file_fail"] +=1
write_log(f"【文件复制失败】src:{old_path} dst:{dst_file} | {e}", log_path)
# 处理子文件夹,只打印名称发生变更的文件夹
for dname in dirs:
new_name = clean_dir_name(dname)
if len(new_name) == 0:
write_log(f"【警告】文件夹清洗后名称为空,跳过改名:{dname}", log_path)
continue
if new_name != dname:
write_log(f"待修改文件夹-> {dname} → {new_name}", log_path)
except OSError as walk_err:
write_log(f"【严重】遍历目录发生IO异常,部分目录未扫描:{walk_err}", log_path)
write_log("----------任务统计汇总----------", log_path)
write_log(f"总扫描目录:{stat['scan_dir_total']}", log_path)
write_log(f"总扫描文件:{stat['scan_file_total']},媒体文件:{stat['media_file_total']}", log_path)
write_log(f"目录:成功创建 {stat['dir_success']},失败 {stat['dir_fail']}", log_path)
write_log(f"文件:成功复制 {stat['file_success']},失败 {stat['file_fail']}", log_path)
write_log("============================================================", log_path)
if __name__ == "__main__":
main()
+277
View File
@@ -0,0 +1,277 @@
import os
import re
import argparse
import shutil
from datetime import datetime
# ====================== 【配置区】 ======================
# 建议日志放在【本机内置磁盘】,不要放在容易掉线的外接卷,防止盘断开日志写失败
LOG_FILE = "./rename_log.txt"
#需要完全跳过的目录名称(basename,大小写敏感)
SKIP_DIRS = [
"@eaDir", # 群晖隐含目录
]
# 需要跳过的隐含文件名称(完整文件名匹配)
SKIP_FILES = {
".DS_Store",
"Thumbs.db",
"desktop.ini",
}
# 文件清洗规则:依旧删除全部 []【】
RULES_FILE = [
(r"^[A-Za-z] ", ""),
(r"\[.*?\]", ""),
(r"【.*?】", ""),
(r"丨", ""),
(r"\b(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|中英双语|双语字幕)\b", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+-]", ""),
]
# 1.删除中文全角【】
# 2.剥最外层英文[]
# 3.清除碎片 ][
# 4.最后清理遗留空括号 () ()
RULES_DIR = [
(r"【.*?】", ""), # 删除中文全角【】以及内部内容
(r"^\[(.*)\]$", r"\1"), # 整串被英文[]包裹,只剥外层
(r"\]\[", ""), # 清除中间碎片 ][
(r"^[A-Za-z] ", ""),
(r"丨", ""),
(r"\b(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|中英|双语|国语|国粤|中字|超清|高清|清晰|无水印|HD|BD|字幕)\b", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"\(\)", ""), # 清除英文空括号 ()
(r"()", ""), # 清除中文全角空括号 ()
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+\-[\]]", ""), # 允许文件夹内部保留[]
]
#完整全部媒体后缀(不带--strm‑mode时使用)
FULL_ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm", ".flv", ".avi", ".wmv", ".ts", ".rmvb", ".webm", ".mp3", ".flac", ".aac", ".wav", ".ogg", ".m4a", ".wma", ".alac", ".rm", ".iso"}
# strm模式:仅strm+字幕
STRM_ONLY_EXT = {".strm", ".srt", ".ass", ".sub"}
MAX_FILENAME_LEN = 245 # mac文件名最大安全长度,预留扩展名位置
# =======================================================
def full2half(s):
result = []
for char in s:
code = ord(char)
if code == 12288:
char = chr(32)
elif 65281 <= code <= 65374:
char = chr(code - 65248)
result.append(char)
return "".join(result)
def clean_file_name(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
name_no_ext = full2half(name_no_ext)
for item in RULES_FILE:
if len(item) == 3:
pat, repl, flag = item
name_no_ext = re.sub(pat, repl, name_no_ext, flags=flag)
else:
pat, repl = item
name_no_ext = re.sub(pat, repl, name_no_ext)
name_no_ext = name_no_ext.strip()
if len(name_no_ext) > MAX_FILENAME_LEN:
name_no_ext = name_no_ext[:MAX_FILENAME_LEN]
return name_no_ext + ext
def clean_dir_name(name: str) -> str:
name = full2half(name)
year_match = re.search(r"^\[(\d{4})\]$", name)
year_str = ""
if year_match:
year_str = year_match.group(1)
for item in RULES_DIR:
if len(item) == 3:
pat, repl, flag = item
name = re.sub(pat, repl, name, flags=flag)
else:
pat, repl = item
name = re.sub(pat, repl, name)
name = name.strip()
if year_str and name:
name = f"{name}({year_str})"
if len(name) > MAX_FILENAME_LEN:
name = name[:MAX_FILENAME_LEN]
return name
def get_quality_tag(filename:str):
m = re.search(r"\b(2160p|1080p|720p)\b", filename, re.IGNORECASE)
if m:
return m.group(1).lower()
return None
def resolve_conflict(dst_dir:str, base_name:str, ext:str, orig_filename:str):
candidate = base_name + ext
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
qual = get_quality_tag(orig_filename)
if qual:
candidate = f"{base_name}({qual}){ext}"
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
idx = 1
while True:
candidate = f"{base_name}({idx}){ext}"
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
idx +=1
def write_log(msg: str, log_file: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
try:
with open(log_file, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
except Exception:
#日志写入失败降级控制台输出,不打断程序
print(f"[LOG-WRITE-FAILED] {line}")
def main():
parser = argparse.ArgumentParser(description="媒体文件名镜像清洗工具,源目录只读,生成镜像副本")
parser.add_argument("--dir", required=True, help="原始源媒体根目录")
parser.add_argument("--output", required=True, help="输出镜像根目录")
parser.add_argument("--apply", action="store_true", help="加上此参数才执行真实复制生成镜像")
parser.add_argument("--dry-run", action="store_true", help="预览模式(默认就是预览,该参数为显式简写)")
parser.add_argument("--strm-mode", action="store_true", help="开启strm模式:仅处理 .strm .srt .ass .sub;过滤mkv/mp4等视频文件")
parser.add_argument("--log", default="./rename_log.txt", help="日志文件路径,默认 ./rename_log.txt")
args = parser.parse_args()
target_dir = args.dir
out_dir = args.output
log_path = args.log
DRY_RUN = True
if args.apply:
DRY_RUN = False
if args.strm_mode:
ALLOW_EXT = STRM_ONLY_EXT
mode_info = "STRM模式【仅strm+字幕】"
else:
ALLOW_EXT = FULL_ALLOW_EXT
mode_info = "完整媒体模式【全部媒体后缀】"
if not os.path.isdir(target_dir):
print(f"错误:源目录不存在 -> {target_dir}")
return
#初始化日志
try:
with open(log_path, "w", encoding="utf-8") as f:
f.flush()
except Exception as e:
print(f"警告:无法初始化日志文件 {log_path},后续仅控制台输出日志,异常:{e}")
write_log("===== 文件名+文件夹清洗【增加清除空括号()()】 =====", log_path)
write_log(f"源目录:{target_dir}", log_path)
write_log(f"输出镜像目录:{out_dir}", log_path)
write_log(f"运行模式:{mode_info}", log_path)
write_log(f"预览模式 DRY_RUN = {DRY_RUN}", log_path)
if SKIP_DIRS:
write_log(f"配置跳过目录名列表:{SKIP_DIRS}", log_path)
write_log(f"过滤隐含系统文件:{SKIP_FILES}", log_path)
stat = {
"scan_dir_total":0,
"scan_file_total":0,
"media_file_total":0,
"file_success":0,
"file_fail":0,
"dir_success":0,
"dir_fail":0
}
try:
for root, dirs, files in os.walk(target_dir, topdown=False):
#过滤跳过目录:@eaDir、配置SKIP_DIRS
remove_idx = []
for idx, dname in enumerate(dirs):
if dname in SKIP_DIRS:
remove_idx.append(idx)
for idx in reversed(remove_idx):
del dirs[idx]
stat["scan_dir_total"] += 1
rel = os.path.relpath(root, target_dir)
if rel == ".":
dst_current_dir = out_dir
else:
src_basename = os.path.basename(root)
new_dir_name = clean_dir_name(src_basename)
if len(new_dir_name) == 0:
write_log(f"【警告】文件夹清洗后名称为空,使用原名保留:{src_basename}", log_path)
new_dir_name = src_basename
dst_current_dir = os.path.join(out_dir, rel.replace(src_basename, new_dir_name))
#创建输出目录
if not DRY_RUN:
try:
os.makedirs(dst_current_dir, exist_ok=True)
stat["dir_success"] +=1
except OSError as e:
stat["dir_fail"] +=1
write_log(f"【目录创建失败】{dst_current_dir} | {e}", log_path)
#处理本目录全部文件
for fname in files:
if fname in SKIP_FILES:
continue
stat["scan_file_total"] +=1
ext = os.path.splitext(fname)[1].lower()
if ext in ALLOW_EXT:
stat["media_file_total"] += 1
new_name = clean_file_name(fname)
old_path = os.path.join(root, fname)
base, ext_out = os.path.splitext(new_name)
final_fname = resolve_conflict(dst_current_dir, base, ext_out, fname)
dst_file = os.path.join(dst_current_dir, final_fname)
if final_fname != fname:
write_log(f"待修改文件-> {fname} → {final_fname}", log_path)
if not DRY_RUN:
try:
shutil.copy2(old_path, dst_file)
stat["file_success"] +=1
except OSError as e:
stat["file_fail"] +=1
write_log(f"【文件复制失败】src:{old_path} dst:{dst_file} | {e}", log_path)
#处理子文件夹,只打印名称发生变更的文件夹
for dname in dirs:
new_name = clean_dir_name(dname)
if len(new_name) == 0:
write_log(f"【警告】文件夹清洗后名称为空,跳过改名:{dname}", log_path)
continue
if new_name != dname:
write_log(f"待修改文件夹-> {dname} → {new_name}", log_path)
except OSError as walk_err:
write_log(f"【严重】遍历目录发生IO异常,部分目录未扫描:{walk_err}", log_path)
write_log("----------任务统计汇总----------", log_path)
write_log(f"总扫描目录:{stat['scan_dir_total']}", log_path)
write_log(f"总扫描文件:{stat['scan_file_total']},媒体文件:{stat['media_file_total']}", log_path)
write_log(f"目录:成功创建 {stat['dir_success']},失败 {stat['dir_fail']}", log_path)
write_log(f"文件:成功复制 {stat['file_success']},失败 {stat['file_fail']}", log_path)
write_log("============================================================", log_path)
if __name__ == "__main__":
main()
+274
View File
@@ -0,0 +1,274 @@
import os
import re
import argparse
import shutil
from datetime import datetime
# ====================== 【配置区】 ======================
LOG_FILE = "./rename_log.txt"
# 需要完全跳过的目录名称(basename,大小写敏感)
SKIP_DIRS = [
"@eaDir", # 群晖隐含目录
]
# 需要跳过的隐含文件名称(完整文件名匹配)
SKIP_FILES = {
".DS_Store",
"Thumbs.db",
"desktop.ini",
}
# 文件清洗规则
RULES_FILE = [
(r"^[A-Za-z] ", ""),
(r"\[.*?\]", ""),
(r"【.*?】", ""),
(r"丨", ""),
(r"(?<!\w)(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB-DL|HD|4K|中英双语|双语字幕|双语|中文|国语|粤语|台语|韩语|中英双字|国语中字|繁体中字|简体中字|简繁中字|双语中字|官方中字|特效中字)(?!\w)", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+\-]", ""),
]
# 文件夹清洗规则
RULES_DIR = [
(r"【.*?】", ""), # 删除中文全角【】以及内部内容
(r"^\[(.*)\]$", r"\1"), # 整串被[]包裹,只剥外层
(r"\]\[", ""), # 清除中间碎片 ][
(r"^[A-Za-z] ", ""),
(r"丨", ""),
(r"(?<!\w)(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|BD|BluRay|BLURAY|WEBRip|WEB-DL|HD|4K|中英双语|双语字幕|双语|中文|国语|粤语|台语|韩语|中英双字|国语中字|繁体中字|简体中字|简繁中字|双语中字|官方中字|特效中字)(?!\w)", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"\(\)", ""), # 清除英文空括号 ()
(r"()", ""), # 清除中文全角空括号 ()
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+\-[\]]", ""), # 允许文件夹内部保留[]
]
#完整全部媒体后缀(不带--strm-mode时使用)
FULL_ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm", ".flv", ".avi", ".wmv", ".ts", ".rmvb", ".webm", ".mp3", ".flac", ".aac", ".wav", ".ogg", ".m4a", ".wma", ".alac", ".rm", ".iso"}
# strm模式:仅strm+字幕
STRM_ONLY_EXT = {".strm", ".srt", ".ass", ".sub"}
MAX_FILENAME_LEN = 245 # mac文件名最大安全长度,预留扩展名位置
# =======================================================
def full2half(s):
result = []
for char in s:
code = ord(char)
if code == 12288:
char = chr(32)
elif 65281 <= code <= 65374:
char = chr(code - 65248)
result.append(char)
return "".join(result)
def clean_file_name(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
name_no_ext = full2half(name_no_ext)
for item in RULES_FILE:
if len(item) == 3:
pat, repl, flag = item
name_no_ext = re.sub(pat, repl, name_no_ext, flags=flag)
else:
pat, repl = item
name_no_ext = re.sub(pat, repl, name_no_ext)
name_no_ext = name_no_ext.strip()
if len(name_no_ext) > MAX_FILENAME_LEN:
name_no_ext = name_no_ext[:MAX_FILENAME_LEN]
return name_no_ext + ext
def clean_dir_name(name: str) -> str:
name = full2half(name)
year_match = re.search(r"^\[(\d{4})\]$", name)
year_str = ""
if year_match:
year_str = year_match.group(1)
for item in RULES_DIR:
if len(item) == 3:
pat, repl, flag = item
name = re.sub(pat, repl, name, flags=flag)
else:
pat, repl = item
name = re.sub(pat, repl, name)
name = name.strip()
if year_str and name:
name = f"{name}({year_str})"
if len(name) > MAX_FILENAME_LEN:
name = name[:MAX_FILENAME_LEN]
return name
def get_quality_tag(filename:str):
m = re.search(r"(?<!\w)(2160p|1080p|720p)(?!\w)", filename, re.IGNORECASE)
if m:
return m.group(1).lower()
return None
def resolve_conflict(dst_dir:str, base_name:str, ext:str, orig_filename:str):
candidate = base_name + ext
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
qual = get_quality_tag(orig_filename)
if qual:
candidate = f"{base_name}({qual}){ext}"
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
idx = 1
while True:
candidate = f"{base_name}({idx}){ext}"
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
idx +=1
def write_log(msg: str, log_file: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
try:
with open(log_file, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
except Exception:
#日志写入失败降级控制台输出,不打断程序
print(f"[LOG-WRITE-FAILED] {line}")
def main():
parser = argparse.ArgumentParser(description="媒体文件名镜像清洗工具,源目录只读,生成镜像副本")
parser.add_argument("--dir", required=True, help="原始源媒体根目录")
parser.add_argument("--output", required=True, help="输出镜像根目录")
parser.add_argument("--apply", action="store_true", help="加上此参数才执行真实复制生成镜像")
parser.add_argument("--dry-run", action="store_true", help="预览模式(默认就是预览,该参数为显式简写)")
parser.add_argument("--strm-mode", action="store_true", help="开启strm模式:仅处理 .strm .srt .ass .sub;过滤mkv/mp4等视频文件")
parser.add_argument("--log", default="./rename_log.txt", help="日志文件路径,默认 ./rename_log.txt")
args = parser.parse_args()
target_dir = args.dir
out_dir = args.output
log_path = args.log
DRY_RUN = True
if args.apply:
DRY_RUN = False
if args.dry_run:
DRY_RUN = True
if args.strm_mode:
ALLOW_EXT = STRM_ONLY_EXT
mode_info = "STRM模式【仅strm+字幕】"
else:
ALLOW_EXT = FULL_ALLOW_EXT
mode_info = "完整媒体模式【全部媒体后缀】"
if not os.path.isdir(target_dir):
print(f"错误:源目录不存在 -> {target_dir}")
return
#初始化日志
try:
with open(log_path, "w", encoding="utf-8") as f:
f.flush()
except Exception as e:
print(f"警告:无法初始化日志文件 {log_path},后续仅控制台输出日志,异常:{e}")
write_log("===== 文件名+文件夹清洗【修复参数符号,过滤BD/HD/4K/双语/国语等标记】 =====", log_path)
write_log(f"源目录:{target_dir}", log_path)
write_log(f"输出镜像目录:{out_dir}", log_path)
write_log(f"运行模式:{mode_info}", log_path)
write_log(f"预览模式 DRY_RUN = {DRY_RUN}", log_path)
if SKIP_DIRS:
write_log(f"配置跳过目录名列表:{SKIP_DIRS}", log_path)
write_log(f"过滤隐含系统文件:{SKIP_FILES}", log_path)
stat = {
"scan_dir_total":0,
"scan_file_total":0,
"media_file_total":0,
"file_success":0,
"file_fail":0,
"dir_success":0,
"dir_fail":0
}
try:
for root, dirs, files in os.walk(target_dir, topdown=False):
#过滤跳过目录:@eaDir、配置SKIP_DIRS
remove_idx = []
for idx, dname in enumerate(dirs):
if dname in SKIP_DIRS:
remove_idx.append(idx)
for idx in reversed(remove_idx):
del dirs[idx]
stat["scan_dir_total"] += 1
rel = os.path.relpath(root, target_dir)
if rel == ".":
dst_current_dir = out_dir
else:
src_basename = os.path.basename(root)
new_dir_name = clean_dir_name(src_basename)
if len(new_dir_name) == 0:
write_log(f"【警告】文件夹清洗后名称为空,使用原名保留:{src_basename}", log_path)
new_dir_name = src_basename
dst_current_dir = os.path.join(out_dir, rel.replace(src_basename, new_dir_name))
# 创建输出目录
if not DRY_RUN:
try:
os.makedirs(dst_current_dir, exist_ok=True)
stat["dir_success"] +=1
except OSError as e:
stat["dir_fail"] +=1
write_log(f"【目录创建失败】{dst_current_dir} | {e}", log_path)
# 处理本目录全部文件
for fname in files:
if fname in SKIP_FILES:
continue
stat["scan_file_total"] +=1
ext = os.path.splitext(fname)[1].lower()
if ext in ALLOW_EXT:
stat["media_file_total"] += 1
new_name = clean_file_name(fname)
old_path = os.path.join(root, fname)
base, ext_out = os.path.splitext(new_name)
final_fname = resolve_conflict(dst_current_dir, base, ext_out, fname)
dst_file = os.path.join(dst_current_dir, final_fname)
if final_fname != fname:
write_log(f"待修改文件-> {fname} → {final_fname}", log_path)
if not DRY_RUN:
try:
shutil.copy2(old_path, dst_file)
stat["file_success"] +=1
except OSError as e:
stat["file_fail"] +=1
write_log(f"【文件复制失败】src:{old_path} dst:{dst_file} | 错误:{e}", log_path)
# 处理子文件夹,只打印名称发生变更的文件夹
for dname in dirs:
new_name = clean_dir_name(dname)
if len(new_name) == 0:
write_log(f"【警告】文件夹清洗后名称为空,跳过改名:{dname}", log_path)
continue
if new_name != dname:
write_log(f"待修改文件夹-> {dname} → {new_name}", log_path)
except OSError as walk_err:
write_log(f"【严重】遍历目录发生IO异常,部分目录未扫描:{walk_err}", log_path)
write_log("----------任务统计汇总----------", log_path)
write_log(f"总扫描目录:{stat['scan_dir_total']}", log_path)
write_log(f"总扫描文件:{stat['scan_file_total']},媒体文件:{stat['media_file_total']}", log_path)
write_log(f"目录:成功创建 {stat['dir_success']},失败 {stat['dir_fail']}", log_path)
write_log(f"文件:成功复制 {stat['file_success']},失败 {stat['file_fail']}", log_path)
write_log("============================================================", log_path)
if __name__ == "__main__":
main()
+196
View File
@@ -0,0 +1,196 @@
import os
import re
import argparse
import shutil
from datetime import datetime
# ====================== 配置区 ======================
RULES_FILE = [
(r"^[A-Za-z] ", ""),
(r"\[.*?\]", ""),
(r"【.*?】", ""),
(r"丨", ""),
(r"\b(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|中英双语|双语字幕)\b", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+-]", ""),
]
RULES_DIR = [
(r"^[A-Za-z] ", ""),
(r"丨", ""),
(r"\b(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|中英双语|双语字幕)\b", "", re.IGNORECASE),
(r"\.+", ""),
(r"\s", ""),
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+-]", ""),
]
ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm",".flv",".avi",".wmv",".ts",".rmvb",".webm",".mp3",".flac",".aac",".wav",".ogg",".m4a",".wma",".alac",".rm",".iso"}
# ====================================================
def full2half(s):
result = []
for char in s:
code = ord(char)
if code == 12288:
char = chr(32)
elif 65281 <= code <= 65374:
char = chr(code - 65248)
result.append(char)
return "".join(result)
def clean_file_name(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
name_no_ext = full2half(name_no_ext)
for item in RULES_FILE:
if len(item) == 3:
pat, repl, flag = item
name_no_ext = re.sub(pat, repl, name_no_ext, flags=flag)
else:
pat, repl = item
name_no_ext = re.sub(pat, repl, name_no_ext)
name_no_ext = name_no_ext.strip()
return name_no_ext + ext
def clean_dir_name(name: str) -> str:
name = full2half(name)
year_match = re.search(r"\[(\d{4})\]", name)
year_str = ""
if year_match:
year_str = year_match.group(1)
name = re.sub(r"\[.*?\]", "", name)
for item in RULES_DIR:
if len(item) == 3:
pat, repl, flag = item
name = re.sub(pat, repl, name, flags=flag)
else:
pat, repl = item
name = re.sub(pat, repl, name)
name = name.strip()
if year_str and name:
name = f"{name}({year_str})"
return name
def get_quality_tag(filename:str):
m = re.search(r"\b(2160p|1080p|720p)\b", filename, re.IGNORECASE)
if m:
return m.group(1).lower()
return None
def resolve_conflict(dst_dir:str, base_name:str, ext:str, orig_filename:str):
"""解决输出目录同名冲突:优先追加画质,无画质则追加(1)(2)"""
candidate = base_name + ext
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
qual = get_quality_tag(orig_filename)
if qual:
candidate = f"{base_name}({qual}){ext}"
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
idx = 1
while True:
candidate = f"{base_name}({idx}){ext}"
dst_path = os.path.join(dst_dir, candidate)
if not os.path.exists(dst_path):
return candidate
idx +=1
def write_log(msg: str, log_file: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
with open(log_file, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
def process_tree(src_root:str, dst_root:str, dry_run:bool, log_path:str):
stat = {
"scan_dir_total":0,
"scan_file_total":0,
"media_file_total":0,
"file_success":0,
"file_fail":0,
"dir_success":0,
"dir_fail":0
}
for src_dir, dirs, files in os.walk(src_root):
stat["scan_dir_total"] +=1
rel = os.path.relpath(src_dir, src_root)
if rel == ".":
dst_current_dir = dst_root
else:
dst_current_dir = os.path.join(dst_root, clean_dir_name(os.path.basename(src_dir)))
# 创建输出目录
if not dry_run:
try:
os.makedirs(dst_current_dir, exist_ok=True)
stat["dir_success"] +=1
except Exception as e:
stat["dir_fail"] +=1
write_log(f"【目录创建失败】{dst_current_dir} | {e}", log_path)
else:
write_log(f"【预览-输出目录】{dst_current_dir}", log_path)
# 处理本目录全部文件
for fname in files:
stat["scan_file_total"] += 1
src_file = os.path.join(src_dir, fname)
ext = os.path.splitext(fname)[1].lower()
if ext in ALLOW_EXT:
stat["media_file_total"] +=1
new_fname = clean_file_name(fname)
base, ext_out = os.path.splitext(new_fname)
final_fname = resolve_conflict(dst_current_dir, base, ext_out, fname)
dst_file = os.path.join(dst_current_dir, final_fname)
write_log(f"待复制文件-> {fname} → {final_fname}", log_path)
if not dry_run:
try:
shutil.copy2(src_file, dst_file)
stat["file_success"] +=1
except Exception as e:
stat["file_fail"] +=1
write_log(f"【文件复制失败】src:{src_file} dst:{dst_file} | {e}", log_path)
return stat
def main():
parser = argparse.ArgumentParser(description="媒体文件名镜像清洗工具,源目录只读,输出全新镜像目录")
parser.add_argument("--dir", required=True, help="原始源媒体根目录")
parser.add_argument("--output", required=True, help="输出镜像根目录")
parser.add_argument("--apply", action="store_true", help="加上此参数才真正复制生成镜像;默认预览dry‑run")
parser.add_argument("--log", default="./rename_log.txt", help="日志文件路径,默认同脚本目录rename_log.txt")
args = parser.parse_args()
src_dir = args.dir
out_dir = args.output
dry_run = not args.apply
log_path = args.log
if not os.path.isdir(src_dir):
print(f"错误:源目录不存在 -> {src_dir}")
return
with open(log_path, "w", encoding="utf-8") as f:
f.flush()
write_log("===== 媒体文件名镜像清洗【源目录只读,生成镜像副本】 =====", log_path)
write_log(f"源目录:{src_dir}", log_path)
write_log(f"输出镜像目录:{out_dir}", log_path)
write_log(f"预览模式 DRY_RUN = {dry_run}", log_path)
stat = process_tree(src_dir, out_dir, dry_run, log_path)
write_log("----------任务统计汇总----------", log_path)
write_log(f"总扫描目录:{stat['scan_dir_total']}", log_path)
write_log(f"总扫描文件:{stat['scan_file_total']},媒体文件:{stat['media_file_total']}", log_path)
write_log(f"目录:成功创建 {stat['dir_success']},失败 {stat['dir_fail']}", log_path)
write_log(f"文件:成功复制 {stat['file_success']},失败 {stat['file_fail']}", log_path)
write_log("============================================================", log_path)
if __name__ == "__main__":
main()
+131
View File
@@ -0,0 +1,131 @@
import os
import re
import argparse
from datetime import datetime
# ====================== 【配置区,不再写死目录】 ======================
LOG_FILE = "./rename_log.txt"
# 清洗规则
RULES = [
(r"^[A-Za-z] ", ""), #1.移除开头单个字母+空格
(r"\[.*?\]", ""), #2.移除英文方括号及内部内容
(r"【.*?】", ""), #3.移除中文【】及内部内容
(r"丨", ""), #清除汉字竖线 丨
(r"\b(2160p|1080p|720p|HDR|DV|DoVi|HEVC|x265|x264|DDP|AAC|Atmos|TrueHD|中英双语|双语字幕)\b", "", re.IGNORECASE),
(r"\.+", ""), #删除连续的点
(r"\s", ""), #删除全部空格
# 保留:汉字、半角英文、数字、半角 () . : + -
(r"[^\u4e00-\u9fa5a-zA-Z0-9().:+-]", ""),
]
ALLOW_EXT = {".mkv", ".mp4", ".mov", ".srt", ".ass", ".sub", ".strm",".flv",".avi",".wmv",".ts",".rmvb",".webm",".mp3",".flac",".aac",".wav",".ogg",".m4a",".wma",".alac",".rm",".iso"}
# ====================================================================
def clean_filename(name: str) -> str:
name_no_ext, ext = os.path.splitext(name)
# 全角转半角
def full2half(s):
result = []
for char in s:
code = ord(char)
if code == 12288:
char = chr(32)
elif 65281 <= code <= 65374:
char = chr(code - 65248)
result.append(char)
return "".join(result)
name_no_ext = full2half(name_no_ext)
for item in RULES:
if len(item) == 3:
pat, repl, flag = item
name_no_ext = re.sub(pat, repl, name_no_ext, flags=flag)
else:
pat, repl = item
name_no_ext = re.sub(pat, repl, name_no_ext)
name_no_ext = name_no_ext.strip()
return name_no_ext + ext
def write_log(msg: str):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{now}] {msg}"
print(line)
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + "\n")
f.flush()
def main():
parser = argparse.ArgumentParser(description="媒体文件名批量清洗重命名工具")
parser.add_argument("--dir", required=True, help="目标根目录路径")
parser.add_argument("--apply", action="store_true", help="加上此参数才执行真实重命名;默认仅预览DryRun")
args = parser.parse_args()
target_dir = args.dir
DRY_RUN = not args.apply
# 校验目录是否存在
if not os.path.isdir(target_dir):
print(f"错误:目录不存在 -> {target_dir}")
return
# 每次运行前清空日志文件
with open(LOG_FILE, "w", encoding="utf-8") as f:
f.flush()
write_log("===== 文件名+文件夹清洗(移除开头A 中文片名前缀) =====")
write_log(f"根目录:{target_dir}")
write_log(f"预览模式 DRY_RUN = {DRY_RUN}")
file_rename_list = []
dir_rename_list = []
total_scan_dirs = 0
total_all_files = 0 # 全部扫描到的文件(所有后缀)
total_media_files = 0 # 媒体文件(ALLOW_EXT后缀)
for root, dirs, files in os.walk(target_dir, topdown=False):
total_scan_dirs += 1
for fname in files:
total_all_files +=1
ext = os.path.splitext(fname)[1].lower()
if ext in ALLOW_EXT:
total_media_files += 1
new_name = clean_filename(fname)
if new_name != fname:
old_path = os.path.join(root, fname)
new_path = os.path.join(root, new_name)
file_rename_list.append((old_path, new_path))
write_log(f"待修改文件-> {fname} → {new_name}")
# 处理文件夹
for dname in dirs:
new_name = clean_filename(dname)
if new_name != dname:
old_path = os.path.join(root, dname)
new_path = os.path.join(root, new_name)
dir_rename_list.append((old_path, new_name))
write_log(f"待修改文件夹-> {dname} → {new_name}")
# ========== 执行阶段 ==========
if not DRY_RUN:
# 先文件
for old, new in file_rename_list:
try:
os.rename(old, new)
except Exception as e:
write_log(f"【文件重命名失败】{old} -> {new} | 错误:{e}")
# 后文件夹
for old, new in dir_rename_list:
try:
os.rename(old, new)
except Exception as e:
write_log(f"【文件夹重命名失败】{old} -> {new} | 错误:{e}")
# 最终汇总输出
write_log(f"任务完成,总扫描目录:{total_scan_dirs},待修改文件夹:{len(dir_rename_list)}")
write_log(f"总扫描文件:{total_all_files},媒体文件:{total_media_files},待修改文件:{len(file_rename_list)}")
write_log("============================================================")
if __name__ == "__main__":
main()
+7833
View File
File diff suppressed because it is too large Load Diff
+489
View File
@@ -0,0 +1,489 @@
[
{
"type": "dir",
"orig_basename": "洛杉矶劫案.2160p.6v电影 地址发布页 www.6v123.net 收藏不迷路",
"step1_name": "洛杉矶劫案.2160p.6v电影地址发布页www.6v123.net收藏不迷路",
"step2_name": "洛杉矶劫案_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"D001",
"D003"
]
},
{
"type": "dir",
"orig_basename": "劫机",
"step1_name": "劫机",
"step2_name": "劫机_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": []
},
{
"type": "file",
"orig_basename": "4K.strm",
"step1_name": "4K.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F003"
]
},
{
"type": "file",
"orig_basename": "1080p.strm",
"step1_name": "1080p.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F003"
]
},
{
"type": "file",
"orig_basename": "云边有个小卖部_1080P.strm",
"step1_name": "云边有个小卖部_1080P.strm",
"step2_name": "云边有个小卖部.strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F003"
]
},
{
"type": "file",
"orig_basename": "1080p.strm",
"step1_name": "1080p.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F003"
]
},
{
"type": "file",
"orig_basename": "1080p.strm",
"step1_name": "1080p.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F003"
]
},
{
"type": "file",
"orig_basename": "[迅雷下载www.2tu.cc]鬼子来了.BD1280高清国语中字.strm",
"step1_name": "[迅雷下载www.2tu.cc]鬼子来了.BD1280高清国语中字.strm",
"step2_name": "鬼子来了.1280高清国语中字.strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F003"
]
},
{
"type": "file",
"orig_basename": "【太平洋幽灵.Against the Sun】【高清720P版HD-RMVB.中字】.strm",
"step1_name": "【太平洋幽灵.AgainsttheSun】【高清720P版HD-RMVB.中字】.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F002"
]
},
{
"type": "file",
"orig_basename": "【Journey.To.The.West.Conquering.The.Demons】【高清版DVD-RMVB.国语中英双字】.strm",
"step1_name": "【Journey.To.The.West.Conquering.The.Demons】【高清版DVD-RMVB.国语中英双字】.strm",
"step2_name": "strm_dup(2)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F002"
]
},
{
"type": "file",
"orig_basename": "【The.Marine.3.Homefront】【高清1280版BD-RMVB.中英双字】.strm",
"step1_name": "【The.Marine.3.Homefront】【高清1280版BD-RMVB.中英双字】.strm",
"step2_name": "strm_dup(3)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F002"
]
},
{
"type": "file",
"orig_basename": "加勒比海盗4.strm",
"step1_name": "加勒比海盗4.strm",
"step2_name": "加勒比海盗4.strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": []
},
{
"type": "file",
"orig_basename": "1080P.strm",
"step1_name": "1080P.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F003"
]
},
{
"type": "file",
"orig_basename": "猎杀红色十月.The.Hunt.for.Red.October.1990.BD1080p.X264.2Audio.AAC.HALFCD-NORM.Christian.strm",
"step1_name": "猎杀红色十月.The.Hunt.for.Red.October.1990.BD1080p.X264.2Audio.AAC.HALFCD-NORM.Christian.strm",
"step2_name": "猎杀红色十月.The.Hunt.for.Red.October.1990.2Audio.HALFCD-NORM.Christian.strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F003"
]
},
{
"type": "file",
"orig_basename": "[1982][CN][逆光]Ni.Guang.TVRip.Xvid-Mustdown[www.ed2kers.com].strm",
"step1_name": "[1982][CN][逆光]Ni.Guang.TVRip.Xvid-Mustdown[www.ed2kers.com].strm",
"step2_name": "Ni.Guang.TVRip.Xvid-Mustdown.strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[唐山大兄.cd1.1971.国粵双语].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[唐山大兄.cd1.1971.国粵双语].九洲客.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[死亡游戏.cd2.1978].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[死亡游戏.cd2.1978].九洲客.strm",
"step2_name": "strm_dup(2)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[死亡游戏.cd1.1978].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[死亡游戏.cd1.1978].九洲客.strm",
"step2_name": "strm_dup(3)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[死亡塔.cd2.1981].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[死亡塔.cd2.1981].九洲客.strm",
"step2_name": "strm_dup(4)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[死亡塔.cd1.1981].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[死亡塔.cd1.1981].九洲客.strm",
"step2_name": "strm_dup(5)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[猛龙过江.cd2.1972.国粵双语].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[猛龙过江.cd2.1972.国粵双语].九洲客.strm",
"step2_name": "strm_dup(6)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[猛龙过江.cd1.1972.国粵双语].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[猛龙过江.cd1.1972.国粵双语].九洲客.strm",
"step2_name": "strm_dup(7)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[龙争虎斗.cd2.1973.国粵双语].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[龙争虎斗.cd2.1973.国粵双语].九洲客.strm",
"step2_name": "strm_dup(8)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[龙争虎斗.cd1.1973.国粵双语].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[龙争虎斗.cd1.1973.国粵双语].九洲客.strm",
"step2_name": "strm_dup(9)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[精武门.cd2.1972.国粵双语].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[精武门.cd2.1972.国粵双语].九洲客.strm",
"step2_name": "strm_dup(10)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[精武门.cd1.1972.国粵双语].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[精武门.cd1.1972.国粵双语].九洲客.strm",
"step2_name": "strm_dup(11)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[开心鬼4.1989.国粤双语.简繁中字].暮云春树.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[开心鬼4.1989.国粤双语.简繁中字].暮云春树.strm",
"step2_name": "暮云春树.strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[开心鬼2.1985.国粤双语.简繁中字].tdw9430.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[开心鬼2.1985.国粤双语.简繁中字].tdw9430.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[开心鬼1.1984.国粤双语.简繁中字].tdw9430.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[开心鬼1.1984.国粤双语.简繁中字].tdw9430.strm",
"step2_name": "strm_dup(2)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[极限特工Ⅰ.2002.中英字幕].九洲客.strm",
"step1_name": "[极限特工Ⅰ.2002.中英字幕].九洲客.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn [黑客帝国 3.2003.中英字幕].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[黑客帝国3.2003.中英字幕].九洲客.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn [黑客帝国 2.2003.中英字幕].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[黑客帝国2.2003.中英字幕].九洲客.strm",
"step2_name": "strm_dup(2)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn [黑客帝国 1.1999.中英字幕].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[黑客帝国1.1999.中英字幕].九洲客.strm",
"step2_name": "strm_dup(3)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[非常人贩2.2005.中英字幕].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[非常人贩2.2005.中英字幕].九洲客.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[SCG-CMCT]www.dream2008.cn[非常人贩1.2002.中英字幕].九洲客.strm",
"step1_name": "[SCG-CMCT]www.dream2008.cn[非常人贩1.2002.中英字幕].九洲客.strm",
"step2_name": "strm_dup(2)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[电锯惊魂Ⅳ.2007.中英字幕].九洲客.strm",
"step1_name": "[电锯惊魂Ⅳ.2007.中英字幕].九洲客.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[电锯惊魂Ⅲ.2006.中英字幕].九洲客.strm",
"step1_name": "[电锯惊魂Ⅲ.2006.中英字幕].九洲客.strm",
"step2_name": "strm_dup(2)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[电锯惊魂Ⅱ.2005.中英字幕].九洲客.strm",
"step1_name": "[电锯惊魂Ⅱ.2005.中英字幕].九洲客.strm",
"step2_name": "strm_dup(3)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[电锯惊魂Ⅰ.2004.中英字幕].九洲客.strm",
"step1_name": "[电锯惊魂Ⅰ.2004.中英字幕].九洲客.strm",
"step2_name": "strm_dup(4)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[第一滴血Ⅲ.1988.中英字幕].九洲客.strm",
"step1_name": "[第一滴血Ⅲ.1988.中英字幕].九洲客.strm",
"step2_name": "strm_dup(1)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[第一滴血Ⅱ.1985.中英字幕].九洲客.strm",
"step1_name": "[第一滴血Ⅱ.1985.中英字幕].九洲客.strm",
"step2_name": "strm_dup(2)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
},
{
"type": "file",
"orig_basename": "[第一滴血Ⅰ.1982.中英字幕].九洲客.strm",
"step1_name": "[第一滴血Ⅰ.1982.中英字幕].九洲客.strm",
"step2_name": "strm_dup(3)",
"step2_dup_warn": true,
"safe_guard_trigger": false,
"hit_rule_ids": [
"F001",
"F006"
]
}
]
+186
View File
@@ -0,0 +1,186 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
watcher.py —— 自研媒体刮削「监听服务」
功能:
1. 用 watchdog 监听「清理后媒体目录」
2. 检测到新媒体文件/目录写入稳定后,自动调用 media_scraper 刮削
3. 刮削结果(媒体 + nfo + 海报)复制落库到成品目录
4. 源目录保持原样,不写入任何文件
用法:
./watcher.py --config config.json # 常驻服务
./watcher.py --config config.json --once # 只扫描一次现有内容后退出(用于初始化存量)
config.json 字段:
{
"source": "<清理后媒体目录>",
"dest": "<成品落库目录>",
"tmdb_api_key": "", # TMDB API Key;留空时用 --mock 跑通管线
"mock": true, # true=模拟元数据(无Key验证用);true后配好Key改为 false
"settle": 6, # 写入稳定等待秒数
"language": "zh-CN"
}
"""
import argparse
import json
import os
import sys
import threading
import time
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
# 复用核心刮削器
from media_scraper import (Config, Scraper, clean_ext, VIDEO_EXTS,
scan_and_scrape)
class Config2(Config):
"""扩展 Config:加载 watcher 的 source/dest/settle。"""
def __init__(self, path):
super().__init__(path)
data = json.load(open(path, encoding="utf-8"))
self.source = os.path.abspath(data.get("source", ""))
self.dest = os.path.abspath(data.get("dest", ""))
self.settle = int(data.get("settle", 6))
self.mock = data.get("mock", False)
if self.mock:
self.tmdb_api_key = "" # mock 模式不需要 key
class ScraperWorker:
"""把新媒体单元交给刮削器,带去重与写入稳定判定。"""
def __init__(self, cfg, log):
self.cfg = cfg
self.log = log
self.scraper = Scraper(cfg, cfg.dest, source_root=cfg.source, log=log)
self.processed = set() # 已处理的绝对路径
self.lock = threading.Lock()
os.makedirs(cfg.dest, exist_ok=True)
def _is_stable(self, path):
"""判断文件/目录是否写入稳定:两次采样大小一致,最多等 settle 秒。"""
def size(p):
if os.path.isfile(p):
return os.path.getsize(p)
# 目录:取所有文件大小之和
try:
return sum(os.path.getsize(os.path.join(r, f))
for r, _, fs in os.walk(p) for f in fs)
except OSError:
return -1
last = size(path)
wait = self.cfg.settle
while wait > 0:
time.sleep(min(wait, 2))
wait -= 2
cur = size(path)
if cur == last and cur >= 0:
return True
last = cur
return True
def handle(self, path):
path = os.path.abspath(path)
if not os.path.exists(path):
return
key = path if os.path.isdir(path) else os.path.dirname(path)
with self.lock:
if key in self.processed:
return
self.processed.add(key)
try:
self.log(f"检测到新媒体: {path},等待写入稳定…")
self._is_stable(path)
self.log(f"开始刮削: {path}")
scan_and_scrape(path, self.cfg.dest, self.scraper)
self.log(f"完成: {path}")
except Exception as e:
self.log(f"处理失败 {path}: {e}")
class MediaHandler(FileSystemEventHandler):
def __init__(self, worker):
self.worker = worker
self._threads = []
self.lock = threading.Lock()
def _dispatch(self, path):
if os.path.basename(path).startswith("."): # 隐藏/临时文件
return
ext = clean_ext(path)
if ext in VIDEO_EXTS or os.path.isdir(path):
t = threading.Thread(target=self.worker.handle, args=(path,),
daemon=True)
t.start()
with self.lock:
self._threads.append(t)
self._threads = [x for x in self._threads if x.is_alive()]
def on_created(self, event):
self._dispatch(event.src_path)
def on_moved(self, event):
# 下载工具常见:先 .part 再改名成正式名,此时事件是 moved
if not event.dest_path.endswith(".part"):
self._dispatch(event.dest_path)
def on_closed(self, event):
pass
def main():
ap = argparse.ArgumentParser(description="自研媒体刮削监听服务")
ap.add_argument("--config", required=True, help="config.json 路径")
ap.add_argument("--once", action="store_true",
help="扫描现有内容一次后退出(初始化存量)")
args = ap.parse_args()
cfg = Config2(args.config)
if not cfg.source or not os.path.isdir(cfg.source):
print(f"配置错误:source 不存在或未设置 -> {cfg.source}")
sys.exit(1)
def log(msg):
line = f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {msg}"
print(line)
# 追加写日志文件
logfile = os.path.join(cfg.dest, "..", "scraper.log")
try:
with open(logfile, "a", encoding="utf-8") as f:
f.write(line + "\n")
except OSError:
pass
worker = ScraperWorker(cfg, log)
# 启动时先扫描一次现有内容(这样重启服务能补处理之前漏掉的媒体)
for entry in os.listdir(cfg.source):
p = os.path.join(cfg.source, entry)
if os.path.isdir(p) or clean_ext(p) in VIDEO_EXTS:
worker.handle(p)
if args.once:
log("存量扫描完成,退出")
return
# 常驻监听
handler = MediaHandler(worker)
observer = Observer()
observer.schedule(handler, cfg.source, recursive=False)
observer.start()
log(f"开始监听: {cfg.source} -> 成品目录: {cfg.dest}")
try:
while True:
time.sleep(2)
except KeyboardInterrupt:
observer.stop()
observer.join()
if __name__ == "__main__":
main()
+101
View File
@@ -0,0 +1,101 @@
# 自研媒体刮削监听服务 —— 使用说明
一个 Python 服务:监听「清理后媒体目录」,新媒体出现自动刮削(TMDB),结果**复制**落库到成品目录。
已在本机 macOS 用 mock 模式跑通整条链路(监听 → 识别 → 刮削 → 复制落库)。
## 文件清单
| 文件 | 职责 |
|---|---|
| `media_scraper.py` | 核心刮削器:文件名解析 → TMDB 查询 → 生成 nfo(Kodi规范) → 下载海报 → 复制落库 |
| `watcher.py` | 监听服务:watchdog 监听清理目录,写入稳定后自动触发刮削 |
| `config.json` | 配置:源目录、成品目录、TMDB Key、mock 开关 |
| `.venv/` | 本地 Python 环境(已装 watchdog、requests) |
## 快速上手(本地 macOS)
```bash
# 1) 已准备好 .venv(watchdog、requests 已装)。若新环境:
python3 -m venv .venv
./.venv/bin/pip install watchdog requests
# 2) 先 mock 跑通管线(无需 Key,验证 nfo 生成 + 复制落库)
./.venv/bin/python watcher.py --config config.json --once
# 3) 配好 TMDB Key 后真刮削
# 在 config.json 填 tmdb_api_key,并把 "mock": true 改成 false
```
## 配置(config.json)
```json
{
"source": "/vol1/media/cleaned", // 你的清理后媒体目录(media_final.py 的输出)
"dest": "/vol1/media/library", // 成品落库目录(刮削+复制后)
"tmdb_api_key": "", // TMDB API Key(themoviedb.org/settings/api 免费申请)
"mock": true, // true=模拟元数据;配好 Key 后改 false
"settle": 6, // 写入稳定等待秒数(大文件拷贝完再处理)
"language": "zh-CN" // 刮削文案语言
}
```
> `mock: true` 时不需要 Key,用于无网络/无 Key 环境下验证整条管线;正式使用务必 `mock: false` + 填 Key。
## 部署到飞牛 fnOS
飞牛基于 Linux(Debian)。推荐用 Python3 + systemd(或直接用容器把本目录挂进去跑)。
```bash
cd /你的项目目录
python3 -m venv .venv
.venv/bin/pip install watchdog requests
# 编辑 config.json,把 source/dest 改成飞牛上的真实路径,填 TMDB Key,mock 改 false
# 常驻运行(前台,Ctrl+C 停止)
.venv/bin/python watcher.py --config config.json
# 后台常驻(nohup)
nohup .venv/bin/python watcher.py --config config.json > scraper.out 2>&1 &
# 或用 systemd 自启(推荐)
# 项目里已附 media-scraper.service:先把它里面 3 处「/你的项目绝对路径」改成飞牛真实路径
sudo cp media-scraper.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now media-scraper # 开机自启 + 立即启动
journalctl -u media-scraper -f # 看日志
```
## 命令行用法(media_scraper.py 单条/批量)
```bash
# 处理单个媒体文件或目录
./.venv/bin/python media_scraper.py --source "阿凡达(2009).mkv" --dest /成品目录
# 递归处理某目录下所有新媒体
./.venv/bin/python media_scraper.py --source /清理目录 --dest /成品目录 --recurse
# 预览不落盘
./.venv/bin/python media_scraper.py --source xx --dest yy --dry-run
# mock 模式(无 Key 验证)
./.venv/bin/python media_scraper.py --source xx --dest yy --mock
```
## 行为与命名约定
- **电影**:单文件 `阿凡达(2009).mkv` 或电影目录 → 复制后生成 `阿凡达(2009).nfo` + 海报。
- **剧集**:目录内文件带 `S01E01` / `第01集` / `E01` → 识别为剧集 → 生成 `tvshow.nfo` + 每集 `xxx.nfo` + 海报。
- **落库方式**:始终「复制」,源目录保持原样、不写入任何文件。
- **安全保护**:目标路径若与源相同会直接报错终止,绝不误删源目录。
## 已知限制(诚实说明)
- 数据源仅 TMDB 单一来源;冷门片/非主流命名可能匹配不准。
- 海报下载依赖能访问 TMDB 图片服务器;国内网络可能需代理或换 TMDB 备用源。
- 单集文件若无季信息默认按第 1 季处理;建议目录按「剧名(年份)/剧名.SxxExx.mkv」组织识别最准。
- nfo 字段已覆盖 title/year/rating/plot/uniqueid/genre/**director/studio/actor** 等核心项;如需更多字段可再扩展。演员、导演、制片厂来自 TMDB credits 接口,连不上时为空白但不影响 nfo 生成。
## 验证方式
- 本机已用 mock 跑通:电影、剧集目录、单集均正确复制 + 生成 nfo,且实时监听投放新文件能自动触发刮削落库。
- 部署后自查:往 `source` 丢一个清理后的影片,几秒后检查 `dest` 是否出现「媒体副本 + .nfo(+ 海报)」。
@@ -0,0 +1,2 @@
SecretId,SecretKey
AKIDh8RvFOL6h6JI3av2ykJemhPvEMMp7E7p,Yu30sY0HNIYeXHpDOL6g2XxCG8nNkxzs
1 SecretId SecretKey
2 AKIDh8RvFOL6h6JI3av2ykJemhPvEMMp7E7p Yu30sY0HNIYeXHpDOL6g2XxCG8nNkxzs
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
+280
View File
@@ -0,0 +1,280 @@
.timeline.spaced-lines ul:not(ul ul) > li:nth-child(3n) p {
line-height: 1.7rem;
}
.timeline {
--timeline-active-color: var(--background-modifier-success);
}
.timeline.active-color-background-modifier-success {
--timeline-active-color: var(--background-modifier-success);
}
.timeline.active-color-background-modifier-error {
--timeline-active-color: var(--background-modifier-error);
}
.timeline.active-color-background-modifier-error-hover {
--timeline-active-color: var(--background-modifier-error-hover);
}
.timeline.active-color-text-accent {
--timeline-active-color: var(--text-accent);
}
.timeline.active-color-text-accent-hover {
--timeline-active-color: var(--text-accent-hover);
}
.timeline.active-color-text-error {
--timeline-active-color: var(--text-error);
}
.timeline.active-color-text-error-hover {
--timeline-active-color: var(--text-error-hover);
}
.timeline.active-color-text-selection {
--timeline-active-color: var(--text-selection);
}
.timeline.active-color-interactive-accent {
--timeline-active-color: var(--interactive-accent);
}
.timeline.active-color-interactive-accent-hover {
--timeline-active-color: var(--interactive-accent-hover);
}
.timeline.active-color-interactive-success {
--timeline-active-color: var(--interactive-success);
}
.timeline ul:not(ul ul) {
display: grid;
grid-template-columns: auto auto 1fr;
column-gap: 1.5rem;
margin: 2.3rem 0;
}
.timeline ul:not(ul ul) > li {
list-style: none;
}
.timeline ul:not(ul ul) > li > *:first-child {
margin-top: 0;
}
.timeline ul:not(ul ul) > li > *:last-child {
margin-bottom: 0;
}
.timeline ul:not(ul ul) > li:nth-child(3n), .timeline ul:not(ul ul) > li:nth-child(3n+2) {
grid-column: 3;
}
.timeline ul:not(ul ul) > li:nth-child(3n+1), .timeline ul:not(ul ul) > li:nth-child(3n+2) {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0.4em 0;
font-size: 1.3rem;
font-weight: bold;
}
.timeline ul:not(ul ul) > li:nth-child(3n+1) > *, .timeline ul:not(ul ul) > li:nth-child(3n+2) > * {
font-size: 1.3rem;
font-weight: bold;
}
.timeline ul:not(ul ul) > li:nth-child(3n+1) {
grid-column: 1;
position: relative;
justify-self: right;
text-align: right;
}
.timeline ul:not(ul ul) > li:nth-child(3n+1)::before, .timeline ul:not(ul ul) > li:nth-child(3n+1)::after {
content: " ";
position: absolute;
height: 100%;
width: 0.5rem;
right: -2rem;
top: 0;
}
.timeline ul:not(ul ul) > li:nth-child(3n+1)::before {
background-color: var(--background-primary);
}
.timeline ul:not(ul ul) > li:nth-child(3n+1)::after {
background-color: var(--text-normal);
opacity: 0.25;
}
.timeline ul:not(ul ul) > li:nth-child(3n) {
position: relative;
margin-bottom: 4.5rem;
padding-top: 0.4em;
}
.timeline ul:not(ul ul) > li:nth-child(3n)::after {
content: " ";
position: absolute;
border-bottom: 0.1rem dashed var(--text-normal);
opacity: 0.1;
width: 100%;
left: 0;
bottom: -2.25rem;
transform: translateY(50%);
}
.timeline ul:not(ul ul) > li:nth-child(3n):last-child {
margin-bottom: 0.4em;
}
.timeline ul:not(ul ul) > li:nth-child(3n):last-child::after {
display: none;
}
.timeline ul:not(ul ul)::before {
content: "";
height: 100%;
width: 0.5rem;
grid-column: 2/span 1;
grid-row-start: 1;
grid-row-end: span 1000;
background-color: var(--text-normal);
opacity: 0.1;
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n+2), .timeline.body-2 ul:not(ul ul) > li:nth-child(3n), .timeline.body-3 ul:not(ul ul) > li:nth-child(3n+2), .timeline.body-3 ul:not(ul ul) > li:nth-child(3n), .timeline.body-4 ul:not(ul ul) > li:nth-child(3n+2), .timeline.body-4 ul:not(ul ul) > li:nth-child(3n) {
background-color: var(--background-primary-alt);
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n), .timeline.body-3 ul:not(ul ul) > li:nth-child(3n), .timeline.body-4 ul:not(ul ul) > li:nth-child(3n) {
margin-bottom: 2.25rem;
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n):last-child, .timeline.body-3 ul:not(ul ul) > li:nth-child(3n):last-child, .timeline.body-4 ul:not(ul ul) > li:nth-child(3n):last-child {
margin-bottom: 0.4em;
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n)::after, .timeline.body-3 ul:not(ul ul) > li:nth-child(3n)::after, .timeline.body-4 ul:not(ul ul) > li:nth-child(3n)::after {
display: none;
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n), .timeline.body-2 ul:not(ul ul) > li:nth-child(3n+2), .timeline.body-4 ul:not(ul ul) > li:nth-child(3n), .timeline.body-4 ul:not(ul ul) > li:nth-child(3n+2) {
padding: 1.5rem;
padding-top: 0.4em;
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n+2), .timeline.body-4 ul:not(ul ul) > li:nth-child(3n+2) {
padding-bottom: 0;
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n+1), .timeline.body-4 ul:not(ul ul) > li:nth-child(3n+1) {
margin-top: 0.4em;
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n+2) {
border-radius: 1.5rem 1.5rem 0 0;
}
.timeline.body-2 ul:not(ul ul) > li:nth-child(3n) {
border-radius: 0 0 1.5rem 1.5rem;
}
.timeline.body-3 ul:not(ul ul) > li:nth-child(3n+2), .timeline.body-3 ul:not(ul ul) > li:nth-child(3n) {
margin-left: 1rem;
}
.timeline.body-3 ul:not(ul ul) > li:nth-child(3n+2) {
position: relative;
background: var(--timeline-active-color);
padding-left: 1.5rem;
padding-right: 1.5rem;
}
.timeline.body-3 ul:not(ul ul) > li:nth-child(3n+2)::before {
content: "";
position: absolute;
width: 2rem;
background: var(--timeline-active-color);
top: 0;
bottom: 0;
left: -1rem;
clip-path: polygon(1rem 0, 100% 0, 100% 100%, 1rem 100%, 0 50%);
}
.timeline.body-3 ul:not(ul ul) > li:nth-child(3n) {
padding: 1.5rem;
}
.timeline.body-4 ul:not(ul ul) > li:nth-child(3n+2), .timeline.body-4 ul:not(ul ul) > li:nth-child(3n) {
border-left: 0.3rem solid var(--timeline-active-color);
}
.timeline.line-2 ul:not(ul ul) > li:nth-child(3n+1)::before, .timeline.line-2 ul:not(ul ul) > li:nth-child(3n+1)::after {
right: -2.2rem;
top: 50%;
transform: translateY(-50%);
border-radius: 50%;
}
.timeline.line-2 ul:not(ul ul) > li:nth-child(3n+1)::before {
height: 1.2rem;
width: 1.2rem;
}
.timeline.line-2 ul:not(ul ul) > li:nth-child(3n+1)::after {
background: transparent;
border: 0.2rem solid var(--text-normal);
height: 0.8rem;
width: 0.8rem;
opacity: 0.15;
}
.timeline.line-2 ul:not(ul ul)::before {
width: 0.2rem;
opacity: 0.15;
}
.timeline.line-3 ul:not(ul ul) > li:nth-child(3n+1)::before {
background: var(--timeline-active-color);
height: 1rem;
width: 1rem;
border: 0.3rem solid var(--background-primary);
right: -2.45rem;
top: 50%;
transform: translateY(-50%);
border-radius: 50%;
}
.timeline.line-3 ul:not(ul ul) > li:nth-child(3n+1)::after {
background: transparent;
}
.timeline.line-3 ul:not(ul ul)::before {
width: 0.3rem;
opacity: 0.15;
}
.timeline.line-4 ul:not(ul ul) > li:nth-child(3n+1)::before, .timeline.line-4 ul:not(ul ul) > li:nth-child(3n+1)::after {
top: 50%;
transform: translateY(-50%);
border-radius: 50%;
}
.timeline.line-4 ul:not(ul ul) > li:nth-child(3n+1)::before {
background: var(--text-normal);
height: 1.3rem;
width: 1.3rem;
right: -2.225rem;
}
.timeline.line-4 ul:not(ul ul) > li:nth-child(3n+1)::after {
opacity: 1;
background: var(--timeline-active-color);
height: 0.85rem;
width: 0.85rem;
right: -2rem;
}
.timeline.line-4 ul:not(ul ul)::before {
opacity: 1;
width: 0.15rem;
background-color: transparent;
background-image: linear-gradient(var(--text-normal) 60%, rgba(255, 255, 255, 0) 0%);
background-position: right;
background-size: 0.15rem 1.5rem;
background-repeat: repeat-y;
}
.timeline.line-5 ul:not(ul ul) > li:nth-child(3n+1)::before, .timeline.line-5 ul:not(ul ul) > li:nth-child(3n+1)::after {
top: 50%;
}
.timeline.line-5 ul:not(ul ul) > li:nth-child(3n+1)::before {
width: 3rem;
height: 3rem;
right: -3.1rem;
transform: translateY(-50%);
}
.timeline.line-5 ul:not(ul ul) > li:nth-child(3n+1)::after {
width: 1rem;
height: 1rem;
right: 0;
transform: translateY(-50%) translateX(2.1rem) rotate(45deg);
}
.timeline.line-5 ul:not(ul ul)::before {
width: 0.2rem;
opacity: 0.25;
}
+1
View File
@@ -0,0 +1 @@
{"error":{"code":4401},"success":false}
File diff suppressed because it is too large Load Diff
+1898
View File
File diff suppressed because it is too large Load Diff
+413
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
+59
View File
@@ -0,0 +1,59 @@
services:
mysql:
image: mysql:8.0
container_name: t3fap-mysql
restart: always
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_0900_ai_ci
environment:
MYSQL_DATABASE: t3mt_next
MYSQL_USER: t3mt
MYSQL_PASSWORD: change_me
MYSQL_ROOT_PASSWORD: change_root_me
TZ: Asia/Shanghai
volumes:
- ./mysql-data:/var/lib/mysql
healthcheck:
test:
[
"CMD-SHELL",
"mysqladmin ping -h 127.0.0.1 -uroot -p\"$$MYSQL_ROOT_PASSWORD\" --silent",
]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
networks:
- t3fap_net
t3fap:
image: ghcr.io/qq85423296/t3fap
container_name: t3fap
restart: always
depends_on:
mysql:
condition: service_healthy
ports:
- "8521:8521"
environment:
TZ: Asia/Shanghai
T3MT_ENV: production
T3MT_LOG_LEVEL: INFO
T3MT_PUBLIC_BASE_URL: http://127.0.0.1:8521
T3MT_DATABASE_URL: mysql+pymysql://t3mt:change_me@mysql:3306/t3mt_next?charset=utf8mb4
T3MT_ENABLE_QQBOT_GATEWAY: "0"
T3MT_QQBOT_GATEWAY_RETRY_SECONDS: "15"
volumes:
- ./logs:/app/storage/logs
- ./packages:/app/storage/packages
- ./runtime:/app/storage/runtime
- ./downloads:/app/backend/downloads
security_opt:
- apparmor:unconfined
networks:
- t3fap_net
networks:
t3fap_net:
driver: bridge
+21
View File
@@ -0,0 +1,21 @@
services:
t3fap:
image: ghcr.io/qq85423296/t3fap
container_name: t3fap
restart: always
ports:
- "8521:8521"
environment:
TZ: Asia/Shanghai
T3MT_ENV: production
T3MT_LOG_LEVEL: INFO
T3MT_PUBLIC_BASE_URL: http://127.0.0.1:8521
T3MT_DATABASE_URL: sqlite:////app/storage/runtime/t3mt-next.db
T3MT_ENABLE_QQBOT_GATEWAY: "0"
volumes:
- ./logs:/app/storage/logs
- ./packages:/app/storage/packages
- ./runtime:/app/storage/runtime
- ./downloads:/app/backend/downloads
security_opt:
- apparmor:unconfined
+832
View File
@@ -0,0 +1,832 @@
mixed-port: 7890
allow-lan: true
mode: rule
bind-address: '*'
log-level: info
external-controller: 0.0.0.0:9090
unified-delay: true
ipv6: false
profile:
store-selected: true
tun:
mtu: 1500
dns:
enable: true
ipv6: true
use-system-hosts: false
listen: '127.0.0.1:5335'
default-nameserver: [180.76.76.76, 182.254.118.118, 8.8.8.8, 180.184.2.2]
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter: ['*.lan', 'stun.*.*.*', 'stun.*.*', time.windows.com, time.nist.gov, time.apple.com, time.asia.apple.com, '*.ntp.org.cn', '*.openwrt.pool.ntp.org', time1.cloud.tencent.com, time.ustc.edu.cn, pool.ntp.org, ntp.ubuntu.com, ntp.aliyun.com, ntp1.aliyun.com, ntp2.aliyun.com, ntp3.aliyun.com, ntp4.aliyun.com, ntp5.aliyun.com, ntp6.aliyun.com, ntp7.aliyun.com, time1.aliyun.com, time2.aliyun.com, time3.aliyun.com, time4.aliyun.com, time5.aliyun.com, time6.aliyun.com, time7.aliyun.com, '*.time.edu.cn', time1.apple.com, time2.apple.com, time3.apple.com, time4.apple.com, time5.apple.com, time6.apple.com, time7.apple.com, time1.google.com, time2.google.com, time3.google.com, time4.google.com, music.163.com, '*.music.163.com', '*.126.net', musicapi.taihe.com, music.taihe.com, songsearch.kugou.com, trackercdn.kugou.com, '*.kuwo.cn', api-jooxtt.sanook.com, api.joox.com, joox.com, y.qq.com, '*.y.qq.com', streamoc.music.tc.qq.com, mobileoc.music.tc.qq.com, isure.stream.qqmusic.qq.com, dl.stream.qqmusic.qq.com, aqqmusic.tc.qq.com, amobile.music.tc.qq.com, '*.xiami.com', '*.music.migu.cn', music.migu.cn, '*.msftconnecttest.com', '*.msftncsi.com', localhost.ptlogin2.qq.com, '*.*.*.srv.nintendo.net', '*.*.stun.playstation.net', 'xbox.*.*.microsoft.com', '*.ipv6.microsoft.com', '*.*.xboxlive.com', '*.cpolar.top','*.picp.net','*.3322.org','*.dscloud.me','*.joyagain.top','*.joyagain.me','*.xicp.cn','*.himan.vip',speedtest.cros.wr.pvp.net]
nameserver: [180.76.76.76, 119.29.29.29, 180.184.1.1, 223.5.5.5, 8.8.8.8, 'https://223.6.6.6/dns-query#h3=true', 'https://dns.alidns.com/dns-query', 'https://cloudflare-dns.com/dns-query', 'https://doh.pub/dns-query']
fallback-filter: { geoip: true, ipcidr: [240.0.0.0/4, 0.0.0.0/32, 127.0.0.1/32], domain: [+.google.com, +.facebook.com, +.twitter.com, +.youtube.com, +.xn--ngstr-lra8j.com, +.google.cn, +.googleapis.cn, +.googleapis.com, +.gvt1.com] }
proxies:
- { name: '🌏自动最优线路(hy2)-网址: www.dg6.me', type: hysteria2, server: cluster.cloudfrontcdn.com, port: 25948, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: '🌏自动最优线路(AnyTLS)-网址: www.dg6.me', type: anytls, server: cluster.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇯🇵6日本-连通/移动(hy2), type: hysteria2, server: 6jp.cloudfrontcdn.com, port: 22162, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇯🇵6日本-连通/移动(AnyTLS), type: anytls, server: 6jp.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇯🇵7日本-联通/移动(hy2), type: hysteria2, server: 7jp.cloudfrontcdn.com, port: 25118, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇯🇵7日本-联通/移动(AnyTLS), type: anytls, server: 7jp.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇯🇵10日本-全网优化(hy2), type: hysteria2, server: 10jp.cloudfrontcdn.com, port: 25761, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇯🇵10日本-全网优化(AnyTLS), type: anytls, server: 10jp.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇰🇷8韩国集群-全网优化(hy2), type: hysteria2, server: 8kr.cloudfrontcdn.com, port: 22558, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇰🇷8韩国集群-全网优化(AnyTLS), type: anytls, server: 8kr.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇰🇷9韩国-全网优化(hy2), type: hysteria2, server: 9kr.cloudfrontcdn.com, port: 21074, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇰🇷9韩国-全网优化(AnyTLS), type: anytls, server: 9kr.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇰🇷25韩国-全网优化(hy2), type: hysteria2, server: 25kr.cloudfrontcdn.com, port: 24714, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇰🇷25韩国-全网优化(AnyTLS), type: anytls, server: 25kr.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇺🇸11美国西集群-全网优化(hy2), type: hysteria2, server: 11us.cloudfrontcdn.com, port: 23124, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇺🇸11美国西集群-全网优化(AnyTLS), type: anytls, server: 11us.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇺🇸12美国凤凰城-全网优化(hy2), type: hysteria2, server: 12us.cloudfrontcdn.com, port: 21148, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇺🇸12美国凤凰城-全网优化(AnyTLS), type: anytls, server: 12us.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇺🇸29美国旧金山-全网优化(hy2), type: hysteria2, server: 29us.cloudfrontcdn.com, port: 22289, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇺🇸29美国旧金山-全网优化(AnyTLS), type: anytls, server: 29us.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇺🇸39美国华盛顿-全网优化(hy2), type: hysteria2, server: 39us.cloudfrontcdn.com, port: 24627, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇺🇸39美国华盛顿-全网优化(AnyTLS), type: anytls, server: 39us.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇦🇪13迪拜-电信/移动/南方联通(hy2), type: hysteria2, server: 13dxb.cloudfrontcdn.com, port: 24189, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇦🇪13迪拜-电信/移动/南方联通(AnyTLS), type: anytls, server: 13dxb.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇮🇳14印度-移动/南方联通(hy2), type: hysteria2, server: 14in.cloudfrontcdn.com, port: 23335, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇮🇳14印度-移动/南方联通(AnyTLS), type: anytls, server: 14in.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇸🇬15新加坡-全网优化(hy2), type: hysteria2, server: 15sg.cloudfrontcdn.com, port: 23753, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇸🇬15新加坡-全网优化(AnyTLS), type: anytls, server: 15sg.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇸🇬24新加坡-联通/移动(hy2), type: hysteria2, server: 24sg.cloudfrontcdn.com, port: 23987, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇸🇬24新加坡-联通/移动(AnyTLS), type: anytls, server: 24sg.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇩🇪16德国-电信/联通(hy2), type: hysteria2, server: 16de.cloudfrontcdn.com, port: 24200, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇩🇪16德国-电信/联通(AnyTLS), type: anytls, server: 16de.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇬🇧17英国-全网优化(hy2), type: hysteria2, server: 17uk.cloudfrontcdn.com, port: 22675, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇬🇧17英国-全网优化(AnyTLS), type: anytls, server: 17uk.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇨🇦18加拿大-全网优化(hy2), type: hysteria2, server: 18ca.cloudfrontcdn.com, port: 24663, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇨🇦18加拿大-全网优化(AnyTLS), type: anytls, server: 18ca.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇨🇦26加拿大-全网优化(hy2), type: hysteria2, server: 26ca.cloudfrontcdn.com, port: 23256, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇨🇦26加拿大-全网优化(AnyTLS), type: anytls, server: 26ca.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇦🇺19澳洲-移动优化(hy2), type: hysteria2, server: 19sdy.cloudfrontcdn.com, port: 24886, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇦🇺19澳洲-移动优化(AnyTLS), type: anytls, server: 19sdy.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇧🇷20巴西-全网优化(hy2), type: hysteria2, server: 20br.cloudfrontcdn.com, port: 23011, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇧🇷20巴西-全网优化(AnyTLS), type: anytls, server: 20br.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇨🇱21智利-全网优化(hy2), type: hysteria2, server: 21chi.cloudfrontcdn.com, port: 25241, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇨🇱21智利-全网优化(AnyTLS), type: anytls, server: 21chi.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇹🇷22土耳其-全网优化(hy2), type: hysteria2, server: 22tr.cloudfrontcdn.com, port: 23440, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇹🇷22土耳其-全网优化(AnyTLS), type: anytls, server: 22tr.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇫🇷23法国-全网优化(hy2), type: hysteria2, server: 23fr.cloudfrontcdn.com, port: 22562, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇫🇷23法国-全网优化(AnyTLS), type: anytls, server: 23fr.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇲🇽27墨西哥-全网优化(hy2), type: hysteria2, server: 27mx.cloudfrontcdn.com, port: 24799, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇲🇽27墨西哥-全网优化(AnyTLS), type: anytls, server: 27mx.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇳🇱28荷兰-全网优化(hy2), type: hysteria2, server: 28nl.cloudfrontcdn.com, port: 21510, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇳🇱28荷兰-全网优化(AnyTLS), type: anytls, server: 28nl.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇪🇸31西班牙-全网优化(hy2), type: hysteria2, server: 31es.cloudfrontcdn.com, port: 24260, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇪🇸31西班牙-全网优化(AnyTLS), type: anytls, server: 31es.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇷🇺32俄罗斯-全网优化(hy2), type: hysteria2, server: 32ru.cloudfrontcdn.com, port: 22021, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇷🇺32俄罗斯-全网优化(AnyTLS), type: anytls, server: 32ru.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: '🇺🇦40 乌克兰-全网优化(hy2)', type: hysteria2, server: 40ua.cloudfrontcdn.com, port: 21392, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: '🇺🇦40 乌克兰-全网优化(AnyTLS)', type: anytls, server: 40ua.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇨🇭41瑞士-全网优化(hy2), type: hysteria2, server: 41ch.cloudfrontcdn.com, port: 24726, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇨🇭41瑞士-全网优化(AnyTLS), type: anytls, server: 41ch.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇭🇰1香港集群-全网优化(hy2)(限速30M), type: hysteria2, server: 1hk.cloudfrontcdn.com, port: 23542, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, up: 50, down: 100, skip-cert-verify: true }
- { name: 🇯🇵6日本-连通/移动(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17906, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇰🇷8韩国-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17908, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇰🇷9韩国-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17909, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇯🇵10日本-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17910, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇺🇸11美国西集群-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17911, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇺🇸12美国凤凰城-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17912, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇸🇬15新加坡-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17915, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇸🇬24新加坡-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17924, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇰🇷25韩国-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17925, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇦🇺19澳洲-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17919, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇭🇰1香港-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17901, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇭🇰2香港-专线(TCP), type: trojan, server: dnsmart.dg-cdn.mob.networklinkpro.com, port: 17902, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, skip-cert-verify: true, network: ws }
- { name: 🇭🇰1香港集群-全网优化(AnyTLS), type: anytls, server: 1hk.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇭🇰2香港集群-全网优化(hy2)(限速30M), type: hysteria2, server: 2hk.cloudfrontcdn.com, port: 24943, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, up: 30, down: 30, skip-cert-verify: true }
- { name: 🇭🇰3香港集群-全网优化(hy2), type: hysteria2, server: 3hk.cloudfrontcdn.com, port: 21066, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, up: 50, down: 100, skip-cert-verify: true }
- { name: 🇭🇰3香港集群-全网优化(AnyTLS), type: anytls, server: 3hk.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇨🇳4台湾-联通优化(hy2), type: hysteria2, server: 4tw.cloudfrontcdn.com, port: 23576, ports: 21000-26000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: 🇨🇳4台湾-联通优化(AnyTLS), type: anytls, server: 4tw.cloudfrontcdn.com, port: 4430, client-fingerprint: chrome, password: de4f90f7-263c-4a81-af14-2add4630b4d9, udp: true, tfo: true, sni: d2-cn-gotcha204-1.bilivideo.com, skip-cert-verify: true }
- { name: 🇨🇳5台湾-联通/移动(hy2), type: hysteria2, server: 5tw.cloudfrontcdn.com, port: 51164, ports: 50001-55000, password: de4f90f7-263c-4a81-af14-2add4630b4d9, skip-cert-verify: true }
- { name: '🌏自动最优线路(hy1)-网址: www.dg6.me', type: hysteria, server: cluster.cloudfrontcdn.com, port: 9845, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇺🇸11美国西集群-全网优化(hy1), type: hysteria, server: 11us.cloudfrontcdn.com, port: 8221, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇺🇸12美国凤凰城-电信/连通(hy1), type: hysteria, server: 12us.cloudfrontcdn.com, port: 8656, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇺🇸39美国华盛顿-全网优化(hy1), type: hysteria, server: 39us.cloudfrontcdn.com, port: 9738, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇮🇳14印度-移动/南方联通(hy1), type: hysteria, server: 14in.cloudfrontcdn.com, port: 5625, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇸🇬24新加坡-联通/移动(hy1), type: hysteria, server: 24sg.cloudfrontcdn.com, port: 8551, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: false, skip-cert-verify: true }
- { name: 🇩🇪16德国-电信/联通(hy1), type: hysteria, server: 16de.cloudfrontcdn.com, port: 8268, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇬🇧17英国-全网优化(hy1), type: hysteria, server: 17uk.cloudfrontcdn.com, port: 5786, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇨🇦18加拿大-全网优化(hy1), type: hysteria, server: 18ca.cloudfrontcdn.com, port: 8215, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇨🇦26加拿大-全网优化(hy1), type: hysteria, server: 26ca.cloudfrontcdn.com, port: 8948, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇦🇺19澳洲-连通/移动(hy1), type: hysteria, server: 19sdy.cloudfrontcdn.com, port: 7017, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: false, skip-cert-verify: true }
- { name: 🇧🇷20巴西-全网优化(hy1), type: hysteria, server: 20br.cloudfrontcdn.com, port: 9264, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇨🇱21智利-全网优化(hy1), type: hysteria, server: 21chi.cloudfrontcdn.com, port: 8190, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇫🇷23法国-全网优化(hy1), type: hysteria, server: 23fr.cloudfrontcdn.com, port: 7354, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇲🇽27墨西哥-全网优化(hy1), type: hysteria, server: 27mx.cloudfrontcdn.com, port: 7248, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇪🇸31西班牙-全网优化(hy1), type: hysteria, server: 31es.cloudfrontcdn.com, port: 5720, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇭🇰3香港集群-全网优化(hy1), type: hysteria, server: 3hk.cloudfrontcdn.com, port: 6452, ports: 5000-10000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 50, down: 100, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: 🇨🇳5台湾-联通/移动(hy1), type: hysteria, server: 5tw.cloudfrontcdn.com, port: 40541, ports: 40001-45000, auth_str: de4f90f7-263c-4a81-af14-2add4630b4d9, alpn: [h3], protocol: udp, up: 70, down: 150, fast-open: true, disable_mtu_discovery: true, skip-cert-verify: true }
- { name: '官网: www.dg6.me', type: vmess, server: 114.114.114.114, port: 2235, uuid: de4f90f7-263c-4a81-af14-2add4630b4d9, alterId: 0, cipher: auto, udp: true }
proxy-groups:
- { name: 狗狗加速.com, type: select, proxies: [♻️自动选择, 🔯故障转移, hy1, 🐴Trojan, AnyTLS, 🔥ChatGPT, Hysteria2, '🌏自动最优线路(hy2)-网址: www.dg6.me', '🌏自动最优线路(AnyTLS)-网址: www.dg6.me', 🇯🇵6日本-连通/移动(hy2), 🇯🇵6日本-连通/移动(AnyTLS), 🇯🇵7日本-联通/移动(hy2), 🇯🇵7日本-联通/移动(AnyTLS), 🇯🇵10日本-全网优化(hy2), 🇯🇵10日本-全网优化(AnyTLS), 🇰🇷8韩国集群-全网优化(hy2), 🇰🇷8韩国集群-全网优化(AnyTLS), 🇰🇷9韩国-全网优化(hy2), 🇰🇷9韩国-全网优化(AnyTLS), 🇰🇷25韩国-全网优化(hy2), 🇰🇷25韩国-全网优化(AnyTLS), 🇺🇸11美国西集群-全网优化(hy2), 🇺🇸11美国西集群-全网优化(AnyTLS), 🇺🇸12美国凤凰城-全网优化(hy2), 🇺🇸12美国凤凰城-全网优化(AnyTLS), 🇺🇸29美国旧金山-全网优化(hy2), 🇺🇸29美国旧金山-全网优化(AnyTLS), 🇺🇸39美国华盛顿-全网优化(hy2), 🇺🇸39美国华盛顿-全网优化(AnyTLS), 🇦🇪13迪拜-电信/移动/南方联通(hy2), 🇦🇪13迪拜-电信/移动/南方联通(AnyTLS), 🇮🇳14印度-移动/南方联通(hy2), 🇮🇳14印度-移动/南方联通(AnyTLS), 🇸🇬15新加坡-全网优化(hy2), 🇸🇬15新加坡-全网优化(AnyTLS), 🇸🇬24新加坡-联通/移动(hy2), 🇸🇬24新加坡-联通/移动(AnyTLS), 🇩🇪16德国-电信/联通(hy2), 🇩🇪16德国-电信/联通(AnyTLS), 🇬🇧17英国-全网优化(hy2), 🇬🇧17英国-全网优化(AnyTLS), 🇨🇦18加拿大-全网优化(hy2), 🇨🇦18加拿大-全网优化(AnyTLS), 🇨🇦26加拿大-全网优化(hy2), 🇨🇦26加拿大-全网优化(AnyTLS), 🇦🇺19澳洲-移动优化(hy2), 🇦🇺19澳洲-移动优化(AnyTLS), 🇧🇷20巴西-全网优化(hy2), 🇧🇷20巴西-全网优化(AnyTLS), 🇨🇱21智利-全网优化(hy2), 🇨🇱21智利-全网优化(AnyTLS), 🇹🇷22土耳其-全网优化(hy2), 🇹🇷22土耳其-全网优化(AnyTLS), 🇫🇷23法国-全网优化(hy2), 🇫🇷23法国-全网优化(AnyTLS), 🇲🇽27墨西哥-全网优化(hy2), 🇲🇽27墨西哥-全网优化(AnyTLS), 🇳🇱28荷兰-全网优化(hy2), 🇳🇱28荷兰-全网优化(AnyTLS), 🇪🇸31西班牙-全网优化(hy2), 🇪🇸31西班牙-全网优化(AnyTLS), 🇷🇺32俄罗斯-全网优化(hy2), 🇷🇺32俄罗斯-全网优化(AnyTLS), '🇺🇦40 乌克兰-全网优化(hy2)', '🇺🇦40 乌克兰-全网优化(AnyTLS)', 🇨🇭41瑞士-全网优化(hy2), 🇨🇭41瑞士-全网优化(AnyTLS), 🇭🇰1香港集群-全网优化(hy2)(限速30M), 🇯🇵6日本-连通/移动(TCP), 🇰🇷8韩国-专线(TCP), 🇰🇷9韩国-专线(TCP), 🇯🇵10日本-专线(TCP), 🇺🇸11美国西集群-专线(TCP), 🇺🇸12美国凤凰城-专线(TCP), 🇸🇬15新加坡-专线(TCP), 🇸🇬24新加坡-专线(TCP), 🇰🇷25韩国-专线(TCP), 🇦🇺19澳洲-专线(TCP), 🇭🇰1香港-专线(TCP), 🇭🇰2香港-专线(TCP), 🇭🇰1香港集群-全网优化(AnyTLS), 🇭🇰2香港集群-全网优化(hy2)(限速30M), 🇭🇰3香港集群-全网优化(hy2), 🇭🇰3香港集群-全网优化(AnyTLS), 🇨🇳4台湾-联通优化(hy2), 🇨🇳4台湾-联通优化(AnyTLS), 🇨🇳5台湾-联通/移动(hy2), '🌏自动最优线路(hy1)-网址: www.dg6.me', 🇺🇸11美国西集群-全网优化(hy1), 🇺🇸12美国凤凰城-电信/连通(hy1), 🇺🇸39美国华盛顿-全网优化(hy1), 🇮🇳14印度-移动/南方联通(hy1), 🇸🇬24新加坡-联通/移动(hy1), 🇩🇪16德国-电信/联通(hy1), 🇬🇧17英国-全网优化(hy1), 🇨🇦18加拿大-全网优化(hy1), 🇨🇦26加拿大-全网优化(hy1), 🇦🇺19澳洲-连通/移动(hy1), 🇧🇷20巴西-全网优化(hy1), 🇨🇱21智利-全网优化(hy1), 🇫🇷23法国-全网优化(hy1), 🇲🇽27墨西哥-全网优化(hy1), 🇪🇸31西班牙-全网优化(hy1), 🇭🇰3香港集群-全网优化(hy1), 🇨🇳5台湾-联通/移动(hy1), '官网: www.dg6.me'] }
- { name: ♻️自动选择, type: url-test, proxies: ['🌏自动最优线路(hy2)-网址: www.dg6.me', '🌏自动最优线路(AnyTLS)-网址: www.dg6.me', 🇯🇵6日本-连通/移动(hy2), 🇯🇵6日本-连通/移动(AnyTLS), 🇯🇵7日本-联通/移动(hy2), 🇯🇵7日本-联通/移动(AnyTLS), 🇯🇵10日本-全网优化(hy2), 🇯🇵10日本-全网优化(AnyTLS), 🇰🇷8韩国集群-全网优化(hy2), 🇰🇷8韩国集群-全网优化(AnyTLS), 🇰🇷9韩国-全网优化(hy2), 🇰🇷9韩国-全网优化(AnyTLS), 🇰🇷25韩国-全网优化(hy2), 🇰🇷25韩国-全网优化(AnyTLS), 🇺🇸11美国西集群-全网优化(hy2), 🇺🇸11美国西集群-全网优化(AnyTLS), 🇺🇸12美国凤凰城-全网优化(hy2), 🇺🇸12美国凤凰城-全网优化(AnyTLS), 🇺🇸29美国旧金山-全网优化(hy2), 🇺🇸29美国旧金山-全网优化(AnyTLS), 🇺🇸39美国华盛顿-全网优化(hy2), 🇺🇸39美国华盛顿-全网优化(AnyTLS), 🇦🇪13迪拜-电信/移动/南方联通(hy2), 🇦🇪13迪拜-电信/移动/南方联通(AnyTLS), 🇮🇳14印度-移动/南方联通(hy2), 🇮🇳14印度-移动/南方联通(AnyTLS), 🇸🇬15新加坡-全网优化(hy2), 🇸🇬15新加坡-全网优化(AnyTLS), 🇸🇬24新加坡-联通/移动(hy2), 🇸🇬24新加坡-联通/移动(AnyTLS), 🇩🇪16德国-电信/联通(hy2), 🇩🇪16德国-电信/联通(AnyTLS), 🇬🇧17英国-全网优化(hy2), 🇬🇧17英国-全网优化(AnyTLS), 🇨🇦18加拿大-全网优化(hy2), 🇨🇦18加拿大-全网优化(AnyTLS), 🇨🇦26加拿大-全网优化(hy2), 🇨🇦26加拿大-全网优化(AnyTLS), 🇦🇺19澳洲-移动优化(hy2), 🇦🇺19澳洲-移动优化(AnyTLS), 🇧🇷20巴西-全网优化(hy2), 🇧🇷20巴西-全网优化(AnyTLS), 🇨🇱21智利-全网优化(hy2), 🇨🇱21智利-全网优化(AnyTLS), 🇹🇷22土耳其-全网优化(hy2), 🇹🇷22土耳其-全网优化(AnyTLS), 🇫🇷23法国-全网优化(hy2), 🇫🇷23法国-全网优化(AnyTLS), 🇲🇽27墨西哥-全网优化(hy2), 🇲🇽27墨西哥-全网优化(AnyTLS), 🇳🇱28荷兰-全网优化(hy2), 🇳🇱28荷兰-全网优化(AnyTLS), 🇪🇸31西班牙-全网优化(hy2), 🇪🇸31西班牙-全网优化(AnyTLS), 🇷🇺32俄罗斯-全网优化(hy2), 🇷🇺32俄罗斯-全网优化(AnyTLS), '🇺🇦40 乌克兰-全网优化(hy2)', '🇺🇦40 乌克兰-全网优化(AnyTLS)', 🇨🇭41瑞士-全网优化(hy2), 🇨🇭41瑞士-全网优化(AnyTLS), 🇭🇰1香港集群-全网优化(hy2)(限速30M), 🇯🇵6日本-连通/移动(TCP), 🇰🇷8韩国-专线(TCP), 🇰🇷9韩国-专线(TCP), 🇯🇵10日本-专线(TCP), 🇺🇸11美国西集群-专线(TCP), 🇺🇸12美国凤凰城-专线(TCP), 🇸🇬15新加坡-专线(TCP), 🇸🇬24新加坡-专线(TCP), 🇰🇷25韩国-专线(TCP), 🇦🇺19澳洲-专线(TCP), 🇭🇰1香港-专线(TCP), 🇭🇰2香港-专线(TCP), 🇭🇰1香港集群-全网优化(AnyTLS), 🇭🇰2香港集群-全网优化(hy2)(限速30M), 🇭🇰3香港集群-全网优化(hy2), 🇭🇰3香港集群-全网优化(AnyTLS), 🇨🇳4台湾-联通优化(hy2), 🇨🇳4台湾-联通优化(AnyTLS), 🇨🇳5台湾-联通/移动(hy2), '🌏自动最优线路(hy1)-网址: www.dg6.me', 🇺🇸11美国西集群-全网优化(hy1), 🇺🇸12美国凤凰城-电信/连通(hy1), 🇺🇸39美国华盛顿-全网优化(hy1), 🇮🇳14印度-移动/南方联通(hy1), 🇸🇬24新加坡-联通/移动(hy1), 🇩🇪16德国-电信/联通(hy1), 🇬🇧17英国-全网优化(hy1), 🇨🇦18加拿大-全网优化(hy1), 🇨🇦26加拿大-全网优化(hy1), 🇦🇺19澳洲-连通/移动(hy1), 🇧🇷20巴西-全网优化(hy1), 🇨🇱21智利-全网优化(hy1), 🇫🇷23法国-全网优化(hy1), 🇲🇽27墨西哥-全网优化(hy1), 🇪🇸31西班牙-全网优化(hy1), 🇭🇰3香港集群-全网优化(hy1), 🇨🇳5台湾-联通/移动(hy1), '官网: www.dg6.me'], url: 'http://1.1.1.1', interval: 600 }
- { name: 🔯故障转移, type: fallback, proxies: ['🌏自动最优线路(hy2)-网址: www.dg6.me', '🌏自动最优线路(AnyTLS)-网址: www.dg6.me', 🇯🇵6日本-连通/移动(hy2), 🇯🇵6日本-连通/移动(AnyTLS), 🇯🇵7日本-联通/移动(hy2), 🇯🇵7日本-联通/移动(AnyTLS), 🇯🇵10日本-全网优化(hy2), 🇯🇵10日本-全网优化(AnyTLS), 🇰🇷8韩国集群-全网优化(hy2), 🇰🇷8韩国集群-全网优化(AnyTLS), 🇰🇷9韩国-全网优化(hy2), 🇰🇷9韩国-全网优化(AnyTLS), 🇰🇷25韩国-全网优化(hy2), 🇰🇷25韩国-全网优化(AnyTLS), 🇺🇸11美国西集群-全网优化(hy2), 🇺🇸11美国西集群-全网优化(AnyTLS), 🇺🇸12美国凤凰城-全网优化(hy2), 🇺🇸12美国凤凰城-全网优化(AnyTLS), 🇺🇸29美国旧金山-全网优化(hy2), 🇺🇸29美国旧金山-全网优化(AnyTLS), 🇺🇸39美国华盛顿-全网优化(hy2), 🇺🇸39美国华盛顿-全网优化(AnyTLS), 🇦🇪13迪拜-电信/移动/南方联通(hy2), 🇦🇪13迪拜-电信/移动/南方联通(AnyTLS), 🇮🇳14印度-移动/南方联通(hy2), 🇮🇳14印度-移动/南方联通(AnyTLS), 🇸🇬15新加坡-全网优化(hy2), 🇸🇬15新加坡-全网优化(AnyTLS), 🇸🇬24新加坡-联通/移动(hy2), 🇸🇬24新加坡-联通/移动(AnyTLS), 🇩🇪16德国-电信/联通(hy2), 🇩🇪16德国-电信/联通(AnyTLS), 🇬🇧17英国-全网优化(hy2), 🇬🇧17英国-全网优化(AnyTLS), 🇨🇦18加拿大-全网优化(hy2), 🇨🇦18加拿大-全网优化(AnyTLS), 🇨🇦26加拿大-全网优化(hy2), 🇨🇦26加拿大-全网优化(AnyTLS), 🇦🇺19澳洲-移动优化(hy2), 🇦🇺19澳洲-移动优化(AnyTLS), 🇧🇷20巴西-全网优化(hy2), 🇧🇷20巴西-全网优化(AnyTLS), 🇨🇱21智利-全网优化(hy2), 🇨🇱21智利-全网优化(AnyTLS), 🇹🇷22土耳其-全网优化(hy2), 🇹🇷22土耳其-全网优化(AnyTLS), 🇫🇷23法国-全网优化(hy2), 🇫🇷23法国-全网优化(AnyTLS), 🇲🇽27墨西哥-全网优化(hy2), 🇲🇽27墨西哥-全网优化(AnyTLS), 🇳🇱28荷兰-全网优化(hy2), 🇳🇱28荷兰-全网优化(AnyTLS), 🇪🇸31西班牙-全网优化(hy2), 🇪🇸31西班牙-全网优化(AnyTLS), 🇷🇺32俄罗斯-全网优化(hy2), 🇷🇺32俄罗斯-全网优化(AnyTLS), '🇺🇦40 乌克兰-全网优化(hy2)', '🇺🇦40 乌克兰-全网优化(AnyTLS)', 🇨🇭41瑞士-全网优化(hy2), 🇨🇭41瑞士-全网优化(AnyTLS), 🇭🇰1香港集群-全网优化(hy2)(限速30M), 🇯🇵6日本-连通/移动(TCP), 🇰🇷8韩国-专线(TCP), 🇰🇷9韩国-专线(TCP), 🇯🇵10日本-专线(TCP), 🇺🇸11美国西集群-专线(TCP), 🇺🇸12美国凤凰城-专线(TCP), 🇸🇬15新加坡-专线(TCP), 🇸🇬24新加坡-专线(TCP), 🇰🇷25韩国-专线(TCP), 🇦🇺19澳洲-专线(TCP), 🇭🇰1香港-专线(TCP), 🇭🇰2香港-专线(TCP), 🇭🇰1香港集群-全网优化(AnyTLS), 🇭🇰2香港集群-全网优化(hy2)(限速30M), 🇭🇰3香港集群-全网优化(hy2), 🇭🇰3香港集群-全网优化(AnyTLS), 🇨🇳4台湾-联通优化(hy2), 🇨🇳4台湾-联通优化(AnyTLS), 🇨🇳5台湾-联通/移动(hy2), '🌏自动最优线路(hy1)-网址: www.dg6.me', 🇺🇸11美国西集群-全网优化(hy1), 🇺🇸12美国凤凰城-电信/连通(hy1), 🇺🇸39美国华盛顿-全网优化(hy1), 🇮🇳14印度-移动/南方联通(hy1), 🇸🇬24新加坡-联通/移动(hy1), 🇩🇪16德国-电信/联通(hy1), 🇬🇧17英国-全网优化(hy1), 🇨🇦18加拿大-全网优化(hy1), 🇨🇦26加拿大-全网优化(hy1), 🇦🇺19澳洲-连通/移动(hy1), 🇧🇷20巴西-全网优化(hy1), 🇨🇱21智利-全网优化(hy1), 🇫🇷23法国-全网优化(hy1), 🇲🇽27墨西哥-全网优化(hy1), 🇪🇸31西班牙-全网优化(hy1), 🇭🇰3香港集群-全网优化(hy1), 🇨🇳5台湾-联通/移动(hy1), '官网: www.dg6.me'], url: 'http://1.1.1.1', interval: 450 }
- { name: Hysteria2, type: select, proxies: ['🌏自动最优线路(hy2)-网址: www.dg6.me', 🇯🇵6日本-连通/移动(hy2), 🇯🇵7日本-联通/移动(hy2), 🇯🇵10日本-全网优化(hy2), 🇰🇷8韩国集群-全网优化(hy2), 🇰🇷9韩国-全网优化(hy2), 🇰🇷25韩国-全网优化(hy2), 🇺🇸11美国西集群-全网优化(hy2), 🇺🇸12美国凤凰城-全网优化(hy2), 🇺🇸29美国旧金山-全网优化(hy2), 🇺🇸39美国华盛顿-全网优化(hy2), 🇦🇪13迪拜-电信/移动/南方联通(hy2), 🇮🇳14印度-移动/南方联通(hy2), 🇸🇬15新加坡-全网优化(hy2), 🇸🇬24新加坡-联通/移动(hy2), 🇩🇪16德国-电信/联通(hy2), 🇬🇧17英国-全网优化(hy2), 🇨🇦18加拿大-全网优化(hy2), 🇨🇦26加拿大-全网优化(hy2), 🇦🇺19澳洲-移动优化(hy2), 🇧🇷20巴西-全网优化(hy2), 🇨🇱21智利-全网优化(hy2), 🇹🇷22土耳其-全网优化(hy2), 🇫🇷23法国-全网优化(hy2), 🇲🇽27墨西哥-全网优化(hy2), 🇳🇱28荷兰-全网优化(hy2), 🇪🇸31西班牙-全网优化(hy2), 🇷🇺32俄罗斯-全网优化(hy2), '🇺🇦40 乌克兰-全网优化(hy2)', 🇨🇭41瑞士-全网优化(hy2), 🇭🇰1香港集群-全网优化(hy2)(限速30M), 🇭🇰2香港集群-全网优化(hy2)(限速30M), 🇭🇰3香港集群-全网优化(hy2), 🇨🇳4台湾-联通优化(hy2), 🇨🇳5台湾-联通/移动(hy2)] }
- { name: 🔥ChatGPT, type: select, proxies: ['🌏自动最优线路(hy2)-网址: www.dg6.me', '🌏自动最优线路(AnyTLS)-网址: www.dg6.me', 🇯🇵6日本-连通/移动(hy2), 🇯🇵6日本-连通/移动(AnyTLS), 🇯🇵7日本-联通/移动(hy2), 🇯🇵7日本-联通/移动(AnyTLS), 🇯🇵10日本-全网优化(hy2), 🇯🇵10日本-全网优化(AnyTLS), 🇰🇷8韩国集群-全网优化(hy2), 🇰🇷8韩国集群-全网优化(AnyTLS), 🇰🇷9韩国-全网优化(hy2), 🇰🇷9韩国-全网优化(AnyTLS), 🇰🇷25韩国-全网优化(hy2), 🇰🇷25韩国-全网优化(AnyTLS), 🇺🇸11美国西集群-全网优化(hy2), 🇺🇸11美国西集群-全网优化(AnyTLS), 🇺🇸12美国凤凰城-全网优化(hy2), 🇺🇸12美国凤凰城-全网优化(AnyTLS), 🇺🇸29美国旧金山-全网优化(hy2), 🇺🇸29美国旧金山-全网优化(AnyTLS), 🇺🇸39美国华盛顿-全网优化(hy2), 🇺🇸39美国华盛顿-全网优化(AnyTLS), 🇦🇪13迪拜-电信/移动/南方联通(hy2), 🇦🇪13迪拜-电信/移动/南方联通(AnyTLS), 🇮🇳14印度-移动/南方联通(hy2), 🇮🇳14印度-移动/南方联通(AnyTLS), 🇸🇬15新加坡-全网优化(hy2), 🇸🇬15新加坡-全网优化(AnyTLS), 🇸🇬24新加坡-联通/移动(hy2), 🇸🇬24新加坡-联通/移动(AnyTLS), 🇩🇪16德国-电信/联通(hy2), 🇩🇪16德国-电信/联通(AnyTLS), 🇬🇧17英国-全网优化(hy2), 🇬🇧17英国-全网优化(AnyTLS), 🇨🇦18加拿大-全网优化(hy2), 🇨🇦18加拿大-全网优化(AnyTLS), 🇨🇦26加拿大-全网优化(hy2), 🇨🇦26加拿大-全网优化(AnyTLS), 🇦🇺19澳洲-移动优化(hy2), 🇦🇺19澳洲-移动优化(AnyTLS), 🇧🇷20巴西-全网优化(hy2), 🇧🇷20巴西-全网优化(AnyTLS), 🇨🇱21智利-全网优化(hy2), 🇨🇱21智利-全网优化(AnyTLS), 🇹🇷22土耳其-全网优化(hy2), 🇹🇷22土耳其-全网优化(AnyTLS), 🇫🇷23法国-全网优化(hy2), 🇫🇷23法国-全网优化(AnyTLS), 🇲🇽27墨西哥-全网优化(hy2), 🇲🇽27墨西哥-全网优化(AnyTLS), 🇳🇱28荷兰-全网优化(hy2), 🇳🇱28荷兰-全网优化(AnyTLS), 🇪🇸31西班牙-全网优化(hy2), 🇪🇸31西班牙-全网优化(AnyTLS), '🇺🇦40 乌克兰-全网优化(hy2)', '🇺🇦40 乌克兰-全网优化(AnyTLS)', 🇨🇭41瑞士-全网优化(hy2), 🇨🇭41瑞士-全网优化(AnyTLS), 🇰🇷8韩国-专线(TCP), 🇰🇷9韩国-专线(TCP), 🇯🇵10日本-专线(TCP), 🇺🇸11美国西集群-专线(TCP), 🇺🇸12美国凤凰城-专线(TCP), 🇸🇬15新加坡-专线(TCP), 🇸🇬24新加坡-专线(TCP), 🇰🇷25韩国-专线(TCP), 🇦🇺19澳洲-专线(TCP), '🌏自动最优线路(hy1)-网址: www.dg6.me', 🇺🇸11美国西集群-全网优化(hy1), 🇺🇸12美国凤凰城-电信/连通(hy1), 🇺🇸39美国华盛顿-全网优化(hy1), 🇮🇳14印度-移动/南方联通(hy1), 🇸🇬24新加坡-联通/移动(hy1), 🇩🇪16德国-电信/联通(hy1), 🇬🇧17英国-全网优化(hy1), 🇨🇦18加拿大-全网优化(hy1), 🇨🇦26加拿大-全网优化(hy1), 🇦🇺19澳洲-连通/移动(hy1), 🇧🇷20巴西-全网优化(hy1), 🇨🇱21智利-全网优化(hy1), 🇫🇷23法国-全网优化(hy1), 🇲🇽27墨西哥-全网优化(hy1), 🇪🇸31西班牙-全网优化(hy1), '官网: www.dg6.me'] }
- { name: AnyTLS, type: select, proxies: ['🌏自动最优线路(AnyTLS)-网址: www.dg6.me', 🇯🇵6日本-连通/移动(AnyTLS), 🇯🇵7日本-联通/移动(AnyTLS), 🇯🇵10日本-全网优化(AnyTLS), 🇰🇷8韩国集群-全网优化(AnyTLS), 🇰🇷9韩国-全网优化(AnyTLS), 🇰🇷25韩国-全网优化(AnyTLS), 🇺🇸11美国西集群-全网优化(AnyTLS), 🇺🇸12美国凤凰城-全网优化(AnyTLS), 🇺🇸29美国旧金山-全网优化(AnyTLS), 🇺🇸39美国华盛顿-全网优化(AnyTLS), 🇦🇪13迪拜-电信/移动/南方联通(AnyTLS), 🇮🇳14印度-移动/南方联通(AnyTLS), 🇸🇬15新加坡-全网优化(AnyTLS), 🇸🇬24新加坡-联通/移动(AnyTLS), 🇩🇪16德国-电信/联通(AnyTLS), 🇬🇧17英国-全网优化(AnyTLS), 🇨🇦18加拿大-全网优化(AnyTLS), 🇨🇦26加拿大-全网优化(AnyTLS), 🇦🇺19澳洲-移动优化(AnyTLS), 🇧🇷20巴西-全网优化(AnyTLS), 🇨🇱21智利-全网优化(AnyTLS), 🇹🇷22土耳其-全网优化(AnyTLS), 🇫🇷23法国-全网优化(AnyTLS), 🇲🇽27墨西哥-全网优化(AnyTLS), 🇳🇱28荷兰-全网优化(AnyTLS), 🇪🇸31西班牙-全网优化(AnyTLS), 🇷🇺32俄罗斯-全网优化(AnyTLS), '🇺🇦40 乌克兰-全网优化(AnyTLS)', 🇨🇭41瑞士-全网优化(AnyTLS), 🇭🇰1香港集群-全网优化(AnyTLS), 🇭🇰3香港集群-全网优化(AnyTLS), 🇨🇳4台湾-联通优化(AnyTLS)] }
- { name: 🐴Trojan, type: select, proxies: [🇯🇵6日本-连通/移动(TCP), 🇰🇷8韩国-专线(TCP), 🇰🇷9韩国-专线(TCP), 🇯🇵10日本-专线(TCP), 🇺🇸11美国西集群-专线(TCP), 🇺🇸12美国凤凰城-专线(TCP), 🇸🇬15新加坡-专线(TCP), 🇸🇬24新加坡-专线(TCP), 🇰🇷25韩国-专线(TCP), 🇦🇺19澳洲-专线(TCP), 🇭🇰1香港-专线(TCP), 🇭🇰2香港-专线(TCP)] }
- { name: hy1, type: select, proxies: ['🌏自动最优线路(hy1)-网址: www.dg6.me', 🇺🇸11美国西集群-全网优化(hy1), 🇺🇸12美国凤凰城-电信/连通(hy1), 🇺🇸39美国华盛顿-全网优化(hy1), 🇮🇳14印度-移动/南方联通(hy1), 🇸🇬24新加坡-联通/移动(hy1), 🇩🇪16德国-电信/联通(hy1), 🇬🇧17英国-全网优化(hy1), 🇨🇦18加拿大-全网优化(hy1), 🇨🇦26加拿大-全网优化(hy1), 🇦🇺19澳洲-连通/移动(hy1), 🇧🇷20巴西-全网优化(hy1), 🇨🇱21智利-全网优化(hy1), 🇫🇷23法国-全网优化(hy1), 🇲🇽27墨西哥-全网优化(hy1), 🇪🇸31西班牙-全网优化(hy1), 🇭🇰3香港集群-全网优化(hy1), 🇨🇳5台湾-联通/移动(hy1)] }
rules:
- 'DOMAIN,subapi.doggysub.uk,DIRECT'
- 'PROCESS-NAME,v2ray,DIRECT'
- 'PROCESS-NAME,xray,DIRECT'
- 'PROCESS-NAME,naive,DIRECT'
- 'PROCESS-NAME,trojan,DIRECT'
- 'PROCESS-NAME,trojan-go,DIRECT'
- 'PROCESS-NAME,ss-local,DIRECT'
- 'PROCESS-NAME,privoxy,DIRECT'
- 'PROCESS-NAME,leaf,DIRECT'
- 'PROCESS-NAME,v2ray.exe,DIRECT'
- 'PROCESS-NAME,xray.exe,DIRECT'
- 'PROCESS-NAME,naive.exe,DIRECT'
- 'PROCESS-NAME,trojan.exe,DIRECT'
- 'PROCESS-NAME,trojan-go.exe,DIRECT'
- 'PROCESS-NAME,ss-local.exe,DIRECT'
- 'PROCESS-NAME,privoxy.exe,DIRECT'
- 'PROCESS-NAME,leaf.exe,DIRECT'
- 'PROCESS-NAME,Surge,DIRECT'
- 'PROCESS-NAME,Surge 2,DIRECT'
- 'PROCESS-NAME,Surge 3,DIRECT'
- 'PROCESS-NAME,Surge 4,DIRECT'
- 'PROCESS-NAME,Surge%202,DIRECT'
- 'PROCESS-NAME,Surge%203,DIRECT'
- 'PROCESS-NAME,Surge%204,DIRECT'
- 'PROCESS-NAME,Thunder,DIRECT'
- 'PROCESS-NAME,DownloadService,DIRECT'
- 'PROCESS-NAME,qBittorrent,DIRECT'
- 'PROCESS-NAME,Transmission,DIRECT'
- 'PROCESS-NAME,fdm,DIRECT'
- 'PROCESS-NAME,aria2c,DIRECT'
- 'PROCESS-NAME,Folx,DIRECT'
- 'PROCESS-NAME,NetTransport,DIRECT'
- 'PROCESS-NAME,uTorrent,DIRECT'
- 'PROCESS-NAME,WebTorrent,DIRECT'
- 'PROCESS-NAME,aria2c.exe,DIRECT'
- 'PROCESS-NAME,BitComet.exe,DIRECT'
- 'PROCESS-NAME,fdm.exe,DIRECT'
- 'PROCESS-NAME,NetTransport.exe,DIRECT'
- 'PROCESS-NAME,qbittorrent.exe,DIRECT'
- 'PROCESS-NAME,Thunder.exe,DIRECT'
- 'PROCESS-NAME,ThunderVIP.exe,DIRECT'
- 'PROCESS-NAME,transmission-daemon.exe,DIRECT'
- 'PROCESS-NAME,transmission-qt.exe,DIRECT'
- 'PROCESS-NAME,uTorrent.exe,DIRECT'
- 'PROCESS-NAME,WebTorrent.exe,DIRECT'
- 'PROCESS-NAME,aDrive.exe,DIRECT'
- 'DOMAIN-SUFFIX,services.googleapis.cn,狗狗加速.com'
- 'DOMAIN-SUFFIX,xn--ngstr-lra8j.com,狗狗加速.com'
- 'DOMAIN,safebrowsing.urlsec.qq.com,DIRECT'
- 'DOMAIN,safebrowsing.googleapis.com,DIRECT'
- 'DOMAIN,developer.apple.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,digicert.com,狗狗加速.com'
- 'DOMAIN,ocsp.apple.com,狗狗加速.com'
- 'DOMAIN,ocsp.comodoca.com,狗狗加速.com'
- 'DOMAIN,ocsp.usertrust.com,狗狗加速.com'
- 'DOMAIN,ocsp.sectigo.com,狗狗加速.com'
- 'DOMAIN,ocsp.verisign.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,apple-dns.net,狗狗加速.com'
- 'DOMAIN,testflight.apple.com,狗狗加速.com'
- 'DOMAIN,sandbox.itunes.apple.com,狗狗加速.com'
- 'DOMAIN,itunes.apple.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,apps.apple.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,blobstore.apple.com,狗狗加速.com'
- 'DOMAIN,cvws.icloud-content.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,mzstatic.com,DIRECT'
- 'DOMAIN-SUFFIX,itunes.apple.com,DIRECT'
- 'DOMAIN-SUFFIX,icloud.com,DIRECT'
- 'DOMAIN-SUFFIX,icloud-content.com,DIRECT'
- 'DOMAIN-SUFFIX,me.com,DIRECT'
- 'DOMAIN-SUFFIX,aaplimg.com,DIRECT'
- 'DOMAIN-SUFFIX,cdn20.com,DIRECT'
- 'DOMAIN-SUFFIX,cdn-apple.com,DIRECT'
- 'DOMAIN-SUFFIX,akadns.net,DIRECT'
- 'DOMAIN-SUFFIX,akamaiedge.net,DIRECT'
- 'DOMAIN-SUFFIX,edgekey.net,DIRECT'
- 'DOMAIN-SUFFIX,mwcloudcdn.com,DIRECT'
- 'DOMAIN-SUFFIX,mwcname.com,DIRECT'
- 'DOMAIN-SUFFIX,apple.com,DIRECT'
- 'DOMAIN-SUFFIX,apple-cloudkit.com,DIRECT'
- 'DOMAIN-SUFFIX,apple-mapkit.com,DIRECT'
- 'DOMAIN,browser-intake-datadoghq.com,🔥ChatGPT'
- 'DOMAIN,chat.openai.com.cdn.cloudflare.net,🔥ChatGPT'
- 'DOMAIN,gemini.google.com,🔥ChatGPT'
- 'DOMAIN,openai-api.arkoselabs.com,🔥ChatGPT'
- 'DOMAIN,openaicom-api-bdcpf8c6d2e9atf6.z01.azurefd.net,🔥ChatGPT'
- 'DOMAIN,openaicomproductionae4b.blob.core.windows.net,🔥ChatGPT'
- 'DOMAIN,production-openaicom-storage.azureedge.net,🔥ChatGPT'
- 'DOMAIN,static.cloudflareinsights.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,ai.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,algolia.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,api.statsig.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,auth0.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,chatgpt.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,chatgpt.livekit.cloud,🔥ChatGPT'
- 'DOMAIN-SUFFIX,client-api.arkoselabs.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,events.statsigapi.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,featuregates.org,🔥ChatGPT'
- 'DOMAIN-SUFFIX,host.livekit.cloud,🔥ChatGPT'
- 'DOMAIN-SUFFIX,identrust.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,intercom.io,🔥ChatGPT'
- 'DOMAIN-SUFFIX,intercomcdn.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,launchdarkly.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,oaistatic.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,oaiusercontent.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,observeit.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,openai.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,openaiapi-site.azureedge.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,openaicom.imgix.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,segment.io,🔥ChatGPT'
- 'DOMAIN-SUFFIX,sentry.io,🔥ChatGPT'
- 'DOMAIN-SUFFIX,stripe.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,turn.livekit.cloud,🔥ChatGPT'
- 'DOMAIN-SUFFIX,sora.com,🔥ChatGPT'
- 'DOMAIN-KEYWORD,openai,🔥ChatGPT'
- 'DOMAIN,api.msn.com,🔥ChatGPT'
- 'DOMAIN,api.statsig.com,🔥ChatGPT'
- 'DOMAIN,assets.msn.com,🔥ChatGPT'
- 'DOMAIN,browser-intake-datadoghq.com,🔥ChatGPT'
- 'DOMAIN,chat.openai.com.cdn.cloudflare.net,🔥ChatGPT'
- 'DOMAIN,copilot.microsoft.com,🔥ChatGPT'
- 'DOMAIN,gateway.bingviz.microsoft.net,🔥ChatGPT'
- 'DOMAIN,gateway.bingviz.microsoftapp.net,🔥ChatGPT'
- 'DOMAIN,in.appcenter.ms,🔥ChatGPT'
- 'DOMAIN,location.microsoft.com,🔥ChatGPT'
- 'DOMAIN,odc.officeapps.live.com,🔥ChatGPT'
- 'DOMAIN,openai-api.arkoselabs.com,🔥ChatGPT'
- 'DOMAIN,openaicomproductionae4b.blob.core.windows.net,🔥ChatGPT'
- 'DOMAIN,production-openaicom-storage.azureedge.net,🔥ChatGPT'
- 'DOMAIN,r.bing.com,🔥ChatGPT'
- 'DOMAIN,self.events.data.microsoft.com,🔥ChatGPT'
- 'DOMAIN,services.bingapis.com,🔥ChatGPT'
- 'DOMAIN,static.cloudflareinsights.com,🔥ChatGPT'
- 'DOMAIN,sydney.bing.com,🔥ChatGPT'
- 'DOMAIN,www.bing.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,algolia.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,api.microsoftapp.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,auth0.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,bing-shopping.microsoft-falcon.io,🔥ChatGPT'
- 'DOMAIN-SUFFIX,challenges.cloudflare.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,chatgpt.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,chatgpt.livekit.cloud,🔥ChatGPT'
- 'DOMAIN-SUFFIX,client-api.arkoselabs.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,edgeservices.bing.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,events.statsigapi.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,featuregates.org,🔥ChatGPT'
- 'DOMAIN-SUFFIX,host.livekit.cloud,🔥ChatGPT'
- 'DOMAIN-SUFFIX,identrust.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,intercom.io,🔥ChatGPT'
- 'DOMAIN-SUFFIX,intercomcdn.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,launchdarkly.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,oaistatic.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,oaiusercontent.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,observeit.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,openai.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,openaiapi-site.azureedge.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,openaicom.imgix.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,segment.io,🔥ChatGPT'
- 'DOMAIN-SUFFIX,sentry.io,🔥ChatGPT'
- 'DOMAIN-SUFFIX,stripe.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,turn.livekit.cloud,🔥ChatGPT'
- 'DOMAIN-KEYWORD,openaicom-api,🔥ChatGPT'
- 'DOMAIN,ai.google.dev,🔥ChatGPT'
- 'DOMAIN,alkalimakersuite-pa.clients6.google.com,🔥ChatGPT'
- 'DOMAIN,makersuite.google.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,bard.google.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,deepmind.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,deepmind.google,🔥ChatGPT'
- 'DOMAIN-SUFFIX,gemini.google.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,generativeai.google,🔥ChatGPT'
- 'DOMAIN-SUFFIX,proactivebackend-pa.googleapis.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,apis.google.com,🔥ChatGPT'
- 'DOMAIN-KEYWORD,colab,🔥ChatGPT'
- 'DOMAIN-KEYWORD,developerprofiles,🔥ChatGPT'
- 'DOMAIN-KEYWORD,generativelanguage,🔥ChatGPT'
- 'DOMAIN,cdn.usefathom.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,anthropic.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,claude.ai,🔥ChatGPT'
- 'DOMAIN-SUFFIX,razie.ai,🔥ChatGPT'
- 'DOMAIN-SUFFIX,razie.aws.intellij.net,🔥ChatGPT'
- 'DOMAIN-SUFFIX,etbrains.ai,🔥ChatGPT'
- 'DOMAIN-SUFFIX,meta.com,🔥ChatGPT'
- 'DOMAIN-SUFFIX,cn,DIRECT'
- 'DOMAIN-KEYWORD,-cn,DIRECT'
- 'DOMAIN-SUFFIX,126.com,DIRECT'
- 'DOMAIN-SUFFIX,126.net,DIRECT'
- 'DOMAIN-SUFFIX,127.net,DIRECT'
- 'DOMAIN-SUFFIX,163.com,DIRECT'
- 'DOMAIN-SUFFIX,360buyimg.com,DIRECT'
- 'DOMAIN-SUFFIX,36kr.com,DIRECT'
- 'DOMAIN-SUFFIX,acfun.tv,DIRECT'
- 'DOMAIN-SUFFIX,air-matters.com,DIRECT'
- 'DOMAIN-SUFFIX,aixifan.com,DIRECT'
- 'DOMAIN-KEYWORD,alicdn,DIRECT'
- 'DOMAIN-KEYWORD,alipay,DIRECT'
- 'DOMAIN-KEYWORD,taobao,DIRECT'
- 'DOMAIN-SUFFIX,amap.com,DIRECT'
- 'DOMAIN-SUFFIX,autonavi.com,DIRECT'
- 'DOMAIN-KEYWORD,baidu,DIRECT'
- 'DOMAIN-SUFFIX,bdimg.com,DIRECT'
- 'DOMAIN-SUFFIX,bdstatic.com,DIRECT'
- 'DOMAIN-SUFFIX,bilibili.com,DIRECT'
- 'DOMAIN-SUFFIX,bilivideo.com,DIRECT'
- 'DOMAIN-SUFFIX,caiyunapp.com,DIRECT'
- 'DOMAIN-SUFFIX,clouddn.com,DIRECT'
- 'DOMAIN-SUFFIX,cnbeta.com,DIRECT'
- 'DOMAIN-SUFFIX,cnbetacdn.com,DIRECT'
- 'DOMAIN-SUFFIX,cootekservice.com,DIRECT'
- 'DOMAIN-SUFFIX,csdn.net,DIRECT'
- 'DOMAIN-SUFFIX,ctrip.com,DIRECT'
- 'DOMAIN-SUFFIX,dgtle.com,DIRECT'
- 'DOMAIN-SUFFIX,dianping.com,DIRECT'
- 'DOMAIN-SUFFIX,douban.com,DIRECT'
- 'DOMAIN-SUFFIX,doubanio.com,DIRECT'
- 'DOMAIN-SUFFIX,duokan.com,DIRECT'
- 'DOMAIN-SUFFIX,easou.com,DIRECT'
- 'DOMAIN-SUFFIX,ele.me,DIRECT'
- 'DOMAIN-SUFFIX,feng.com,DIRECT'
- 'DOMAIN-SUFFIX,fir.im,DIRECT'
- 'DOMAIN-SUFFIX,frdic.com,DIRECT'
- 'DOMAIN-SUFFIX,g-cores.com,DIRECT'
- 'DOMAIN-SUFFIX,godic.net,DIRECT'
- 'DOMAIN-SUFFIX,gtimg.com,DIRECT'
- 'DOMAIN,cdn.hockeyapp.net,DIRECT'
- 'DOMAIN-SUFFIX,hongxiu.com,DIRECT'
- 'DOMAIN-SUFFIX,hxcdn.net,DIRECT'
- 'DOMAIN-SUFFIX,iciba.com,DIRECT'
- 'DOMAIN-SUFFIX,ifeng.com,DIRECT'
- 'DOMAIN-SUFFIX,ifengimg.com,DIRECT'
- 'DOMAIN-SUFFIX,ipip.net,DIRECT'
- 'DOMAIN-SUFFIX,iqiyi.com,DIRECT'
- 'DOMAIN-SUFFIX,jd.com,DIRECT'
- 'DOMAIN-SUFFIX,jianshu.com,DIRECT'
- 'DOMAIN-SUFFIX,knewone.com,DIRECT'
- 'DOMAIN-SUFFIX,le.com,DIRECT'
- 'DOMAIN-SUFFIX,lecloud.com,DIRECT'
- 'DOMAIN-SUFFIX,lemicp.com,DIRECT'
- 'DOMAIN-SUFFIX,luoo.net,DIRECT'
- 'DOMAIN-SUFFIX,meituan.com,DIRECT'
- 'DOMAIN-SUFFIX,meituan.net,DIRECT'
- 'DOMAIN-SUFFIX,mi.com,DIRECT'
- 'DOMAIN-SUFFIX,miaopai.com,DIRECT'
- 'DOMAIN-SUFFIX,microsoft.com,DIRECT'
- 'DOMAIN-SUFFIX,microsoftonline.com,DIRECT'
- 'DOMAIN-SUFFIX,miui.com,DIRECT'
- 'DOMAIN-SUFFIX,miwifi.com,DIRECT'
- 'DOMAIN-SUFFIX,mob.com,DIRECT'
- 'DOMAIN-SUFFIX,netease.com,DIRECT'
- 'DOMAIN-SUFFIX,office.com,DIRECT'
- 'DOMAIN-SUFFIX,office365.com,DIRECT'
- 'DOMAIN-KEYWORD,officecdn,DIRECT'
- 'DOMAIN-SUFFIX,oschina.net,DIRECT'
- 'DOMAIN-SUFFIX,ppsimg.com,DIRECT'
- 'DOMAIN-SUFFIX,pstatp.com,DIRECT'
- 'DOMAIN-SUFFIX,qcloud.com,DIRECT'
- 'DOMAIN-SUFFIX,qdaily.com,DIRECT'
- 'DOMAIN-SUFFIX,qdmm.com,DIRECT'
- 'DOMAIN-SUFFIX,qhimg.com,DIRECT'
- 'DOMAIN-SUFFIX,qhres.com,DIRECT'
- 'DOMAIN-SUFFIX,qidian.com,DIRECT'
- 'DOMAIN-SUFFIX,qihucdn.com,DIRECT'
- 'DOMAIN-SUFFIX,qiniu.com,DIRECT'
- 'DOMAIN-SUFFIX,qiniucdn.com,DIRECT'
- 'DOMAIN-SUFFIX,qiyipic.com,DIRECT'
- 'DOMAIN-SUFFIX,qq.com,DIRECT'
- 'DOMAIN-SUFFIX,qqurl.com,DIRECT'
- 'DOMAIN-SUFFIX,rarbg.to,DIRECT'
- 'DOMAIN-SUFFIX,ruguoapp.com,DIRECT'
- 'DOMAIN-SUFFIX,segmentfault.com,DIRECT'
- 'DOMAIN-SUFFIX,sinaapp.com,DIRECT'
- 'DOMAIN-SUFFIX,smzdm.com,DIRECT'
- 'DOMAIN-SUFFIX,snapdrop.net,DIRECT'
- 'DOMAIN-SUFFIX,sogou.com,DIRECT'
- 'DOMAIN-SUFFIX,sogoucdn.com,DIRECT'
- 'DOMAIN-SUFFIX,sohu.com,DIRECT'
- 'DOMAIN-SUFFIX,soku.com,DIRECT'
- 'DOMAIN-SUFFIX,speedtest.net,DIRECT'
- 'DOMAIN-SUFFIX,sspai.com,DIRECT'
- 'DOMAIN-SUFFIX,suning.com,DIRECT'
- 'DOMAIN-SUFFIX,taobao.com,DIRECT'
- 'DOMAIN-SUFFIX,tencent.com,DIRECT'
- 'DOMAIN-SUFFIX,tenpay.com,DIRECT'
- 'DOMAIN-SUFFIX,tianyancha.com,DIRECT'
- 'DOMAIN-SUFFIX,tmall.com,DIRECT'
- 'DOMAIN-SUFFIX,tudou.com,DIRECT'
- 'DOMAIN-SUFFIX,umetrip.com,DIRECT'
- 'DOMAIN-SUFFIX,upaiyun.com,DIRECT'
- 'DOMAIN-SUFFIX,upyun.com,DIRECT'
- 'DOMAIN-SUFFIX,veryzhun.com,DIRECT'
- 'DOMAIN-SUFFIX,weather.com,DIRECT'
- 'DOMAIN-SUFFIX,weibo.com,DIRECT'
- 'DOMAIN-SUFFIX,xiami.com,DIRECT'
- 'DOMAIN-SUFFIX,xiami.net,DIRECT'
- 'DOMAIN-SUFFIX,xiaomicp.com,DIRECT'
- 'DOMAIN-SUFFIX,ximalaya.com,DIRECT'
- 'DOMAIN-SUFFIX,xmcdn.com,DIRECT'
- 'DOMAIN-SUFFIX,xunlei.com,DIRECT'
- 'DOMAIN-SUFFIX,yhd.com,DIRECT'
- 'DOMAIN-SUFFIX,yihaodianimg.com,DIRECT'
- 'DOMAIN-SUFFIX,yinxiang.com,DIRECT'
- 'DOMAIN-SUFFIX,ykimg.com,DIRECT'
- 'DOMAIN-SUFFIX,youdao.com,DIRECT'
- 'DOMAIN-SUFFIX,youku.com,DIRECT'
- 'DOMAIN-SUFFIX,zealer.com,DIRECT'
- 'DOMAIN-SUFFIX,zhihu.com,DIRECT'
- 'DOMAIN-SUFFIX,zhimg.com,DIRECT'
- 'DOMAIN-SUFFIX,zimuzu.tv,DIRECT'
- 'DOMAIN-SUFFIX,zoho.com,DIRECT'
- 'DOMAIN,fastly-download.epicgames.com,DIRECT'
- 'DOMAIN,epicgames-download1.akamaized.net,DIRECT'
- 'DOMAIN,steamcdn-a.akamaihd.net,DIRECT'
- 'DOMAIN-SUFFIX,steamserver.net,DIRECT'
- 'DOMAIN-SUFFIX,cm.steampowered.com,DIRECT'
- 'DOMAIN-SUFFIX,synology.com,DIRECT'
- 'DOMAIN-SUFFIX,dyndns.org,DIRECT'
- 'DOMAIN-SUFFIX,egdownload.fastly-edge.com,DIRECT'
- 'DOMAIN,cn.bing.com,DIRECT'
- 'DOMAIN-KEYWORD,amazon,狗狗加速.com'
- 'DOMAIN-KEYWORD,google,狗狗加速.com'
- 'DOMAIN-KEYWORD,gmail,狗狗加速.com'
- 'DOMAIN-KEYWORD,youtube,狗狗加速.com'
- 'DOMAIN-KEYWORD,facebook,狗狗加速.com'
- 'DOMAIN-SUFFIX,fb.me,狗狗加速.com'
- 'DOMAIN-SUFFIX,fbcdn.net,狗狗加速.com'
- 'DOMAIN-KEYWORD,twitter,狗狗加速.com'
- 'DOMAIN-KEYWORD,instagram,狗狗加速.com'
- 'DOMAIN-KEYWORD,dropbox,狗狗加速.com'
- 'DOMAIN-SUFFIX,twimg.com,狗狗加速.com'
- 'DOMAIN-KEYWORD,blogspot,狗狗加速.com'
- 'DOMAIN-SUFFIX,youtu.be,狗狗加速.com'
- 'DOMAIN-KEYWORD,whatsapp,狗狗加速.com'
- 'DOMAIN-SUFFIX,ipleak.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,browserscan.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,surfsharkdns.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,edns.ip-api.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,dnsleaktest.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,dnsleak.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,expressvpn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,nordvpn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,surfshark.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,perfect-privacy.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,browserleaks.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,browserleaks.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,browserleaks.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,vpnunlimited.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,whoer.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,whrq.net,狗狗加速.com'
- 'DOMAIN-KEYWORD,admarvel,REJECT'
- 'DOMAIN-KEYWORD,admaster,REJECT'
- 'DOMAIN-KEYWORD,adsage,REJECT'
- 'DOMAIN-KEYWORD,adsmogo,REJECT'
- 'DOMAIN-KEYWORD,adsrvmedia,REJECT'
- 'DOMAIN-KEYWORD,adwords,REJECT'
- 'DOMAIN-KEYWORD,adservice,REJECT'
- 'DOMAIN-SUFFIX,appsflyer.com,REJECT'
- 'DOMAIN-KEYWORD,domob,REJECT'
- 'DOMAIN-SUFFIX,doubleclick.net,REJECT'
- 'DOMAIN-KEYWORD,duomeng,REJECT'
- 'DOMAIN-KEYWORD,dwtrack,REJECT'
- 'DOMAIN-KEYWORD,guanggao,REJECT'
- 'DOMAIN-KEYWORD,lianmeng,REJECT'
- 'DOMAIN-SUFFIX,mmstat.com,REJECT'
- 'DOMAIN-KEYWORD,mopub,REJECT'
- 'DOMAIN-KEYWORD,omgmta,REJECT'
- 'DOMAIN-KEYWORD,openx,REJECT'
- 'DOMAIN-KEYWORD,partnerad,REJECT'
- 'DOMAIN-KEYWORD,pingfore,REJECT'
- 'DOMAIN-KEYWORD,supersonicads,REJECT'
- 'DOMAIN-KEYWORD,uedas,REJECT'
- 'DOMAIN-KEYWORD,umeng,REJECT'
- 'DOMAIN-KEYWORD,usage,REJECT'
- 'DOMAIN-SUFFIX,vungle.com,REJECT'
- 'DOMAIN-KEYWORD,wlmonitor,REJECT'
- 'DOMAIN-KEYWORD,zjtoolbar,REJECT'
- 'DOMAIN-SUFFIX,linkedin.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,licdn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,9to5mac.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,abpchina.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,adblockplus.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,adobe.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,akamaized.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,alfredapp.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,amplitude.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ampproject.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,android.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,angularjs.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,aolcdn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,apkpure.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,appledaily.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,appshopper.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,appspot.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,arcgis.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,archive.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,armorgames.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,aspnetcdn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,att.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,awsstatic.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,azurewebsites.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,bing.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,bintray.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,bit.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,bit.ly,狗狗加速.com'
- 'DOMAIN-SUFFIX,bitbucket.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,bjango.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,bkrtx.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,blog.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,blogcdn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,blogger.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,blogsmithmedia.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,blogspot.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,blogspot.hk,狗狗加速.com'
- 'DOMAIN-SUFFIX,bloomberg.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,box.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,box.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,cachefly.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,chromium.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,cl.ly,狗狗加速.com'
- 'DOMAIN-SUFFIX,cloudflare.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,cloudfront.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,cloudmagic.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,cmail19.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,cnet.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,cocoapods.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,comodoca.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,crashlytics.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,culturedcode.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,d.pr,狗狗加速.com'
- 'DOMAIN-SUFFIX,danilo.to,狗狗加速.com'
- 'DOMAIN-SUFFIX,dayone.me,狗狗加速.com'
- 'DOMAIN-SUFFIX,db.tt,狗狗加速.com'
- 'DOMAIN-SUFFIX,deskconnect.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,disq.us,狗狗加速.com'
- 'DOMAIN-SUFFIX,disqus.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,disquscdn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,dnsimple.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,docker.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,dribbble.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,droplr.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,duckduckgo.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,dueapp.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,dytt8.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,edgecastcdn.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,edgekey.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,edgesuite.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,engadget.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,entrust.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,eurekavpt.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,evernote.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,fabric.io,狗狗加速.com'
- 'DOMAIN-SUFFIX,fast.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,fastly.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,fc2.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,feedburner.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,feedly.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,feedsportal.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,fiftythree.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,firebaseio.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,flexibits.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,flickr.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,flipboard.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,g.co,狗狗加速.com'
- 'DOMAIN-SUFFIX,gabia.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,geni.us,狗狗加速.com'
- 'DOMAIN-SUFFIX,gfx.ms,狗狗加速.com'
- 'DOMAIN-SUFFIX,ggpht.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ghostnoteapp.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,git.io,狗狗加速.com'
- 'DOMAIN-KEYWORD,github,狗狗加速.com'
- 'DOMAIN-SUFFIX,globalsign.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,gmodules.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,godaddy.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,golang.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,gongm.in,狗狗加速.com'
- 'DOMAIN-SUFFIX,goo.gl,狗狗加速.com'
- 'DOMAIN-SUFFIX,goodreaders.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,goodreads.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,gravatar.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,gstatic.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,gvt0.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,hockeyapp.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,hotmail.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,icons8.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ifixit.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ift.tt,狗狗加速.com'
- 'DOMAIN-SUFFIX,ifttt.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,iherb.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,imageshack.us,狗狗加速.com'
- 'DOMAIN-SUFFIX,img.ly,狗狗加速.com'
- 'DOMAIN-SUFFIX,imgur.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,imore.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,instapaper.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ipn.li,狗狗加速.com'
- 'DOMAIN-SUFFIX,is.gd,狗狗加速.com'
- 'DOMAIN-SUFFIX,issuu.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,itgonglun.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,itun.es,狗狗加速.com'
- 'DOMAIN-SUFFIX,ixquick.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,j.mp,狗狗加速.com'
- 'DOMAIN-SUFFIX,js.revsci.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,jshint.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,jtvnw.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,justgetflux.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,kat.cr,狗狗加速.com'
- 'DOMAIN-SUFFIX,klip.me,狗狗加速.com'
- 'DOMAIN-SUFFIX,libsyn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,line-apps.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,linode.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,lithium.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,littlehj.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,live.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,live.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,livefilestore.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,llnwd.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,macid.co,狗狗加速.com'
- 'DOMAIN-SUFFIX,macromedia.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,macrumors.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,mashable.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,mathjax.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,medium.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,mega.co.nz,狗狗加速.com'
- 'DOMAIN-SUFFIX,mega.nz,狗狗加速.com'
- 'DOMAIN-SUFFIX,megaupload.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,microsofttranslator.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,mindnode.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,mobile01.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,modmyi.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,msedge.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,myfontastic.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,name.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,nextmedia.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,nsstatic.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,nssurge.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,nyt.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,nytimes.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,omnigroup.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,onedrive.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,onenote.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ooyala.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,openvpn.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,openwrt.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,orkut.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,osxdaily.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,outlook.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ow.ly,狗狗加速.com'
- 'DOMAIN-SUFFIX,paddleapi.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,parallels.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,parse.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,pdfexpert.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,periscope.tv,狗狗加速.com'
- 'DOMAIN-SUFFIX,pinboard.in,狗狗加速.com'
- 'DOMAIN-SUFFIX,pinterest.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,pixelmator.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,pixiv.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,playpcesor.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,playstation.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,playstation.com.hk,狗狗加速.com'
- 'DOMAIN-SUFFIX,playstation.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,playstationnetwork.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,pushwoosh.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,rime.im,狗狗加速.com'
- 'DOMAIN-SUFFIX,servebom.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,sfx.ms,狗狗加速.com'
- 'DOMAIN-SUFFIX,shadowsocks.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,sharethis.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,shazam.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,skype.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,smartdnsproxy.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,smartmailcloud.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,sndcdn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,sony.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,soundcloud.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,sourceforge.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,spotify.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,squarespace.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,sstatic.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,st.luluku.pw,狗狗加速.com'
- 'DOMAIN-SUFFIX,stackoverflow.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,startpage.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,staticflickr.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,steamcommunity.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,symauth.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,symcb.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,symcd.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,tapbots.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,tapbots.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,tdesktop.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,techcrunch.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,techsmith.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,thepiratebay.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,theverge.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,time.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,timeinc.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,tiny.cc,狗狗加速.com'
- 'DOMAIN-SUFFIX,tinypic.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,tmblr.co,狗狗加速.com'
- 'DOMAIN-SUFFIX,todoist.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,trello.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,trustasiassl.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,tumblr.co,狗狗加速.com'
- 'DOMAIN-SUFFIX,tumblr.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,tweetdeck.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,tweetmarker.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,twitch.tv,狗狗加速.com'
- 'DOMAIN-SUFFIX,txmblr.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,typekit.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,ubertags.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ublock.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,ubnt.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ulyssesapp.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,urchin.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,usertrust.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,v.gd,狗狗加速.com'
- 'DOMAIN-SUFFIX,v2ex.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,vimeo.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,vimeocdn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,vine.co,狗狗加速.com'
- 'DOMAIN-SUFFIX,vivaldi.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,vox-cdn.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,vsco.co,狗狗加速.com'
- 'DOMAIN-SUFFIX,vultr.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,w.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,w3schools.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,webtype.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,wikiwand.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,wikileaks.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,wikimedia.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,wikipedia.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,wikipedia.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,windows.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,windows.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,wire.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,wordpress.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,workflowy.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,wp.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,wsj.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,wsj.net,狗狗加速.com'
- 'DOMAIN-SUFFIX,xda-developers.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,xeeno.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,xiti.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,yahoo.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,yimg.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,ying.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,yoyo.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,ytimg.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,signal.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,whispersystems.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,cangku.moe,狗狗加速.com'
- 'DOMAIN-SUFFIX,tradingview.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,x.com,狗狗加速.com'
- 'DOMAIN-SUFFIX,asmr.one,狗狗加速.com'
- 'DOMAIN-SUFFIX,telegra.ph,狗狗加速.com'
- 'DOMAIN-SUFFIX,telegram.org,狗狗加速.com'
- 'DOMAIN-SUFFIX,t.me,狗狗加速.com'
- 'DOMAIN-SUFFIX,telegram.me,狗狗加速.com'
- 'IP-CIDR,91.108.4.0/22,狗狗加速.com,no-resolve'
- 'IP-CIDR,91.108.8.0/21,狗狗加速.com,no-resolve'
- 'IP-CIDR,91.108.16.0/22,狗狗加速.com,no-resolve'
- 'IP-CIDR,91.108.56.0/22,狗狗加速.com,no-resolve'
- 'IP-CIDR,149.154.160.0/20,狗狗加速.com,no-resolve'
- 'IP-CIDR6,2001:67c:4e8::/48,狗狗加速.com,no-resolve'
- 'IP-CIDR6,2001:b28:f23d::/48,狗狗加速.com,no-resolve'
- 'IP-CIDR6,2001:b28:f23f::/48,狗狗加速.com,no-resolve'
- 'IP-CIDR,120.232.181.162/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,120.241.147.226/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,120.253.253.226/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,120.253.255.162/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,120.253.255.34/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,120.253.255.98/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,180.163.150.162/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,180.163.150.34/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,180.163.151.162/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,180.163.151.34/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,203.208.39.0/24,狗狗加速.com,no-resolve'
- 'IP-CIDR,203.208.40.0/24,狗狗加速.com,no-resolve'
- 'IP-CIDR,203.208.41.0/24,狗狗加速.com,no-resolve'
- 'IP-CIDR,203.208.43.0/24,狗狗加速.com,no-resolve'
- 'IP-CIDR,203.208.50.0/24,狗狗加速.com,no-resolve'
- 'IP-CIDR,220.181.174.162/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,220.181.174.226/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,220.181.174.34/32,狗狗加速.com,no-resolve'
- 'IP-CIDR,24.199.123.28/32,🔥ChatGPT,no-resolve'
- 'IP-CIDR,64.23.132.171/32,🔥ChatGPT,no-resolve'
- 'IP-CIDR,24.199.123.28/32,🔥ChatGPT,no-resolve'
- 'IP-CIDR,64.23.132.171/32,🔥ChatGPT,no-resolve'
- 'DOMAIN,injections.adguard.org,DIRECT'
- 'DOMAIN,local.adguard.org,DIRECT'
- 'DOMAIN-SUFFIX,local,DIRECT'
- 'IP-CIDR,127.0.0.0/8,DIRECT'
- 'IP-CIDR,172.16.0.0/12,DIRECT'
- 'IP-CIDR,192.168.0.0/16,DIRECT'
- 'IP-CIDR,10.0.0.0/8,DIRECT'
- 'IP-CIDR,17.0.0.0/8,DIRECT'
- 'IP-CIDR,100.64.0.0/10,DIRECT'
- 'IP-CIDR,224.0.0.0/4,DIRECT'
- 'IP-CIDR6,fe80::/10,DIRECT'
- 'GEOIP,CN,DIRECT'
- 'MATCH,狗狗加速.com'
File diff suppressed because it is too large Load Diff
+647
View File
@@ -0,0 +1,647 @@
mixed-port: 7890
allow-lan: true
bind-address: '*'
mode: rule
log-level: info
ipv6: false
skip-auth-prefixes: # 设置跳过验证的 IP 段
- 127.0.0.1/8
- ::1/128
find-process-mode: strict
unified-delay: true
external-controller: 0.0.0.0:9090
external-controller-cors:
allow-private-network: true
allow-origins:
- '*'
### Tunnel配置
tun:
enable: false
stack: system
device: meta
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
strict-route: true
mtu: 1500
# 如果有使用zerotier或者headscale等,需要自己配置排除自己的网段
# route-exclude-address: ["192.168.110.0/24"]
dns:
enable: true
ipv6: false
default-nameserver: [223.5.5.5, 119.29.29.29]
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter: ['*.lan','*.localhost','*.cpolar.top','*.picp.net','*.3322.org','*.dscloud.me','*.joyagain.top','*.joyagain.me','*.xicp.cn','*.himan.vip']
use-hosts: true
nameserver: ['https://doh.pub/dns-query', 'https://dns.alidns.com/dns-query']
fallback: ['https://doh.dns.sb/dns-query', 'https://dns.cloudflare.com/dns-query', 'https://dns.twnic.tw/dns-query', 'tls://8.8.4.4:853']
fallback-filter: { geoip: true, ipcidr: [240.0.0.0/4, 0.0.0.0/32] }
proxies:
- { name: '剩余流量:3574.8 GB', type: ss, server: www.4399.com, port: 60001, cipher: chacha20-ietf-poly1305, password: 5135ccc0-37f1-4d5e-8df5-594b2440878d, udp: true }
- { name: 套餐到期:长期有效, type: ss, server: www.4399.com, port: 60001, cipher: chacha20-ietf-poly1305, password: 5135ccc0-37f1-4d5e-8df5-594b2440878d, udp: true }
- { name: 地址:国际流量.COM, type: ss, server: www.4399.com, port: 60001, cipher: chacha20-ietf-poly1305, password: 5135ccc0-37f1-4d5e-8df5-594b2440878d, udp: true }
- { name: 地址:iPLC国际流量站.COM, type: ss, server: www.4399.com, port: 60001, cipher: chacha20-ietf-poly1305, password: 5135ccc0-37f1-4d5e-8df5-594b2440878d, udp: true }
- { name: ⚠️请设置自动更新订阅, type: ss, server: www.4399.com, port: 60008, cipher: chacha20-ietf-poly1305, password: 5135ccc0-37f1-4d5e-8df5-594b2440878d, udp: true }
- { name: '01 美国 高级静态', type: vmess, server: 50001.20250808iplcin.top, port: 50001, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '02 美国 顶级', type: vmess, server: 50002.20250808iplcin.top, port: 50002, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '03 美国 初级慢速', type: vmess, server: 50003.20250808iplcin.top, port: 50003, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '04 美国 初级年费专享', type: vmess, server: 50004.20250808iplcin.top, port: 50004, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '05 美国 高级优先', type: vmess, server: 50005.20250808iplcin.top, port: 50005, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '06 新加坡 高级', type: vmess, server: 50006.20250808iplcin.top, port: 50006, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '07 新加坡 顶级', type: vmess, server: 50007.20250808iplcin.top, port: 50007, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '08 新加坡 高级', type: vmess, server: 50008.20250808iplcin.top, port: 50008, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '09 新加坡 高级下载', type: vmess, server: 50009.20250808iplcin.top, port: 50009, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '10 新加坡 高级概率解锁', type: vmess, server: 50010.20250808iplcin.top, port: 50010, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '11 新加坡 高级概率解锁', type: vmess, server: 50011.20250808iplcin.top, port: 50011, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '12 新加坡 高级高速', type: vmess, server: 50012.20250808iplcin.top, port: 50012, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '13 新加坡 顶级极速', type: vmess, server: 50013.20250808iplcin.top, port: 50013, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '14 新加坡 流畅初级', type: vmess, server: 50014.20250808iplcin.top, port: 50014, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '15 新加坡 初级', type: vmess, server: 50015.20250808iplcin.top, port: 50015, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '16 台湾 顶级', type: vmess, server: 50016.20250808iplcin.top, port: 50016, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '17 台湾 高级', type: vmess, server: 50017.20250808iplcin.top, port: 50017, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '18 台湾 高级', type: vmess, server: 50018.20250808iplcin.top, port: 50018, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '19 台湾 顶级', type: vmess, server: 50019.20250808iplcin.top, port: 50019, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '20 台湾 高级高速', type: vmess, server: 50020.20250808iplcin.top, port: 50020, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '21 香港 初级年付', type: vmess, server: 50021.20250808iplcin.top, port: 50021, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '22 香港 新加坡 动态', type: vmess, server: 50022.20250808iplcin.top, port: 50022, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '23 新加坡高级高速', type: vmess, server: 50023.20250808iplcin.top, port: 50023, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '24 香港 新加坡 高级动态', type: vmess, server: 50024.20250808iplcin.top, port: 50024, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '25 香港 新加坡 高级动态', type: vmess, server: 50025.20250808iplcin.top, port: 50025, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '26 新加坡 顶级极速 静态', type: vmess, server: 50026.20250808iplcin.top, port: 50026, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '27 香港 新加坡 高级动态', type: vmess, server: 50027.20250808iplcin.top, port: 50027, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '28 香港 新加坡 高级', type: vmess, server: 50028.20250808iplcin.top, port: 50028, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '29 香港 新加坡 视频增强', type: vmess, server: 50029.20250808iplcin.top, port: 50029, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '30 香港 新加坡 高级双线', type: vmess, server: 50030.20250808iplcin.top, port: 50030, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '31 日本 高级', type: vmess, server: 50031.20250808iplcin.top, port: 50031, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '32 日本 高级', type: vmess, server: 50032.20250808iplcin.top, port: 50032, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '33 日本 顶级极速', type: vmess, server: 50033.20250808iplcin.top, port: 50033, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '34 日本 顶级极速', type: vmess, server: 50034.20250808iplcin.top, port: 50034, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
- { name: '35 日本 顶级', type: vmess, server: 50035.20250808iplcin.top, port: 50035, uuid: 5135ccc0-37f1-4d5e-8df5-594b2440878d, alterId: 0, cipher: auto, udp: true }
proxy-groups:
- { name: IPLC 国际流量站, type: select, proxies: [自动选择, 故障转移, '剩余流量:3574.8 GB', 套餐到期:长期有效, 地址:国际流量.COM, 地址:iPLC国际流量站.COM, ⚠️请设置自动更新订阅, '01 美国 高级静态', '02 美国 顶级', '03 美国 初级慢速', '04 美国 初级年费专享', '05 美国 高级优先', '06 新加坡 高级', '07 新加坡 顶级', '08 新加坡 高级', '09 新加坡 高级下载', '10 新加坡 高级概率解锁', '11 新加坡 高级概率解锁', '12 新加坡 高级高速', '13 新加坡 顶级极速', '14 新加坡 流畅初级', '15 新加坡 初级', '16 台湾 顶级', '17 台湾 高级', '18 台湾 高级', '19 台湾 顶级', '20 台湾 高级高速', '21 香港 初级年付', '22 香港 新加坡 动态', '23 新加坡高级高速', '24 香港 新加坡 高级动态', '25 香港 新加坡 高级动态', '26 新加坡 顶级极速 静态', '27 香港 新加坡 高级动态', '28 香港 新加坡 高级', '29 香港 新加坡 视频增强', '30 香港 新加坡 高级双线', '31 日本 高级', '32 日本 高级', '33 日本 顶级极速', '34 日本 顶级极速', '35 日本 顶级'] }
- { name: 自动选择, type: url-test, proxies: ['剩余流量:3574.8 GB', 套餐到期:长期有效, 地址:国际流量.COM, 地址:iPLC国际流量站.COM, ⚠️请设置自动更新订阅, '01 美国 高级静态', '02 美国 顶级', '03 美国 初级慢速', '04 美国 初级年费专享', '05 美国 高级优先', '06 新加坡 高级', '07 新加坡 顶级', '08 新加坡 高级', '09 新加坡 高级下载', '10 新加坡 高级概率解锁', '11 新加坡 高级概率解锁', '12 新加坡 高级高速', '13 新加坡 顶级极速', '14 新加坡 流畅初级', '15 新加坡 初级', '16 台湾 顶级', '17 台湾 高级', '18 台湾 高级', '19 台湾 顶级', '20 台湾 高级高速', '21 香港 初级年付', '22 香港 新加坡 动态', '23 新加坡高级高速', '24 香港 新加坡 高级动态', '25 香港 新加坡 高级动态', '26 新加坡 顶级极速 静态', '27 香港 新加坡 高级动态', '28 香港 新加坡 高级', '29 香港 新加坡 视频增强', '30 香港 新加坡 高级双线', '31 日本 高级', '32 日本 高级', '33 日本 顶级极速', '34 日本 顶级极速', '35 日本 顶级'], url: 'http://www.gstatic.com/generate_204', interval: 86400 }
- { name: 故障转移, type: fallback, proxies: ['剩余流量:3574.8 GB', 套餐到期:长期有效, 地址:国际流量.COM, 地址:iPLC国际流量站.COM, ⚠️请设置自动更新订阅, '01 美国 高级静态', '02 美国 顶级', '03 美国 初级慢速', '04 美国 初级年费专享', '05 美国 高级优先', '06 新加坡 高级', '07 新加坡 顶级', '08 新加坡 高级', '09 新加坡 高级下载', '10 新加坡 高级概率解锁', '11 新加坡 高级概率解锁', '12 新加坡 高级高速', '13 新加坡 顶级极速', '14 新加坡 流畅初级', '15 新加坡 初级', '16 台湾 顶级', '17 台湾 高级', '18 台湾 高级', '19 台湾 顶级', '20 台湾 高级高速', '21 香港 初级年付', '22 香港 新加坡 动态', '23 新加坡高级高速', '24 香港 新加坡 高级动态', '25 香港 新加坡 高级动态', '26 新加坡 顶级极速 静态', '27 香港 新加坡 高级动态', '28 香港 新加坡 高级', '29 香港 新加坡 视频增强', '30 香港 新加坡 高级双线', '31 日本 高级', '32 日本 高级', '33 日本 顶级极速', '34 日本 顶级极速', '35 日本 顶级'], url: 'http://www.gstatic.com/generate_204', interval: 7200 }
rules:
- 'DOMAIN,20250808iplcin.top,DIRECT'
- 'DOMAIN-SUFFIX,services.googleapis.cn,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,xn--ngstr-lra8j.com,IPLC 国际流量站'
- 'DOMAIN,safebrowsing.urlsec.qq.com,DIRECT'
- 'DOMAIN,safebrowsing.googleapis.com,DIRECT'
- 'DOMAIN,developer.apple.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,digicert.com,IPLC 国际流量站'
- 'DOMAIN,ocsp.apple.com,IPLC 国际流量站'
- 'DOMAIN,ocsp.comodoca.com,IPLC 国际流量站'
- 'DOMAIN,ocsp.usertrust.com,IPLC 国际流量站'
- 'DOMAIN,ocsp.sectigo.com,IPLC 国际流量站'
- 'DOMAIN,ocsp.verisign.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,apple-dns.net,IPLC 国际流量站'
- 'DOMAIN,testflight.apple.com,IPLC 国际流量站'
- 'DOMAIN,sandbox.itunes.apple.com,IPLC 国际流量站'
- 'DOMAIN,itunes.apple.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,apps.apple.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,blobstore.apple.com,IPLC 国际流量站'
- 'DOMAIN,cvws.icloud-content.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,mzstatic.com,DIRECT'
- 'DOMAIN-SUFFIX,itunes.apple.com,DIRECT'
- 'DOMAIN-SUFFIX,icloud.com,DIRECT'
- 'DOMAIN-SUFFIX,icloud-content.com,DIRECT'
- 'DOMAIN-SUFFIX,me.com,DIRECT'
- 'DOMAIN-SUFFIX,aaplimg.com,DIRECT'
- 'DOMAIN-SUFFIX,cdn20.com,DIRECT'
- 'DOMAIN-SUFFIX,cdn-apple.com,DIRECT'
- 'DOMAIN-SUFFIX,akadns.net,DIRECT'
- 'DOMAIN-SUFFIX,akamaiedge.net,DIRECT'
- 'DOMAIN-SUFFIX,edgekey.net,DIRECT'
- 'DOMAIN-SUFFIX,mwcloudcdn.com,DIRECT'
- 'DOMAIN-SUFFIX,mwcname.com,DIRECT'
- 'DOMAIN-SUFFIX,apple.com,DIRECT'
- 'DOMAIN-SUFFIX,apple-cloudkit.com,DIRECT'
- 'DOMAIN-SUFFIX,apple-mapkit.com,DIRECT'
- 'DOMAIN-SUFFIX,126.com,DIRECT'
- 'DOMAIN-SUFFIX,126.net,DIRECT'
- 'DOMAIN-SUFFIX,127.net,DIRECT'
- 'DOMAIN-SUFFIX,163.com,DIRECT'
- 'DOMAIN-SUFFIX,360buyimg.com,DIRECT'
- 'DOMAIN-SUFFIX,36kr.com,DIRECT'
- 'DOMAIN-SUFFIX,acfun.tv,DIRECT'
- 'DOMAIN-SUFFIX,air-matters.com,DIRECT'
- 'DOMAIN-SUFFIX,aixifan.com,DIRECT'
- 'DOMAIN-KEYWORD,alicdn,DIRECT'
- 'DOMAIN-KEYWORD,alipay,DIRECT'
- 'DOMAIN-KEYWORD,taobao,DIRECT'
- 'DOMAIN-SUFFIX,amap.com,DIRECT'
- 'DOMAIN-SUFFIX,autonavi.com,DIRECT'
- 'DOMAIN-KEYWORD,baidu,DIRECT'
- 'DOMAIN-SUFFIX,bdimg.com,DIRECT'
- 'DOMAIN-SUFFIX,bdstatic.com,DIRECT'
- 'DOMAIN-SUFFIX,bilibili.com,DIRECT'
- 'DOMAIN-SUFFIX,bilivideo.com,DIRECT'
- 'DOMAIN-SUFFIX,caiyunapp.com,DIRECT'
- 'DOMAIN-SUFFIX,clouddn.com,DIRECT'
- 'DOMAIN-SUFFIX,cnbeta.com,DIRECT'
- 'DOMAIN-SUFFIX,cnbetacdn.com,DIRECT'
- 'DOMAIN-SUFFIX,cootekservice.com,DIRECT'
- 'DOMAIN-SUFFIX,csdn.net,DIRECT'
- 'DOMAIN-SUFFIX,ctrip.com,DIRECT'
- 'DOMAIN-SUFFIX,dgtle.com,DIRECT'
- 'DOMAIN-SUFFIX,dianping.com,DIRECT'
- 'DOMAIN-SUFFIX,douban.com,DIRECT'
- 'DOMAIN-SUFFIX,doubanio.com,DIRECT'
- 'DOMAIN-SUFFIX,duokan.com,DIRECT'
- 'DOMAIN-SUFFIX,easou.com,DIRECT'
- 'DOMAIN-SUFFIX,ele.me,DIRECT'
- 'DOMAIN-SUFFIX,feng.com,DIRECT'
- 'DOMAIN-SUFFIX,fir.im,DIRECT'
- 'DOMAIN-SUFFIX,frdic.com,DIRECT'
- 'DOMAIN-SUFFIX,g-cores.com,DIRECT'
- 'DOMAIN-SUFFIX,godic.net,DIRECT'
- 'DOMAIN-SUFFIX,gtimg.com,DIRECT'
- 'DOMAIN,cdn.hockeyapp.net,DIRECT'
- 'DOMAIN-SUFFIX,hongxiu.com,DIRECT'
- 'DOMAIN-SUFFIX,hxcdn.net,DIRECT'
- 'DOMAIN-SUFFIX,iciba.com,DIRECT'
- 'DOMAIN-SUFFIX,ifeng.com,DIRECT'
- 'DOMAIN-SUFFIX,ifengimg.com,DIRECT'
- 'DOMAIN-SUFFIX,ipip.net,DIRECT'
- 'DOMAIN-SUFFIX,iqiyi.com,DIRECT'
- 'DOMAIN-SUFFIX,jd.com,DIRECT'
- 'DOMAIN-SUFFIX,jianshu.com,DIRECT'
- 'DOMAIN-SUFFIX,knewone.com,DIRECT'
- 'DOMAIN-SUFFIX,le.com,DIRECT'
- 'DOMAIN-SUFFIX,lecloud.com,DIRECT'
- 'DOMAIN-SUFFIX,lemicp.com,DIRECT'
- 'DOMAIN-SUFFIX,licdn.com,DIRECT'
- 'DOMAIN-SUFFIX,luoo.net,DIRECT'
- 'DOMAIN-SUFFIX,meituan.com,DIRECT'
- 'DOMAIN-SUFFIX,meituan.net,DIRECT'
- 'DOMAIN-SUFFIX,mi.com,DIRECT'
- 'DOMAIN-SUFFIX,miaopai.com,DIRECT'
- 'DOMAIN-SUFFIX,microsoft.com,DIRECT'
- 'DOMAIN-SUFFIX,microsoftonline.com,DIRECT'
- 'DOMAIN-SUFFIX,miui.com,DIRECT'
- 'DOMAIN-SUFFIX,miwifi.com,DIRECT'
- 'DOMAIN-SUFFIX,mob.com,DIRECT'
- 'DOMAIN-SUFFIX,netease.com,DIRECT'
- 'DOMAIN-SUFFIX,office.com,DIRECT'
- 'DOMAIN-SUFFIX,office365.com,DIRECT'
- 'DOMAIN-KEYWORD,officecdn,DIRECT'
- 'DOMAIN-SUFFIX,oschina.net,DIRECT'
- 'DOMAIN-SUFFIX,ppsimg.com,DIRECT'
- 'DOMAIN-SUFFIX,pstatp.com,DIRECT'
- 'DOMAIN-SUFFIX,qcloud.com,DIRECT'
- 'DOMAIN-SUFFIX,qdaily.com,DIRECT'
- 'DOMAIN-SUFFIX,qdmm.com,DIRECT'
- 'DOMAIN-SUFFIX,qhimg.com,DIRECT'
- 'DOMAIN-SUFFIX,qhres.com,DIRECT'
- 'DOMAIN-SUFFIX,qidian.com,DIRECT'
- 'DOMAIN-SUFFIX,qihucdn.com,DIRECT'
- 'DOMAIN-SUFFIX,qiniu.com,DIRECT'
- 'DOMAIN-SUFFIX,qiniucdn.com,DIRECT'
- 'DOMAIN-SUFFIX,qiyipic.com,DIRECT'
- 'DOMAIN-SUFFIX,qq.com,DIRECT'
- 'DOMAIN-SUFFIX,qqurl.com,DIRECT'
- 'DOMAIN-SUFFIX,rarbg.to,DIRECT'
- 'DOMAIN-SUFFIX,ruguoapp.com,DIRECT'
- 'DOMAIN-SUFFIX,segmentfault.com,DIRECT'
- 'DOMAIN-SUFFIX,sinaapp.com,DIRECT'
- 'DOMAIN-SUFFIX,smzdm.com,DIRECT'
- 'DOMAIN-SUFFIX,snapdrop.net,DIRECT'
- 'DOMAIN-SUFFIX,sogou.com,DIRECT'
- 'DOMAIN-SUFFIX,sogoucdn.com,DIRECT'
- 'DOMAIN-SUFFIX,sohu.com,DIRECT'
- 'DOMAIN-SUFFIX,soku.com,DIRECT'
- 'DOMAIN-SUFFIX,speedtest.net,DIRECT'
- 'DOMAIN-SUFFIX,sspai.com,DIRECT'
- 'DOMAIN-SUFFIX,suning.com,DIRECT'
- 'DOMAIN-SUFFIX,taobao.com,DIRECT'
- 'DOMAIN-SUFFIX,tencent.com,DIRECT'
- 'DOMAIN-SUFFIX,tenpay.com,DIRECT'
- 'DOMAIN-SUFFIX,tianyancha.com,DIRECT'
- 'DOMAIN-SUFFIX,tmall.com,DIRECT'
- 'DOMAIN-SUFFIX,tudou.com,DIRECT'
- 'DOMAIN-SUFFIX,umetrip.com,DIRECT'
- 'DOMAIN-SUFFIX,upaiyun.com,DIRECT'
- 'DOMAIN-SUFFIX,upyun.com,DIRECT'
- 'DOMAIN-SUFFIX,veryzhun.com,DIRECT'
- 'DOMAIN-SUFFIX,weather.com,DIRECT'
- 'DOMAIN-SUFFIX,weibo.com,DIRECT'
- 'DOMAIN-SUFFIX,xiami.com,DIRECT'
- 'DOMAIN-SUFFIX,xiami.net,DIRECT'
- 'DOMAIN-SUFFIX,xiaomicp.com,DIRECT'
- 'DOMAIN-SUFFIX,ximalaya.com,DIRECT'
- 'DOMAIN-SUFFIX,xmcdn.com,DIRECT'
- 'DOMAIN-SUFFIX,xunlei.com,DIRECT'
- 'DOMAIN-SUFFIX,yhd.com,DIRECT'
- 'DOMAIN-SUFFIX,yihaodianimg.com,DIRECT'
- 'DOMAIN-SUFFIX,yinxiang.com,DIRECT'
- 'DOMAIN-SUFFIX,ykimg.com,DIRECT'
- 'DOMAIN-SUFFIX,youdao.com,DIRECT'
- 'DOMAIN-SUFFIX,youku.com,DIRECT'
- 'DOMAIN-SUFFIX,zealer.com,DIRECT'
- 'DOMAIN-SUFFIX,zhihu.com,DIRECT'
- 'DOMAIN-SUFFIX,zhimg.com,DIRECT'
- 'DOMAIN-SUFFIX,zimuzu.tv,DIRECT'
- 'DOMAIN-SUFFIX,zoho.com,DIRECT'
- 'DOMAIN-SUFFIX,emby.xiaoya.pro,DIRECT'
- 'DOMAIN-SUFFIX,icyou.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,lanyuewan.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby.8.net.co,DIRECT'
- 'DOMAIN-SUFFIX,emby.raydoom.tk,DIRECT'
- 'DOMAIN-SUFFIX,emby.kaiserver.uk,DIRECT'
- 'DOMAIN-SUFFIX,embyxiaoya.laogl.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.poxi1221.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ermaokj.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.bdbd.fun,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wwwh.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.f1rst.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ymschh.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wx1.us.kg,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.r2s.site,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.neversay.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.800686.xyz,DIRECT'
- 'DOMAIN-SUFFIX,syncthing.net,DIRECT'
- 'DOMAIN-SUFFIX,3322.org,DIRECT'
- 'DOMAIN-SUFFIX,picp.net,DIRECT'
- 'DOMAIN-SUFFIX,3322.org,DIRECT'
- 'DOMAIN-SUFFIX,picp.net,DIRECT'
- 'DOMAIN-SUFFIX,wicp.net,DIRECT'
- 'DOMAIN-SUFFIX,xicp.cn,DIRECT'
- 'DOMAIN-SUFFIX,dscloud.me,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.top,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.cn,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.top,DIRECT'
- 'DOMAIN-SUFFIX,againgo.top,DIRECT'
- 'DOMAIN-SUFFIX,himan.vip,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.me,DIRECT'
- 'DOMAIN-SUFFIX,xuanyuan.me,DIRECT'
- 'DOMAIN-SUFFIX,1ms.run,DIRECT'
- 'DOMAIN-KEYWORD,amazon,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,google,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,gmail,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,youtube,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,facebook,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,fb.me,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,fbcdn.net,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,twitter,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,instagram,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,dropbox,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,twimg.com,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,blogspot,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,youtu.be,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,whatsapp,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,admarvel,REJECT'
- 'DOMAIN-KEYWORD,admaster,REJECT'
- 'DOMAIN-KEYWORD,adsage,REJECT'
- 'DOMAIN-KEYWORD,adsmogo,REJECT'
- 'DOMAIN-KEYWORD,adsrvmedia,REJECT'
- 'DOMAIN-KEYWORD,adwords,REJECT'
- 'DOMAIN-KEYWORD,adservice,REJECT'
- 'DOMAIN-SUFFIX,appsflyer.com,REJECT'
- 'DOMAIN-KEYWORD,domob,REJECT'
- 'DOMAIN-SUFFIX,doubleclick.net,REJECT'
- 'DOMAIN-KEYWORD,duomeng,REJECT'
- 'DOMAIN-KEYWORD,dwtrack,REJECT'
- 'DOMAIN-KEYWORD,guanggao,REJECT'
- 'DOMAIN-KEYWORD,lianmeng,REJECT'
- 'DOMAIN-SUFFIX,mmstat.com,REJECT'
- 'DOMAIN-KEYWORD,mopub,REJECT'
- 'DOMAIN-KEYWORD,omgmta,REJECT'
- 'DOMAIN-KEYWORD,openx,REJECT'
- 'DOMAIN-KEYWORD,partnerad,REJECT'
- 'DOMAIN-KEYWORD,pingfore,REJECT'
- 'DOMAIN-KEYWORD,supersonicads,REJECT'
- 'DOMAIN-KEYWORD,uedas,REJECT'
- 'DOMAIN-KEYWORD,umeng,REJECT'
- 'DOMAIN-KEYWORD,usage,REJECT'
- 'DOMAIN-SUFFIX,vungle.com,REJECT'
- 'DOMAIN-KEYWORD,wlmonitor,REJECT'
- 'DOMAIN-KEYWORD,zjtoolbar,REJECT'
- 'DOMAIN-SUFFIX,9to5mac.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,abpchina.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,adblockplus.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,adobe.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,akamaized.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,alfredapp.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,amplitude.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ampproject.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,android.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,angularjs.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,aolcdn.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,apkpure.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,appledaily.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,appshopper.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,appspot.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,arcgis.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,archive.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,armorgames.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,aspnetcdn.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,att.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,awsstatic.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,azureedge.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,azurewebsites.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,bing.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,bintray.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,bit.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,bit.ly,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,bitbucket.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,bjango.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,bkrtx.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,blog.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,blogcdn.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,blogger.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,blogsmithmedia.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,blogspot.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,blogspot.hk,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,bloomberg.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,box.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,box.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,cachefly.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,chromium.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,cl.ly,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,cloudflare.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,cloudfront.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,cloudmagic.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,cmail19.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,cnet.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,cocoapods.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,comodoca.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,crashlytics.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,culturedcode.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,d.pr,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,danilo.to,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,dayone.me,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,db.tt,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,deskconnect.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,disq.us,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,disqus.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,disquscdn.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,dnsimple.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,docker.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,dribbble.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,droplr.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,duckduckgo.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,dueapp.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,dytt8.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,edgecastcdn.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,edgekey.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,edgesuite.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,engadget.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,entrust.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,eurekavpt.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,evernote.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,fabric.io,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,fast.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,fastly.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,fc2.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,feedburner.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,feedly.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,feedsportal.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,fiftythree.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,firebaseio.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,flexibits.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,flickr.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,flipboard.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,g.co,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,gabia.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,geni.us,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,gfx.ms,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ggpht.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ghostnoteapp.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,git.io,IPLC 国际流量站'
- 'DOMAIN-KEYWORD,github,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,globalsign.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,gmodules.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,godaddy.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,golang.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,gongm.in,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,goo.gl,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,goodreaders.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,goodreads.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,gravatar.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,gstatic.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,gvt0.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,hockeyapp.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,hotmail.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,icons8.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ifixit.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ift.tt,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ifttt.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,iherb.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,imageshack.us,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,img.ly,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,imgur.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,imore.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,instapaper.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ipn.li,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,is.gd,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,issuu.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,itgonglun.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,itun.es,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ixquick.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,j.mp,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,js.revsci.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,jshint.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,jtvnw.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,justgetflux.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,kat.cr,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,klip.me,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,libsyn.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,linkedin.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,line-apps.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,linode.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,lithium.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,littlehj.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,live.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,live.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,livefilestore.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,llnwd.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,macid.co,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,macromedia.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,macrumors.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,mashable.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,mathjax.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,medium.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,mega.co.nz,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,mega.nz,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,megaupload.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,microsofttranslator.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,mindnode.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,mobile01.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,modmyi.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,msedge.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,myfontastic.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,name.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,nextmedia.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,nsstatic.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,nssurge.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,nyt.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,nytimes.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,omnigroup.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,onedrive.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,onenote.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ooyala.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,openvpn.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,openwrt.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,orkut.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,osxdaily.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,outlook.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ow.ly,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,paddleapi.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,parallels.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,parse.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,pdfexpert.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,periscope.tv,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,pinboard.in,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,pinterest.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,pixelmator.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,pixiv.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,playpcesor.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,playstation.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,playstation.com.hk,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,playstation.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,playstationnetwork.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,pushwoosh.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,rime.im,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,servebom.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,sfx.ms,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,shadowsocks.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,sharethis.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,shazam.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,skype.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,slack.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,smartdnsIPLC 国际流量站.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,smartmailcloud.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,sndcdn.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,sony.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,soundcloud.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,sourceforge.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,spotify.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,squarespace.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,sstatic.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,st.luluku.pw,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,stackoverflow.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,startpage.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,staticflickr.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,steamcommunity.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,symauth.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,symcb.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,symcd.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tapbots.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tapbots.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tdesktop.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,techcrunch.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,techsmith.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,thepiratebay.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,theverge.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,time.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,timeinc.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tiny.cc,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tinypic.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tmblr.co,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,todoist.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,trello.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,trustasiassl.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tumblr.co,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tumblr.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tweetdeck.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,tweetmarker.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,twitch.tv,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,txmblr.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,typekit.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ubertags.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ublock.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ubnt.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ulyssesapp.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,urchin.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,usertrust.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,v.gd,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,v2ex.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,vimeo.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,vimeocdn.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,vine.co,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,vivaldi.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,vox-cdn.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,vsco.co,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,vultr.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,w.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,w3schools.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,webtype.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wikiwand.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wikileaks.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wikimedia.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wikipedia.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wikipedia.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,windows.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,windows.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wire.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wordpress.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,workflowy.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wp.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wsj.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,wsj.net,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,xda-developers.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,xeeno.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,xiti.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,yahoo.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,yimg.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ying.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,yoyo.org,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,ytimg.com,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,telegra.ph,IPLC 国际流量站'
- 'DOMAIN-SUFFIX,telegram.org,IPLC 国际流量站'
- 'IP-CIDR,91.108.4.0/22,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,91.108.8.0/21,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,91.108.16.0/22,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,91.108.56.0/22,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,149.154.160.0/20,IPLC 国际流量站,no-resolve'
- 'IP-CIDR6,2001:67c:4e8::/48,IPLC 国际流量站,no-resolve'
- 'IP-CIDR6,2001:b28:f23d::/48,IPLC 国际流量站,no-resolve'
- 'IP-CIDR6,2001:b28:f23f::/48,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,120.232.181.162/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,120.241.147.226/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,120.253.253.226/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,120.253.255.162/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,120.253.255.34/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,120.253.255.98/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,180.163.150.162/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,180.163.150.34/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,180.163.151.162/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,180.163.151.34/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,203.208.39.0/24,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,203.208.40.0/24,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,203.208.41.0/24,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,203.208.43.0/24,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,203.208.50.0/24,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,220.181.174.162/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,220.181.174.226/32,IPLC 国际流量站,no-resolve'
- 'IP-CIDR,220.181.174.34/32,IPLC 国际流量站,no-resolve'
- 'DOMAIN,injections.adguard.org,DIRECT'
- 'DOMAIN,local.adguard.org,DIRECT'
- 'DOMAIN-SUFFIX,local,DIRECT'
- 'IP-CIDR,127.0.0.0/8,DIRECT'
- 'IP-CIDR,172.16.0.0/12,DIRECT'
- 'IP-CIDR,192.168.0.0/16,DIRECT'
- 'IP-CIDR,10.0.0.0/8,DIRECT'
- 'IP-CIDR,17.0.0.0/8,DIRECT'
- 'IP-CIDR,100.64.0.0/10,DIRECT'
- 'IP-CIDR,224.0.0.0/4,DIRECT'
- 'IP-CIDR6,fe80::/10,DIRECT'
- 'DOMAIN-SUFFIX,cn,DIRECT'
- 'DOMAIN-KEYWORD,-cn,DIRECT'
- 'GEOIP,CN,DIRECT'
- 'MATCH,IPLC 国际流量站'
+211
View File
@@ -0,0 +1,211 @@
mixed-port: 7890
allow-lan: true
bind-address: '*'
mode: rule
log-level: info
external-controller: '0.0.0.0:9090'
tun:
enable: true
stack: mixed
dns-hijack:
- "any:53"
- "tcp://any:53"
auto-route: true
auto-redirect: true
auto-detect-interface: true
proxy-providers:
IPLC:
url: "https://sub.20250715iplcsub.link/qC8zV8qS1kB1lX2u/4OLCCKkHWHgeCM6m"
type: http
interval: 86400
health-check: {enable: true,url: "https://www.gstatic.com/generate_204", interval: 300}
override:
additional-prefix: "IPLC"
proxies:
- name: "直连"
type: direct
udp: true
geodata-mode: true
geox-url:
geoip: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat"
geosite: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat"
mmdb: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb"
asn: "https://gh-proxy.com/https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb"
dns:
enable: true
ipv6: true
respect-rules: true
enhanced-mode: fake-ip
fake-ip-filter:
- "*"
- "+.lan"
- "+.local"
- "+.market.xiaomi.com"
nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
proxy-server-nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
nameserver-policy:
"geosite:cn,private":
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
"geosite:geolocation-!cn":
- "https://dns.cloudflare.com/dns-query"
- "https://dns.google/dns-query"
proxy-groups:
- name: 默认
type: select
proxies: [自动选择,直连,香港,台湾,日本,新加坡,美国,其它地区,全部节点]
- name: Google
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Telegram
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Twitter
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 哔哩哔哩
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 巴哈姆特
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: YouTube
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: NETFLIX
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Spotify
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Github
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 国内
type: select
proxies: [直连,默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择]
- name: 其他
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
#分隔,下面是地区分组
- name: 香港
type: select
include-all: true
filter: "(?i)港|hk|hongkong|hong kong"
- name: 台湾
type: select
include-all: true
filter: "(?i)台|tw|taiwan"
- name: 日本
type: select
include-all: true
filter: "(?i)日|jp|japan"
- name: 美国
type: select
include-all: true
filter: "(?i)美|us|unitedstates|united states"
- name: 新加坡
type: select
include-all: true
filter: "(?i)(新|sg|singapore)"
- name: 其它地区
type: select
include-all: true
filter: "(?i)^(?!.*(?:|||||港|hk|hongkong|台|tw|taiwan|日|jp|japan|新|sg|singapore|美|us|unitedstates)).*"
- name: 全部节点
type: select
include-all: true
- name: 自动选择
type: url-test
include-all: true
tolerance: 10
rules:
- 'DOMAIN-SUFFIX,synology.com,DIRECT'
- 'DOMAIN-SUFFIX,digitalocean.com,DIRECT'
- 'DOMAIN-SUFFIX,synocommunity.com,DIRECT'
- 'DOMAIN-SUFFIX,emby.xiaoya.pro,DIRECT'
- 'DOMAIN-SUFFIX,icyou.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,lanyuewan.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby.8.net.co,DIRECT'
- 'DOMAIN-SUFFIX,emby.raydoom.tk,DIRECT'
- 'DOMAIN-SUFFIX,emby.kaiserver.uk,DIRECT'
- 'DOMAIN-SUFFIX,embyxiaoya.laogl.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.poxi1221.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ermaokj.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.bdbd.fun,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wwwh.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.f1rst.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ymschh.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wx1.us.kg,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.r2s.site,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.neversay.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.800686.xyz,DIRECT'
- 'DOMAIN-SUFFIX,syncthing.net,DIRECT'
- 'DOMAIN-SUFFIX,3322.org,DIRECT'
- 'DOMAIN-SUFFIX,picp.net,DIRECT'
- 'DOMAIN-SUFFIX,wicp.net,DIRECT'
- 'DOMAIN-SUFFIX,xicp.cn,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.top,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.cn,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.top,DIRECT'
- 'DOMAIN-SUFFIX,againgo.top,DIRECT'
- 'DOMAIN-SUFFIX,himan.vip,DIRECT'
- 'DOMAIN-SUFFIX,himan.cloud,DIRECT'
- 'DOMAIN-SUFFIX,himan.top,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.me,DIRECT'
- 'DOMAIN-SUFFIX,xuanyuan.me,DIRECT'
- 'DOMAIN-SUFFIX,1ms.run,DIRECT'
- GEOIP,lan,直连,no-resolve
- GEOSITE,github,Github
- GEOSITE,twitter,Twitter
- GEOSITE,youtube,YouTube
- GEOSITE,google,Google
- GEOSITE,telegram,Telegram
- GEOSITE,netflix,NETFLIX
- GEOSITE,bilibili,哔哩哔哩
- GEOSITE,bahamut,巴哈姆特
- GEOSITE,spotify,Spotify
- GEOSITE,CN,国内
- GEOSITE,geolocation-!cn,其他
- GEOIP,google,Google
- GEOIP,netflix,NETFLIX
- GEOIP,telegram,Telegram
- GEOIP,twitter,Twitter
- GEOIP,CN,国内
- MATCH,其他
+16
View File
@@ -0,0 +1,16 @@
services:
calibre-web-automated:
image: crocodilestick/calibre-web-automated:latest
container_name: calibre-web-automated
network_mode: bridge
environment:
- PUID=1000
- PGID=100
- TZ=Asia/Shanghai
volumes:
- /vol2/1000/docker/CWA/config:/config
- /vol3/1000/USBD1/Imports:/cwa-book-ingest
- /vol3/1000/USBD1/Books:/calibre-library
ports:
- 7083:8083
restart: always
+20
View File
@@ -0,0 +1,20 @@
version: "3"
services:
syncthing:
image: syncthing/syncthing:latest
container_name: syncthing
hostname: syncthing-fn
environment:
- PUID=1000
- PGID=1000
- STGUIADDRESS=0.0.0.0:8384
volumes:
- /vol2/1000/docker/syncthing:/var/syncthing
- /vol3/1000/USBD1/Imports:/data1
network_mode: host
restart: always
healthcheck:
test: curl -fkLsS -m 2 127.0.0.1:8384/rest/noauth/health | grep -o --color=never OK || exit 1
interval: 1m
timeout: 10s
retries: 3
+25
View File
@@ -0,0 +1,25 @@
version: '2.0'
services:
chatgpt-on-wechat:
image: zhayujie/chatgpt-on-wechat
container_name: chatgpt-on-wechat
security_opt:
- seccomp:unconfined
environment:
CHANNEL_TYPE: 'web'
OPEN_AI_API_KEY: 'YOUR API KEY'
MODEL: ''
PROXY: ''
SINGLE_CHAT_PREFIX: '["bot", "@bot"]'
SINGLE_CHAT_REPLY_PREFIX: '"[bot] "'
GROUP_CHAT_PREFIX: '["@bot"]'
GROUP_NAME_WHITE_LIST: '["ChatGPT测试群", "ChatGPT测试群2"]'
IMAGE_CREATE_PREFIX: '["画", "看", "找"]'
CONVERSATION_MAX_TOKENS: 1000
SPEECH_RECOGNITION: 'False'
CHARACTER_DESC: '你是基于大语言模型的AI智能助手,旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。'
EXPIRES_IN_SECONDS: 3600
USE_GLOBAL_PLUGIN_CONFIG: 'True'
USE_LINKAI: 'False'
LINKAI_API_KEY: ''
LINKAI_APP_CODE: ''
+174
View File
@@ -0,0 +1,174 @@
services:
onlyoffice-mysql-server:
container_name: onlyoffice-mysql-server
image: mysql:8.0.29
environment:
- MYSQL_ROOT_PASSWORD=my-secret-pw
networks:
- onlyoffice
stdin_open: true
tty: true
restart: always
volumes:
- ./config/mysql/conf.d:/etc/mysql/conf.d
- ./config/mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
- mysql_data:/var/lib/mysql
onlyoffice-community-server:
container_name: onlyoffice-community-server
image: onlyoffice/communityserver:12.6.0.1900
depends_on:
- onlyoffice-mysql-server
- onlyoffice-document-server
- onlyoffice-mail-server
- onlyoffice-elasticsearch
environment:
- ONLYOFFICE_CORE_MACHINEKEY=core_secret
- CONTROL_PANEL_PORT_80_TCP=80
- CONTROL_PANEL_PORT_80_TCP_ADDR=onlyoffice-control-panel
- DOCUMENT_SERVER_PORT_80_TCP_ADDR=onlyoffice-document-server
- DOCUMENT_SERVER_JWT_ENABLED=true
- DOCUMENT_SERVER_JWT_SECRET=jwt_secret
- DOCUMENT_SERVER_JWT_HEADER=AuthorizationJwt
- MYSQL_SERVER_ROOT_PASSWORD=my-secret-pw
- MYSQL_SERVER_DB_NAME=onlyoffice
- MYSQL_SERVER_HOST=onlyoffice-mysql-server
- MYSQL_SERVER_USER=onlyoffice_user
- MYSQL_SERVER_PASS=onlyoffice_pass
- MAIL_SERVER_API_PORT=8081
- MAIL_SERVER_API_HOST=onlyoffice-mail-server
- MAIL_SERVER_DB_HOST=onlyoffice-mysql-server
- MAIL_SERVER_DB_PORT=3306
- MAIL_SERVER_DB_NAME=onlyoffice_mailserver
- MAIL_SERVER_DB_USER=mail_admin
- MAIL_SERVER_DB_PASS=Isadmin123
- ELASTICSEARCH_SERVER_HOST=onlyoffice-elasticsearch
- ELASTICSEARCH_SERVER_HTTPPORT=9200
networks:
- onlyoffice
ports:
- '80:80'
- '443:443'
- '5222:5222'
stdin_open: true
tty: true
restart: always
privileged: true
cgroup: host
volumes:
- community_data:/var/www/onlyoffice/Data
- community_log:/var/log/onlyoffice
- community_letsencrypt:/etc/letsencrypt
- document_data:/var/www/onlyoffice/DocumentServerData
- /sys/fs/cgroup:/sys/fs/cgroup:rw
- ./certs:/var/www/onlyoffice/Data/certs
onlyoffice-elasticsearch:
image: onlyoffice/elasticsearch:7.16.3
container_name: onlyoffice-elasticsearch
restart: always
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms1g -Xmx1g -Dlog4j2.formatMsgNoLookups=true"
- "indices.fielddata.cache.size=30%"
- "indices.memory.index_buffer_size=30%"
- "ingest.geoip.downloader.enabled=false"
networks:
- onlyoffice
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65535
hard: 65535
volumes:
- es_data:/usr/share/elasticsearch/data
expose:
- "9200"
- "9300"
onlyoffice-document-server:
container_name: onlyoffice-document-server
image: onlyoffice/documentserver:8.1
stdin_open: true
tty: true
restart: always
environment:
- JWT_ENABLED=true
- JWT_SECRET=jwt_secret
- JWT_HEADER=AuthorizationJwt
networks:
- onlyoffice
expose:
- '80'
- '443'
volumes:
- document_data:/var/www/onlyoffice/Data
- document_log:/var/log/onlyoffice
- ./document_fonts:/usr/share/fonts/truetype/custom
- document_forgotten:/var/lib/onlyoffice/documentserver/App_Data/cache/files/forgotten
onlyoffice-mail-server:
container_name: onlyoffice-mail-server
image: onlyoffice/mailserver:1.6.75
depends_on:
- onlyoffice-mysql-server
hostname: ${MAIL_SERVER_HOSTNAME}
environment:
- MYSQL_SERVER=onlyoffice-mysql-server
- MYSQL_SERVER_PORT=3306
- MYSQL_ROOT_USER=mail_admin
- MYSQL_ROOT_PASSWD=Isadmin123
- MYSQL_SERVER_DB_NAME=onlyoffice_mailserver
networks:
- onlyoffice
restart: always
privileged: true
ports: ['25:25','143:143','587:587']
stdin_open: true
tty: true
expose:
- '8081'
- '3306'
volumes:
- mail_data:/var/vmail
- mail_certs:/etc/pki/tls/mailserver
- mail_log:/var/log
onlyoffice-control-panel:
container_name: onlyoffice-control-panel
depends_on:
- onlyoffice-document-server
- onlyoffice-mail-server
- onlyoffice-community-server
image: onlyoffice/controlpanel:3.5.2.530
environment:
- ONLYOFFICE_CORE_MACHINEKEY=core_secret
expose:
- '80'
- '443'
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- controlpanel_data:/var/www/onlyoffice/Data
- controlpanel_log:/var/log/onlyoffice
networks:
- onlyoffice
stdin_open: true
tty: true
networks:
onlyoffice:
driver: 'bridge'
volumes:
mail_data:
mail_certs:
mail_log:
mail_mysql:
document_data:
document_log:
document_forgotten:
community_mysql:
community_data:
community_log:
community_letsencrypt:
controlpanel_data:
controlpanel_log:
mysql_data:
es_data:
+25
View File
@@ -0,0 +1,25 @@
version: '2.0'
services:
chatgpt-on-wechat:
image: zhayujie/chatgpt-on-wechat
container_name: chatgpt-on-wechat
security_opt:
- seccomp:unconfined
environment:
OPEN_AI_API_KEY: 'sk-1A7f5vBSlhudYmxmyxxxxxxxx7i4KmuHy9ZxPO'
open_ai_api_base: 'https://api.chatanywhere.tech/v1'
MODEL: 'gpt-4o-mini'
PROXY: ''
SINGLE_CHAT_PREFIX: '["bot", "@bot"]'
SINGLE_CHAT_REPLY_PREFIX: '"[bot] "'
GROUP_CHAT_PREFIX: '["@bot"]'
GROUP_NAME_WHITE_LIST: '["ChatGPT测试群", "ChatGPT测试群2"]'
IMAGE_CREATE_PREFIX: '["画", "看", "找"]'
CONVERSATION_MAX_TOKENS: 1000
SPEECH_RECOGNITION: 'False'
CHARACTER_DESC: '你是基于大语言模型的AI智能助手,旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。'
EXPIRES_IN_SECONDS: 3600
USE_GLOBAL_PLUGIN_CONFIG: 'True'
USE_LINKAI: 'False'
LINKAI_API_KEY: ''
LINKAI_APP_CODE: ''
+56
View File
@@ -0,0 +1,56 @@
# 与服务端建立连接,跟上面的配置要对应 阿里106.15.121.26 腾讯150.158.120.215 联通云 116.162.100.119
serverAddr = "124.220.30.149"
serverPort = 7000
# 配置Token鉴权,要与服务端一致
auth.method = "token"
auth.token = "admin8466"
# 配置日志信息
#log.level = "warn"
#log.to = "/opt/frpc/frpc.log"
# frpc.toml
webServer.addr = "192.168.1.108"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "admin8466"
[[proxies]]
name = "frp-fnOS-openlist-9161"
type = "tcp"
localIP = "127.0.0.1"
localPort = 7244
remotePort = 9161
[[proxies]]
name = "frp-dsm-lskypro"
type = "tcp"
localIP = "192.168.1.181"
localPort = 6089
remotePort = 6089
[[proxies]]
name = "frp-fnOS-cwa"
type = "tcp"
localIP = "127.0.0.1"
localPort = 7083
remotePort = 7083
[[proxies]]
name = "frp-fnOS-photo"
type = "tcp"
localIP = "127.0.0.1"
localPort = 2342
remotePort = 2342
+4
View File
@@ -0,0 +1,4 @@
eyJhbGciOiJIUzI1NiIsImtpZCI6InYxIiwidHlwIjoiSldUIn0
memos_pat_BwWQTJJhR1UoNBhkMkkfMQzthWaqXWVR
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
+172
View File
@@ -0,0 +1,172 @@
mixed-port: 7890
allow-lan: true
bind-address: '*'
mode: rule
log-level: info
external-controller: '0.0.0.0:9090'
tun:
enable: true
stack: mixed
dns-hijack:
- "any:53"
- "tcp://any:53"
auto-route: true
auto-redirect: true
auto-detect-interface: true
proxy-providers:
OneMuggle:
url: "订阅链接"
type: http
interval: 86400
health-check: {enable: true,url: "https://www.gstatic.com/generate_204", interval: 300}
override:
additional-prefix: "Muggle"
proxies:
- name: "直连"
type: direct
udp: true
geodata-mode: true
geox-url:
geoip: "https://mirror.ghproxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat"
geosite: "https://mirror.ghproxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat"
mmdb: "https://mirror.ghproxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb"
asn: "https://mirror.ghproxy.com/https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb"
dns:
enable: true
ipv6: true
respect-rules: true
enhanced-mode: fake-ip
fake-ip-filter:
- "*"
- "+.lan"
- "+.local"
- "+.market.xiaomi.com"
nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
proxy-server-nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
nameserver-policy:
"geosite:cn,private":
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
"geosite:geolocation-!cn":
- "https://dns.cloudflare.com/dns-query"
- "https://dns.google/dns-query"
proxy-groups:
- name: 默认
type: select
proxies: [自动选择,直连,香港,台湾,日本,新加坡,美国,其它地区,全部节点]
- name: Google
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Telegram
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Twitter
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 哔哩哔哩
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 巴哈姆特
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: YouTube
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: NETFLIX
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Spotify
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Github
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 国内
type: select
proxies: [直连,默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择]
- name: 其他
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
#分隔,下面是地区分组
- name: 香港
type: select
include-all: true
filter: "(?i)港|hk|hongkong|hong kong"
- name: 台湾
type: select
include-all: true
filter: "(?i)台|tw|taiwan"
- name: 日本
type: select
include-all: true
filter: "(?i)日|jp|japan"
- name: 美国
type: select
include-all: true
filter: "(?i)美|us|unitedstates|united states"
- name: 新加坡
type: select
include-all: true
filter: "(?i)(新|sg|singapore)"
- name: 其它地区
type: select
include-all: true
filter: "(?i)^(?!.*(?:|||||港|hk|hongkong|台|tw|taiwan|日|jp|japan|新|sg|singapore|美|us|unitedstates)).*"
- name: 全部节点
type: select
include-all: true
- name: 自动选择
type: url-test
include-all: true
tolerance: 10
rules:
- GEOIP,lan,直连,no-resolve
- GEOSITE,github,Github
- GEOSITE,twitter,Twitter
- GEOSITE,youtube,YouTube
- GEOSITE,google,Google
- GEOSITE,telegram,Telegram
- GEOSITE,netflix,NETFLIX
- GEOSITE,bilibili,哔哩哔哩
- GEOSITE,bahamut,巴哈姆特
- GEOSITE,spotify,Spotify
- GEOSITE,CN,国内
- GEOSITE,geolocation-!cn,其他
- GEOIP,google,Google
- GEOIP,netflix,NETFLIX
- GEOIP,telegram,Telegram
- GEOIP,twitter,Twitter
- GEOIP,CN,国内
- MATCH,其他
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
+211
View File
@@ -0,0 +1,211 @@
mixed-port: 7890
allow-lan: true
bind-address: '*'
mode: rule
log-level: info
external-controller: '0.0.0.0:9090'
tun:
enable: true
stack: mixed
dns-hijack:
- "any:53"
- "tcp://any:53"
auto-route: true
auto-redirect: true
auto-detect-interface: true
proxy-providers:
狗狗加速:
url: "https://xwj6tm.doggygosubs.com:8443/api/v1/client/5a471ca14910318c9491470a62a712ea?flag=mihomo"
type: http
interval: 86400
health-check: {enable: true,url: "https://www.gstatic.com/generate_204", interval: 300}
override:
additional-prefix: "IPLC"
proxies:
- name: "直连"
type: direct
udp: true
geodata-mode: true
geox-url:
geoip: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat"
geosite: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat"
mmdb: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb"
asn: "https://gh-proxy.com/https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb"
dns:
enable: true
ipv6: true
respect-rules: true
enhanced-mode: fake-ip
fake-ip-filter:
- "*"
- "+.lan"
- "+.local"
- "+.market.xiaomi.com"
nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
proxy-server-nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
nameserver-policy:
"geosite:cn,private":
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
"geosite:geolocation-!cn":
- "https://dns.cloudflare.com/dns-query"
- "https://dns.google/dns-query"
proxy-groups:
- name: 默认
type: select
proxies: [自动选择,直连,香港,台湾,日本,新加坡,美国,其它地区,全部节点]
- name: Google
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Telegram
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Twitter
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 哔哩哔哩
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 巴哈姆特
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: YouTube
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: NETFLIX
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Spotify
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Github
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 国内
type: select
proxies: [直连,默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择]
- name: 其他
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
#分隔,下面是地区分组
- name: 香港
type: select
include-all: true
filter: "(?i)港|hk|hongkong|hong kong"
- name: 台湾
type: select
include-all: true
filter: "(?i)台|tw|taiwan"
- name: 日本
type: select
include-all: true
filter: "(?i)日|jp|japan"
- name: 美国
type: select
include-all: true
filter: "(?i)美|us|unitedstates|united states"
- name: 新加坡
type: select
include-all: true
filter: "(?i)(新|sg|singapore)"
- name: 其它地区
type: select
include-all: true
filter: "(?i)^(?!.*(?:|||||港|hk|hongkong|台|tw|taiwan|日|jp|japan|新|sg|singapore|美|us|unitedstates)).*"
- name: 全部节点
type: select
include-all: true
- name: 自动选择
type: url-test
include-all: true
tolerance: 10
rules:
- 'DOMAIN-SUFFIX,synology.com,DIRECT'
- 'DOMAIN-SUFFIX,digitalocean.com,DIRECT'
- 'DOMAIN-SUFFIX,synocommunity.com,DIRECT'
- 'DOMAIN-SUFFIX,emby.xiaoya.pro,DIRECT'
- 'DOMAIN-SUFFIX,icyou.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,lanyuewan.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby.8.net.co,DIRECT'
- 'DOMAIN-SUFFIX,emby.raydoom.tk,DIRECT'
- 'DOMAIN-SUFFIX,emby.kaiserver.uk,DIRECT'
- 'DOMAIN-SUFFIX,embyxiaoya.laogl.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.poxi1221.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ermaokj.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.bdbd.fun,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wwwh.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.f1rst.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ymschh.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wx1.us.kg,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.r2s.site,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.neversay.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.800686.xyz,DIRECT'
- 'DOMAIN-SUFFIX,syncthing.net,DIRECT'
- 'DOMAIN-SUFFIX,3322.org,DIRECT'
- 'DOMAIN-SUFFIX,picp.net,DIRECT'
- 'DOMAIN-SUFFIX,wicp.net,DIRECT'
- 'DOMAIN-SUFFIX,xicp.cn,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.top,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.cn,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.top,DIRECT'
- 'DOMAIN-SUFFIX,againgo.top,DIRECT'
- 'DOMAIN-SUFFIX,himan.vip,DIRECT'
- 'DOMAIN-SUFFIX,himan.cloud,DIRECT'
- 'DOMAIN-SUFFIX,himan.top,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.me,DIRECT'
- 'DOMAIN-SUFFIX,xuanyuan.me,DIRECT'
- 'DOMAIN-SUFFIX,1ms.run,DIRECT'
- GEOIP,lan,直连,no-resolve
- GEOSITE,github,Github
- GEOSITE,twitter,Twitter
- GEOSITE,youtube,YouTube
- GEOSITE,google,Google
- GEOSITE,telegram,Telegram
- GEOSITE,netflix,NETFLIX
- GEOSITE,bilibili,哔哩哔哩
- GEOSITE,bahamut,巴哈姆特
- GEOSITE,spotify,Spotify
- GEOSITE,CN,国内
- GEOSITE,geolocation-!cn,其他
- GEOIP,google,Google
- GEOIP,netflix,NETFLIX
- GEOIP,telegram,Telegram
- GEOIP,twitter,Twitter
- GEOIP,CN,国内
- MATCH,其他
@@ -0,0 +1,421 @@
mixed-port: 7890
allow-lan: true
bind-address: '*'
mode: rule
log-level: info
external-controller: '0.0.0.0:9090'
tun:
enable: true
stack: mixed
dns-hijack:
- "any:53"
- "tcp://any:53"
auto-route: true
auto-redirect: true
auto-detect-interface: true
proxy-providers:
gg:
url: "https://xwj6tm.doggygosubs.com:8443/api/v1/client/5a471ca14910318c9491470a62a712ea?flag=mihomo"
type: http
interval: 86400
health-check: {enable: true,url: "https://www.gstatic.com/generate_204", interval: 300}
override:
additional-prefix: "gg"
proxies:
- name: "直连"
type: direct
udp: truemixed-port: 7890
allow-lan: true
bind-address: '*'
mode: rule
log-level: info
external-controller: '0.0.0.0:9090'
tun:
enable: true
stack: mixed
dns-hijack:
- "any:53"
- "tcp://any:53"
auto-route: true
auto-redirect: true
auto-detect-interface: true
proxy-providers:
IPLC:
url: "https://sub.20250715iplcsub.link/qC8zV8qS1kB1lX2u/4OLCCKkHWHgeCM6m?clash=1"
type: http
interval: 86400
health-check: {enable: true,url: "https://www.gstatic.com/generate_204", interval: 300}
override:
additional-prefix: "IPLC"
proxies:
- name: "直连"
type: direct
udp: true
geodata-mode: true
geox-url:
geoip: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat"
geosite: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat"
mmdb: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb"
asn: "https://gh-proxy.com/https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb"
dns:
enable: true
ipv6: true
respect-rules: true
enhanced-mode: fake-ip
fake-ip-filter:
- "*"
- "+.lan"
- "+.local"
- "+.market.xiaomi.com"
nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
proxy-server-nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
nameserver-policy:
"geosite:cn,private":
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
"geosite:geolocation-!cn":
- "https://dns.cloudflare.com/dns-query"
- "https://dns.google/dns-query"
proxy-groups:
- name: 默认
type: select
proxies: [自动选择,直连,香港,台湾,日本,新加坡,美国,其它地区,全部节点]
- name: Google
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Telegram
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Twitter
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 哔哩哔哩
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 巴哈姆特
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: YouTube
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: NETFLIX
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Spotify
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Github
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 国内
type: select
proxies: [直连,默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择]
- name: 其他
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
#分隔,下面是地区分组
- name: 香港
type: select
include-all: true
filter: "(?i)港|hk|hongkong|hong kong"
- name: 台湾
type: select
include-all: true
filter: "(?i)台|tw|taiwan"
- name: 日本
type: select
include-all: true
filter: "(?i)日|jp|japan"
- name: 美国
type: select
include-all: true
filter: "(?i)美|us|unitedstates|united states"
- name: 新加坡
type: select
include-all: true
filter: "(?i)(新|sg|singapore)"
- name: 其它地区
type: select
include-all: true
filter: "(?i)^(?!.*(?:|||||港|hk|hongkong|台|tw|taiwan|日|jp|japan|新|sg|singapore|美|us|unitedstates)).*"
- name: 全部节点
type: select
include-all: true
- name: 自动选择
type: url-test
include-all: true
tolerance: 10
rules:
- 'DOMAIN-SUFFIX,synology.com,DIRECT'
- 'DOMAIN-SUFFIX,digitalocean.com,DIRECT'
- 'DOMAIN-SUFFIX,synocommunity.com,DIRECT'
- 'DOMAIN-SUFFIX,emby.xiaoya.pro,DIRECT'
- 'DOMAIN-SUFFIX,icyou.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,lanyuewan.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby.8.net.co,DIRECT'
- 'DOMAIN-SUFFIX,emby.raydoom.tk,DIRECT'
- 'DOMAIN-SUFFIX,emby.kaiserver.uk,DIRECT'
- 'DOMAIN-SUFFIX,embyxiaoya.laogl.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.poxi1221.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ermaokj.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.bdbd.fun,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wwwh.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.f1rst.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ymschh.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wx1.us.kg,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.r2s.site,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.neversay.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.800686.xyz,DIRECT'
- 'DOMAIN-SUFFIX,syncthing.net,DIRECT'
- 'DOMAIN-SUFFIX,3322.org,DIRECT'
- 'DOMAIN-SUFFIX,picp.net,DIRECT'
- 'DOMAIN-SUFFIX,wicp.net,DIRECT'
- 'DOMAIN-SUFFIX,xicp.cn,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.top,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.cn,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.top,DIRECT'
- 'DOMAIN-SUFFIX,againgo.top,DIRECT'
- 'DOMAIN-SUFFIX,himan.vip,DIRECT'
- 'DOMAIN-SUFFIX,himan.cloud,DIRECT'
- 'DOMAIN-SUFFIX,himan.top,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.me,DIRECT'
- 'DOMAIN-SUFFIX,xuanyuan.me,DIRECT'
- 'DOMAIN-SUFFIX,1ms.run,DIRECT'
- GEOIP,lan,直连,no-resolve
- GEOSITE,github,Github
- GEOSITE,twitter,Twitter
- GEOSITE,youtube,YouTube
- GEOSITE,google,Google
- GEOSITE,telegram,Telegram
- GEOSITE,netflix,NETFLIX
- GEOSITE,bilibili,哔哩哔哩
- GEOSITE,bahamut,巴哈姆特
- GEOSITE,spotify,Spotify
- GEOSITE,CN,国内
- GEOSITE,geolocation-!cn,其他
- GEOIP,google,Google
- GEOIP,netflix,NETFLIX
- GEOIP,telegram,Telegram
- GEOIP,twitter,Twitter
- GEOIP,CN,国内
- MATCH,其他
geodata-mode: true
geox-url:
geoip: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat"
geosite: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat"
mmdb: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb"
asn: "https://gh-proxy.com/https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb"
dns:
enable: true
ipv6: true
respect-rules: true
enhanced-mode: fake-ip
fake-ip-filter:
- "*"
- "+.lan"
- "+.local"
- "+.market.xiaomi.com"
nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
proxy-server-nameserver:
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
nameserver-policy:
"geosite:cn,private":
- https://120.53.53.53/dns-query
- https://223.5.5.5/dns-query
"geosite:geolocation-!cn":
- "https://dns.cloudflare.com/dns-query"
- "https://dns.google/dns-query"
proxy-groups:
- name: 默认
type: select
proxies: [自动选择,直连,香港,台湾,日本,新加坡,美国,其它地区,全部节点]
- name: Google
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Telegram
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Twitter
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 哔哩哔哩
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 巴哈姆特
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: YouTube
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: NETFLIX
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Spotify
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Github
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 国内
type: select
proxies: [直连,默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择]
- name: 其他
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
#分隔,下面是地区分组
- name: 香港
type: select
include-all: true
filter: "(?i)港|hk|hongkong|hong kong"
- name: 台湾
type: select
include-all: true
filter: "(?i)台|tw|taiwan"
- name: 日本
type: select
include-all: true
filter: "(?i)日|jp|japan"
- name: 美国
type: select
include-all: true
filter: "(?i)美|us|unitedstates|united states"
- name: 新加坡
type: select
include-all: true
filter: "(?i)(新|sg|singapore)"
- name: 其它地区
type: select
include-all: true
filter: "(?i)^(?!.*(?:|||||港|hk|hongkong|台|tw|taiwan|日|jp|japan|新|sg|singapore|美|us|unitedstates)).*"
- name: 全部节点
type: select
include-all: true
- name: 自动选择
type: url-test
include-all: true
tolerance: 10
rules:
- 'DOMAIN-SUFFIX,synology.com,DIRECT'
- 'DOMAIN-SUFFIX,digitalocean.com,DIRECT'
- 'DOMAIN-SUFFIX,synocommunity.com,DIRECT'
- 'DOMAIN-SUFFIX,emby.xiaoya.pro,DIRECT'
- 'DOMAIN-SUFFIX,icyou.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,lanyuewan.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby.8.net.co,DIRECT'
- 'DOMAIN-SUFFIX,emby.raydoom.tk,DIRECT'
- 'DOMAIN-SUFFIX,emby.kaiserver.uk,DIRECT'
- 'DOMAIN-SUFFIX,embyxiaoya.laogl.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.poxi1221.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ermaokj.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.bdbd.fun,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wwwh.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.f1rst.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ymschh.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wx1.us.kg,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.r2s.site,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.neversay.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.800686.xyz,DIRECT'
- 'DOMAIN-SUFFIX,syncthing.net,DIRECT'
- 'DOMAIN-SUFFIX,3322.org,DIRECT'
- 'DOMAIN-SUFFIX,picp.net,DIRECT'
- 'DOMAIN-SUFFIX,wicp.net,DIRECT'
- 'DOMAIN-SUFFIX,xicp.cn,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.top,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.cn,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.top,DIRECT'
- 'DOMAIN-SUFFIX,againgo.top,DIRECT'
- 'DOMAIN-SUFFIX,himan.vip,DIRECT'
- 'DOMAIN-SUFFIX,himan.cloud,DIRECT'
- 'DOMAIN-SUFFIX,himan.top,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.me,DIRECT'
- 'DOMAIN-SUFFIX,xuanyuan.me,DIRECT'
- 'DOMAIN-SUFFIX,1ms.run,DIRECT'
- GEOIP,lan,直连,no-resolve
- GEOSITE,github,Github
- GEOSITE,twitter,Twitter
- GEOSITE,youtube,YouTube
- GEOSITE,google,Google
- GEOSITE,telegram,Telegram
- GEOSITE,netflix,NETFLIX
- GEOSITE,bilibili,哔哩哔哩
- GEOSITE,bahamut,巴哈姆特
- GEOSITE,spotify,Spotify
- GEOSITE,CN,国内
- GEOSITE,geolocation-!cn,其他
- GEOIP,google,Google
- GEOIP,netflix,NETFLIX
- GEOIP,telegram,Telegram
- GEOIP,twitter,Twitter
- GEOIP,CN,国内
- MATCH,其他
@@ -0,0 +1,244 @@
# url 里填写自己的订阅,名称不能重复
proxy-providers:
provider1:
url: ""
type: http
interval: 86400
health-check: {enable: true,url: "https://www.gstatic.com/generate_204", interval: 300}
override:
additional-prefix: "[provider1]"
provider2:
url: ""
type: http
interval: 86400
health-check: {enable: true,url: "https://www.gstatic.com/generate_204",interval: 300}
override:
additional-prefix: "[provider2]"
proxies:
- name: "直连"
type: direct
udp: true
mixed-port: 7890
ipv6: true
allow-lan: true
unified-delay: false
tcp-concurrent: true
external-controller: 0.0.0.0:9090
external-ui: ui
external-ui-url: "https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip"
geodata-mode: true
geox-url:
geoip: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat"
geosite: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat"
mmdb: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb"
asn: "https://gh-proxy.com/https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb"
find-process-mode: strict
global-client-fingerprint: chrome
profile:
store-selected: true
store-fake-ip: true
sniffer:
enable: true
sniff:
HTTP:
ports: [80, 8080-8880]
override-destination: true
TLS:
ports: [443, 8443]
QUIC:
ports: [443, 8443]
skip-domain:
- "Mijia Cloud"
- "+.push.apple.com"
tun:
enable: true
stack: mixed
dns-hijack:
- "any:53"
- "tcp://any:53"
auto-route: true
auto-redirect: true
auto-detect-interface: true
dns:
enable: true
ipv6: true
enhanced-mode: fake-ip
fake-ip-filter:
- "*"
- "+.lan"
- "+.local"
- "+.market.xiaomi.com"
default-nameserver:
- tls://223.5.5.5
- tls://223.6.6.6
nameserver:
- https://doh.pub/dns-query
- https://dns.alidns.com/dns-query
proxy-groups:
- name: 默认
type: select
proxies: [自动选择,直连,香港,台湾,日本,新加坡,美国,其它地区,全部节点]
- name: Google
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Telegram
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Twitter
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 哔哩哔哩
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 巴哈姆特
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: YouTube
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: NETFLIX
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Spotify
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: Github
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
- name: 国内
type: select
proxies: [直连,默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择]
- name: 其他
type: select
proxies: [默认,香港,台湾,日本,新加坡,美国,其它地区,全部节点,自动选择,直连]
#分隔,下面是地区分组
- name: 香港
type: select
include-all: true
exclude-type: direct
filter: "(?i)港|hk|hongkong|hong kong"
- name: 台湾
type: select
include-all: true
exclude-type: direct
filter: "(?i)台|tw|taiwan"
- name: 日本
type: select
include-all: true
exclude-type: direct
filter: "(?i)日|jp|japan"
- name: 美国
type: select
include-all: true
exclude-type: direct
filter: "(?i)美|us|unitedstates|united states"
- name: 新加坡
type: select
include-all: true
exclude-type: direct
filter: "(?i)(新|sg|singapore)"
- name: 其它地区
type: select
include-all: true
exclude-type: direct
filter: "(?i)^(?!.*(?:|||||港|hk|hongkong|台|tw|taiwan|日|jp|japan|新|sg|singapore|美|us|unitedstates)).*"
- name: 全部节点
type: select
include-all: true
exclude-type: direct
- name: 自动选择
type: url-test
include-all: true
exclude-type: direct
tolerance: 10
rules:
- 'DOMAIN-SUFFIX,synology.com,DIRECT'
- 'DOMAIN-SUFFIX,digitalocean.com,DIRECT'
- 'DOMAIN-SUFFIX,synocommunity.com,DIRECT'
- 'DOMAIN-SUFFIX,emby.xiaoya.pro,DIRECT'
- 'DOMAIN-SUFFIX,icyou.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,lanyuewan.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby.8.net.co,DIRECT'
- 'DOMAIN-SUFFIX,emby.raydoom.tk,DIRECT'
- 'DOMAIN-SUFFIX,emby.kaiserver.uk,DIRECT'
- 'DOMAIN-SUFFIX,embyxiaoya.laogl.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.poxi1221.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ermaokj.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.bdbd.fun,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wwwh.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.f1rst.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ymschh.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wx1.us.kg,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.r2s.site,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.neversay.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.800686.xyz,DIRECT'
- 'DOMAIN-SUFFIX,syncthing.net,DIRECT'
- 'DOMAIN-SUFFIX,3322.org,DIRECT'
- 'DOMAIN-SUFFIX,picp.net,DIRECT'
- 'DOMAIN-SUFFIX,wicp.net,DIRECT'
- 'DOMAIN-SUFFIX,xicp.cn,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.top,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.cn,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.top,DIRECT'
- 'DOMAIN-SUFFIX,againgo.top,DIRECT'
- 'DOMAIN-SUFFIX,himan.vip,DIRECT'
- 'DOMAIN-SUFFIX,himan.cloud,DIRECT'
- 'DOMAIN-SUFFIX,himan.top,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.me,DIRECT'
- 'DOMAIN-SUFFIX,xuanyuan.me,DIRECT'
- 'DOMAIN-SUFFIX,1ms.run,DIRECT'
- GEOIP,lan,直连,no-resolve
- GEOSITE,github,Github
- GEOSITE,twitter,Twitter
- GEOSITE,youtube,YouTube
- GEOSITE,google,Google
- GEOSITE,telegram,Telegram
- GEOSITE,netflix,NETFLIX
- GEOSITE,bilibili,哔哩哔哩
- GEOSITE,bahamut,巴哈姆特
- GEOSITE,spotify,Spotify
- GEOSITE,CN,国内
- GEOSITE,geolocation-!cn,其他
- GEOIP,google,Google
- GEOIP,netflix,NETFLIX
- GEOIP,telegram,Telegram
- GEOIP,twitter,Twitter
- GEOIP,CN,国内
- MATCH,其他
+131
View File
@@ -0,0 +1,131 @@
mixed-port: 7890
allow-lan: true
bind-address: "*"
mode: rule
log-level: info
external-controller: 0.0.0.0:9090
secret: "123456" # 可选,用于设置访问密码
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
dns:
enable: true
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- 114.114.114.114
- 223.5.5.5
fallback:
- tls://8.8.8.8:853
- tls://1.1.1.1:853
proxy-providers:
狗狗加速: # 随便起名,建议有意义
type: http
url: "https://CSWyZi.doggygo.top:8443/api/v1/client/5a471ca14910318c9491470a62a712ea" # 替换成你的第1个链接
path: ./gg.yaml
interval: 86400 # 每天更新一次
health-check:
enable: true
url: "https://www.gstatic.com/generate_204"
interval: 300
IPLC:
type: http
url: "https://sub.20250715iplcsub.link/qC8zV8qS1kB1lX2u/4OLCCKkHWHgeCM6m?clash=1" # 第2个
path: ./iplc.yaml
interval: 86400
health-check:
enable: true
url: "https://www.gstatic.com/generate_204"
interval: 300
proxy-groups:
# 主出口组:你可以在这里手动选机场,或用自动策略
- name: "主出口"
type: select # 手动选择模式(最常用)
proxies:
- "gg-自动"
- "iplc-自动"
- DIRECT
- REJECT
# 每个机场单独做 url-test(延迟最低自动选节点)
- name: "gg-自动"
type: url-test
use:
- 狗狗加速 # 只用这个 provider 的节点
url: "http://www.gstatic.com/generate_204"
interval: 300
tolerance: 50 # 延迟波动容忍(可选)
- name: "iplc-自动"
type: url-test
use:
- IPLC
url: "http://www.gstatic.com/generate_204"
interval: 300
# 可选:全部节点合并 + 自动选延迟最低的(适合追求极致速度)
- name: "全部-最低延迟"
type: url-test
use:
- 狗狗加速
- IPLC
url: "http://www.gstatic.com/generate_204"
interval: 300
tolerance: 100
rules:
- 'DOMAIN-SUFFIX,synology.com,DIRECT'
- 'DOMAIN-SUFFIX,digitalocean.com,DIRECT'
- 'DOMAIN-SUFFIX,synocommunity.com,DIRECT'
- 'DOMAIN-SUFFIX,emby.xiaoya.pro,DIRECT'
- 'DOMAIN-SUFFIX,icyou.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,lanyuewan.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby.8.net.co,DIRECT'
- 'DOMAIN-SUFFIX,emby.raydoom.tk,DIRECT'
- 'DOMAIN-SUFFIX,emby.kaiserver.uk,DIRECT'
- 'DOMAIN-SUFFIX,embyxiaoya.laogl.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.poxi1221.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ermaokj.cn,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.bdbd.fun,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wwwh.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.f1rst.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.ymschh.top,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.wx1.us.kg,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.r2s.site,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.neversay.eu.org,DIRECT'
- 'DOMAIN-SUFFIX,emby-data.800686.xyz,DIRECT'
- 'DOMAIN-SUFFIX,syncthing.net,DIRECT'
- 'DOMAIN-SUFFIX,3322.org,DIRECT'
- 'DOMAIN-SUFFIX,picp.net,DIRECT'
- 'DOMAIN-SUFFIX,wicp.net,DIRECT'
- 'DOMAIN-SUFFIX,xicp.cn,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.top,DIRECT'
- 'DOMAIN-SUFFIX,cpolar.cn,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.top,DIRECT'
- 'DOMAIN-SUFFIX,againgo.top,DIRECT'
- 'DOMAIN-SUFFIX,himan.vip,DIRECT'
- 'DOMAIN-SUFFIX,himan.cloud,DIRECT'
- 'DOMAIN-SUFFIX,himan.top,DIRECT'
- 'DOMAIN-SUFFIX,joyagain.me,DIRECT'
- 'DOMAIN-SUFFIX,xuanyuan.me,DIRECT'
- 'DOMAIN-SUFFIX,1ms.run,DIRECT'
- GEOIP,LAN,DIRECT
- GEOIP,CN,DIRECT
- MATCH,主出口 # 改成你的主出口组名
Binary file not shown.
@@ -0,0 +1,35 @@
version: '3.8'
services:
mihomo:
container_name: mihomo-core
# image: metacubex/mihomo:latest # :Alpha :v1.19.x
#
image: docker.1ms.run/metacubex/mihomo:latest
restart: always
network_mode: host
pid: host
ipc: host
cap_add:
- ALL # NET_ADMIN - ALL
security_opt:
- apparmor=unconfined #
volumes:
- ./data:/root/.config/mihomo #
- /dev/net/tun:/dev/net/tun # TUN
- /etc/localtime:/etc/localtime:ro #
depends_on:
- metacubexd
metacubexd: # (XD)
container_name: mihomo-web
# image: ghcr.io/metacubex/metacubexd:latest
#
image: ghcr.1ms.run/metacubex/metacubexd:latest
restart: always
network_mode: bridge # host
ports:
- "9097:80" # 9091
volumes:
- ./config:/config/caddy #
- /etc/localtime:/etc/localtime:ro
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
[JoyCloud]
type = webdav
url = http://192.168.1.181:6244/dav
vendor = other
user = alAdmin
pass = a-srLYRoZi6Nvr_JmSzmVFDf7iP7_q4W
@@ -0,0 +1,90 @@
[
{
"name": "织梦",
"domain": "zmpt.cc",
"url": "https://zmpt.cc/",
"rss": "https://zmpt.cc/torrentrss.php?passkey=a5b24e65a4359e2120dfbcde82e70fa6&rows=50&ismalldescr=1&linktype=dl",
"downloader": null,
"cookie": "c_secure_pass=eyJ1c2VyX2lkIjoiMTg0NTkiLCJleHBpcmVzIjoxNzkxMzQ3MzIxfS5mOTUwYTc5OGI1MTY3MGU1M2IwMTcwZTM3MGZkZDMyYjUxM2MzZGZhZjEwMWIzMTI4ZGQ2ZjllNjBiNzg4ZWUy",
"apikey": null,
"token": null,
"ua": null,
"proxy": 0,
"filter": null,
"render": null,
"public": 0,
"note": null,
"timeout": 15,
"limit_interval": 0,
"limit_count": 0,
"limit_seconds": 0,
"is_active": true,
"pri": 1
},
{
"name": "铂金家",
"domain": "pthome.net",
"url": "https://pthome.net/",
"rss": "https://pthome.net/torrentrss.php?rows=50&exp=180&ismalldescr=1&linktype=dl&passkey=b867c4dbx1739045435x137159x180x15a0e9fe03fb7b04ef8b5ea20d675bcd",
"downloader": null,
"cookie": "c_secure_uid=MTM3MTU5;c_secure_pass=96b77cf06e40ec17f880a3d3343255dd;c_secure_ssl=eWVhaA%3D%3D;c_secure_tracker_ssl=eWVhaA%3D%3D;c_secure_login=bm9wZQ%3D%3D;Hm_lvt_41bc5487f653d238d282d7de5990fd73=1745069331",
"apikey": null,
"token": null,
"ua": null,
"proxy": 0,
"filter": null,
"render": null,
"public": 0,
"note": null,
"timeout": 15,
"limit_interval": 0,
"limit_count": 0,
"limit_seconds": 0,
"is_active": true,
"pri": 2
},
{
"name": "52pt",
"domain": "52pt.site",
"url": "https://52pt.site/",
"rss": "https://52pt.site/torrentrss.php?rows=50&ismalldescr=1&linktype=dl&passkey=0bde86842ddf1615426b5b6912f85913",
"downloader": null,
"cookie": "c_secure_uid=MjExNjU%3D;c_secure_pass=322dc728c8926892784dc9a81fcc88d6;c_secure_ssl=eWVhaA%3D%3D;c_secure_tracker_ssl=eWVhaA%3D%3D;c_secure_login=bm9wZQ%3D%3D",
"apikey": null,
"token": null,
"ua": null,
"proxy": 0,
"filter": null,
"render": null,
"public": 0,
"note": null,
"timeout": 15,
"limit_interval": 0,
"limit_count": 0,
"limit_seconds": 0,
"is_active": true,
"pri": 3
},
{
"name": "1PTBA",
"domain": "1ptba.com",
"url": "http://1ptba.com/",
"rss": "https://1ptba.com/torrentrss.php?passkey=2f0d543c0883d6923fb303446d061cce&rows=10&cat401=1&cat402=1&cat403=1&cat404=1&cat408=1&cat410=1&cat412=1&paid=0&linktype=dl",
"downloader": "",
"cookie": "_qimei_uuid42=19a070c1e17100762d7eed9b34e39c9a39df8e760b;_qimei_fingerprint=3be02bb021893604b5a7ebe075a55ff0;_qimei_i_3=27d86b80c60b02d39391fe31088776e9f3eaa0f0125b05d1b6db205e26c67539636a35973c89e2d4bf8c;_qimei_h38=;_qimei_i_1=6dfa45f8945a;c_secure_pass=eyJ1c2VyX2lkIjoiMTA5NjY1IiwiZXhwaXJlcyI6MTc5MTM0NzQ5NX0uYzkwNWQ4YzNhNjZhNjlmNWNhYjI2MmYyYzExMTYyY2JlZmNlMGRjNDhmMjk2YWM3YTEyZDc2MTA1ZWI2NGQ3OA%3D%3D",
"apikey": null,
"token": null,
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
"proxy": 0,
"filter": null,
"render": 0,
"public": 0,
"note": null,
"timeout": 0,
"limit_interval": 0,
"limit_count": 0,
"limit_seconds": 0,
"is_active": true,
"pri": 4
}
]
+20
View File
@@ -0,0 +1,20 @@
services:
ai-assistant:
image: ghcr.io/qq85423296/t3fap-ai-assistant:latest
container_name: t3fap-ai-assistant
restart: always
environment:
T3MT_HOST: http://192.168.0.111:8521
T3MT_API_KEY: "这里填t3fap 个人密钥 获取的 key"
T3MT_AUTOMATION_MODE: full-access
T3MT_CONFIRM_REDLINE_ACTIONS: "true"
T3FAP_ASSISTANT_MODEL_NAME: gpt-5.4
T3FAP_ASSISTANT_MODEL: openai/gpt-5.4
T3FAP_ASSISTANT_API_KEY: "这里填新模型 key"
T3FAP_ASSISTANT_API_BASE: https://api.openai.com/v1
T3FAP_ASSISTANT_PICO_TOKEN: ""
ports:
- "18800:18800"
- "18790:18790"
volumes:
- ./assistant-data:/data/picoclaw
BIN
View File
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
frpc
wordpress-1
jeessy-ddns-go-1
+16
View File
@@ -0,0 +1,16 @@
services:
pansou:
image: ghcr.io/fish2018/pansou-web:latest
container_name: pansou
restart: unless-stopped
ports:
- "8383:80" #左边是宿主机端口
environment:
- TZ=Asia/Shanghai
- CACHE_PATH=/app/data/cache
- LOG_PATH=/app/data/logs
volumes:
- ./config:/app/config # 挂载配置文件目录
- ./data:/app/data