Compare commits

...

17 Commits

Author SHA1 Message Date
jxxghp
2102a03740 Merge pull request #885 from wumode/clashruleprovider 2025-08-24 18:46:30 +08:00
wumode
0a9cadf7ab update(ClashRuleProvider): 通过emoji识别国家 2025-08-24 18:06:43 +08:00
jxxghp
279efe8000 Merge pull request #883 from wumode/lexiannot 2025-08-23 17:18:18 +08:00
wumode
fd92e58f81 update(ImdbSource) 修复错误 2025-08-23 16:58:00 +08:00
wumode
fe93e46e02 update(ImdbSource) 修改UA 2025-08-23 00:01:13 +08:00
wumode
cbf541992f update(LexiAnnot): 添加任务页面 2025-08-22 17:03:07 +08:00
jxxghp
8e1d336250 add 统一缓存使用说明 2025-08-21 16:06:23 +08:00
jxxghp
12e0e2b9f5 Merge pull request #881 from wumode/imdbsource 2025-08-20 00:34:31 +08:00
wumode
ac914f70f3 update: ImdbSource&ToBypassTrackers 2025-08-20 00:10:09 +08:00
jxxghp
a07b8a4f4a Merge pull request #878 from wumode/lexiannot 2025-08-17 20:13:53 +08:00
wumode
6960b3f7aa update(LexiAnnot): 支持考试词汇标注 2025-08-17 19:50:30 +08:00
jxxghp
fe83ff1be8 Merge pull request #876 from liuhangbin/multiclass 2025-08-14 19:40:50 +08:00
Hangbin Liu
6357dc8e4a plugins.v2: 添加多级分类插件
目前MP默认只支持二级分类,但是部分用户有多级目录的需求,比如增加按照年代
或者评分度分类。因此增加一个支持多级分类的插件, 目前仅支持电影多级分类。

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
2025-08-14 19:16:45 +08:00
jxxghp
f1d94d0aa3 Merge pull request #875 from yelantf/main 2025-08-12 12:08:56 +08:00
夜阑听风
53dd3bc796 Update dingdingmsg in package.json 2025-08-12 10:59:53 +08:00
夜阑听风
a9d528fc05 Update dingdingmsg version 2025-08-12 10:58:25 +08:00
夜阑听风
0388c437b1 update dingdingmsg to support breakline 2025-08-12 10:56:24 +08:00
21 changed files with 5077 additions and 3592 deletions

185
README.md
View File

@@ -23,6 +23,7 @@ MoviePilot官方插件市场https://github.com/jxxghp/MoviePilot-Plugins
- [12. 如何通过插件扩展支持的存储类型?](#12-如何通过插件扩展支持的存储类型)
- [13. 如何将插件功能集成到工作流?](#13-如何将插件功能集成到工作流)
- [14. 如何在插件中通过消息持续与用户交互?](#14-如何在插件中通过消息持续与用户交互)
- [15. 如何在插件中使用系统级统一缓存?](#15-如何在插件中使用系统级统一缓存)
- [版本发布](#版本发布)
- [1. 如何发布插件版本?](#1-如何发布插件版本)
- [2. 如何开发V2版本的插件以及实现插件多版本兼容](#2-如何开发v2版本的插件以及实现插件多版本兼容)
@@ -1167,6 +1168,190 @@ def get_actions(self) -> List[Dict[str, Any]]:
- 建议在交互中保存用户状态数据,以支持复杂的多步骤操作
- 可以结合插件数据存储功能保存用户的交互历史和偏好设置
### 15. 如何在插件中使用系统级统一缓存?
**(仅支持 `v2.7.4+` 版本)**
- MoviePilot提供了统一的缓存系统支持内存缓存、文件系统缓存和Redis缓存自动管理当有Redis时优先使用Redis否则使用内存或文件系统。插件可以通过系统提供的缓存接口实现高效的缓存管理无需关心系统设置。
- 1. 使用缓存装饰器:
```python
from app.core.cache import cached
class MyPlugin(_PluginBase):
@cached(region="my_plugin", ttl=3600)
def get_data(self, key: str):
"""
使用缓存装饰器缓存结果1小时
"""
# 复杂的计算或网络请求
return expensive_operation(key)
@cached(region="my_plugin_async", ttl=1800, skip_none=True)
async def get_async_data(self, key: str):
"""
异步函数缓存跳过None值
"""
return await async_expensive_operation(key)
```
- 2. 使用TTLCache类
```python
from app.core.cache import TTLCache
class MyPlugin(_PluginBase):
def __init__(self):
super().__init__()
# 创建缓存实例最大128项TTL 30分钟
self.cache = TTLCache(region="my_plugin", maxsize=128, ttl=1800)
def process_data(self, key: str):
# 检查缓存
if key in self.cache:
return self.cache[key]
# 计算并缓存结果
result = expensive_operation(key)
self.cache[key] = result
return result
def clear_cache(self):
"""
清理插件缓存
"""
self.cache.clear()
```
- 3. 使用文件缓存后端(适用于大文件缓存):
```python
from app.core.cache import FileCache, AsyncFileCache
from pathlib import Path
class MyPlugin(_PluginBase):
def __init__(self):
super().__init__()
# 获取文件缓存后端支持Redis和文件系统
self.file_cache = FileCache(
base=Path("/tmp/my_plugin_cache"),
ttl=86400 # 24小时
)
def cache_large_file(self, key: str, data: bytes):
"""
缓存大文件数据
"""
self.file_cache.set(key, data, region="large_files")
def get_cached_file(self, key: str) -> Optional[bytes]:
"""
获取缓存的文件数据
"""
return self.file_cache.get(key, region="large_files")
async def async_cache_operations(self):
"""
异步文件缓存操作
"""
async_cache = AsyncFileCache(
base=Path("/tmp/my_plugin_async_cache"),
ttl=3600
)
# 异步设置缓存
await async_cache.set("async_key", b"async_data", region="async_files")
# 异步获取缓存
data = await async_cache.get("async_key", region="async_files")
await async_cache.close()
```
- 4. 直接使用缓存后端(高级用法):
```python
from app.core.cache import Cache
class MyPlugin(_PluginBase):
def __init__(self):
super().__init__()
# 直接获取缓存后端实例系统自动选择Redis或内存缓存
self.cache_backend = Cache(maxsize=256, ttl=3600)
def custom_cache_operation(self, key: str, value: Any):
"""
自定义缓存操作
"""
# 设置缓存
self.cache_backend.set(key, value, region="custom_region")
# 检查缓存是否存在
if self.cache_backend.exists(key, region="custom_region"):
# 获取缓存
cached_value = self.cache_backend.get(key, region="custom_region")
return cached_value
return None
def iterate_cache_items(self):
"""
遍历缓存项
"""
for key, value in self.cache_backend.items(region="custom_region"):
print(f"缓存键: {key}, 值: {value}")
def cleanup(self):
"""
清理缓存
"""
self.cache_backend.clear(region="custom_region")
self.cache_backend.close()
```
- 5. 缓存装饰器参数说明:
```python
@cached(
region="my_plugin", # 缓存区域,用于隔离不同插件的缓存
maxsize=512, # 最大缓存条目数(仅内存缓存有效)
ttl=1800, # 缓存存活时间(秒)
skip_none=True, # 是否跳过None值缓存
skip_empty=False # 是否跳过空值缓存(空列表、空字典等)
)
def my_function(self, param):
pass
```
- 6. 缓存管理功能:
```python
class MyPlugin(_PluginBase):
@cached(region="my_plugin")
def cached_function(self, param):
return expensive_operation(param)
def clear_my_cache(self):
"""
清理指定区域的缓存
"""
self.cached_function.cache_clear()
def get_cache_info(self):
"""
获取缓存信息
"""
cache_region = self.cached_function.cache_region
return f"缓存区域: {cache_region}"
```
- 7. 缓存后端自动选择:
- 系统会根据配置自动选择缓存后端:
- `CACHE_BACKEND_TYPE=redis`使用Redis作为缓存后端
- `CACHE_BACKEND_TYPE=memory`使用内存缓存cachetools
- 插件代码无需修改,系统会自动处理缓存后端的切换
- 8. 最佳实践:
- 为每个插件使用独立的缓存区域region避免缓存键冲突
- 合理设置TTL避免缓存过期时间过长导致数据过期
- 对于频繁访问的数据使用较长的TTL对于实时性要求高的数据使用较短的TTL
- 使用`skip_none=True`避免缓存无意义的None值
- 大文件或二进制数据建议使用文件缓存后端
- 在插件卸载时清理相关缓存,避免内存泄漏
## 版本发布

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -943,11 +943,14 @@
"name": "钉钉机器人",
"description": "支持使用钉钉机器人发送消息通知。",
"labels": "消息通知,钉钉机器人",
"version": "1.12",
"version": "1.13",
"icon": "Dingding_A.png",
"author": "nnlegenda",
"level": 1,
"v2": true
"v2": true,
"history": {
"v1.13": "优化钉钉消息换行"
}
},
"DynamicWeChat": {
"name": "动态企微可信IP",

View File

@@ -351,6 +351,18 @@
"v2.0": "适配新的目录结构变化,短剧分类名称调整为配置目录路径,升级后需要重新调整设置后才能使用。"
}
},
"MultiClass": {
"name": "视频多级分类",
"description": "支持视频多级分类",
"labels": "文件整理",
"version": "0.1",
"icon": "Calibreweb_B.png",
"author": "liuhangbin",
"level": 1,
"history": {
"v0.1": "视频多级分类插件, 目前仅支持电影按评分,年代,系列分类。"
}
},
"MoviePilotUpdateNotify": {
"name": "MoviePilot更新推送",
"description": "MoviePilot推送release更新通知、自动重启。",
@@ -420,11 +432,12 @@
"name": "绕过Trackers",
"description": "提供tracker服务器IP地址列表帮助IPv6连接绕过OpenClash。",
"labels": "工具",
"version": "1.4.2",
"version": "1.4.3",
"icon": "Clash_A.png",
"author": "wumode",
"level": 2,
"history": {
"v1.4.3": "修复 bug",
"v1.4.2": "修复插件动作",
"v1.4.1": "修复通知类型错误",
"v1.4": "异步查询DNS",
@@ -438,11 +451,13 @@
"name": "IMDb源",
"description": "让探索推荐和媒体识别支持IMDb数据源。",
"labels": "探索",
"version": "1.5.6",
"version": "1.5.8",
"icon": "IMDb_IOS-OSX_App.png",
"author": "wumode",
"level": 1,
"history": {
"v1.5.8": "修改UA",
"v1.5.7": "改进异常处理",
"v1.5.6": "固定仪表盘组件海报比例; 修复 bug",
"v1.5.5": "修复初始化错误",
"v1.5.4": "改进媒体识别",
@@ -468,12 +483,13 @@
"name": "Clash Rule Provider",
"description": "随时为Clash添加一些额外的规则。",
"labels": "工具",
"version": "1.3.2",
"version": "1.3.3",
"icon": "Mihomo_Meta_A.png",
"author": "wumode",
"level": 1,
"release": true,
"history": {
"v1.3.3": "通过emoji识别国家; 按国家分组节点; mrs格式支持",
"v1.3.2": "注册插件动作",
"v1.3.1": "支持配置 Hosts",
"v1.2.8": "改进导入界面",
@@ -496,11 +512,13 @@
"name": "美剧生词标注",
"description": "根据CEFR等级为英语影视剧标注高级词汇。",
"labels": "英语",
"version": "1.0.1",
"version": "1.1.1",
"icon": "LexiAnnot.png",
"author": "wumode",
"level": 1,
"history": {
"v1.1.1": "添加任务页面; 改进 spaCy 模型加载逻辑",
"v1.1.0": "支持考试词汇标注; 优化分词处理; 修复错误",
"v1.0.1": "合并连字符词; 避免ARM平台依赖问题",
"v1.0": "新增LexiAnnot"
}

View File

@@ -39,7 +39,7 @@ class ClashRuleProvider(_PluginBase):
# 插件图标
plugin_icon = "Mihomo_Meta_A.png"
# 插件版本
plugin_version = "1.3.2"
plugin_version = "1.3.3"
# 插件作者
plugin_author = "wumode"
# 作者主页
@@ -71,8 +71,10 @@ class ClashRuleProvider(_PluginBase):
_auto_update_subscriptions = True
_ruleset_prefix: str = '📂<='
_group_by_region: bool = False
_group_by_country: bool = False
_refresh_delay: int = 5
_discard_rules: bool = False
_discard_proxy_groups: bool = False
_enable_acl4ssr: bool = False
_dashboard_components: List[str] = []
_clash_template_yaml: str = ''
@@ -122,15 +124,15 @@ class ClashRuleProvider(_PluginBase):
self._notify = config.get("notify"),
self._sub_links = config.get("sub_links") or []
self._clash_dashboard_url = config.get("clash_dashboard_url") or ''
if self._clash_dashboard_url and self._clash_dashboard_url[-1] == '/':
self._clash_dashboard_url = self._clash_dashboard_url[:-1]
if self._clash_dashboard_url:
self._clash_dashboard_url = self._clash_dashboard_url.rstrip("/")
if not (self._clash_dashboard_url.startswith('http://') or
self._clash_dashboard_url.startswith('https://')):
self._clash_dashboard_url = 'http://' + self._clash_dashboard_url
self._clash_dashboard_secret = config.get("clash_dashboard_secret")
self._movie_pilot_url = config.get("movie_pilot_url")
if self._movie_pilot_url and self._movie_pilot_url[-1] == '/':
self._movie_pilot_url = self._movie_pilot_url[:-1]
if self._movie_pilot_url:
self._movie_pilot_url = self._movie_pilot_url.rstrip("/")
self._cron = config.get("cron_string") or '30 12 * * *'
self._timeout = config.get("timeout")
self._retry_times = config.get("retry_times") or 3
@@ -139,8 +141,10 @@ class ClashRuleProvider(_PluginBase):
self._acl4ssr_prefix = config.get("acl4ssr_prefix", "🗂️=>")
self._auto_update_subscriptions = config.get("auto_update_subscriptions")
self._group_by_region = config.get("group_by_region")
self._group_by_country = config.get("group_by_country") or False
self._refresh_delay = config.get("refresh_delay") or 5
self._discard_rules = config.get("discard_rules") or False
self._discard_proxy_groups = config.get("discard_proxy_groups") or False
self._enable_acl4ssr = config.get("enable_acl4ssr") or False
self._dashboard_components = config.get("dashboard_components") or []
self._clash_template_yaml = config.get("clash_template") or ''
@@ -816,6 +820,8 @@ class ClashRuleProvider(_PluginBase):
for key, value in new_value.items():
if key == 'name' or value is None:
continue
if key == 'payload' and params.get('type') != 'inline':
continue
if value == '' or value is None:
continue
item[key] = value
@@ -1119,8 +1125,6 @@ class ClashRuleProvider(_PluginBase):
def delete_rule_by_priority(self, priority: int, rule_parser: ClashRuleParser
) -> Optional[Union[ClashRule, LogicRule, MatchRule]]:
if not isinstance(priority, int):
return None
res = rule_parser.remove_rule_at_priority(priority)
self.__save_data()
return res
@@ -1263,6 +1267,8 @@ class ClashRuleProvider(_PluginBase):
logger.info(f"已更新: {url}. 节点数量: {len(rs['proxies'])}")
if rs.get('rules') is None:
rs['rules'] = []
if self._discard_proxy_groups:
rs['proxy-groups'] = []
rs = self.__remove_nodes_by_keywords(rs)
except Exception as e:
logger.error(f"解析配置出错: {e}")
@@ -1290,7 +1296,7 @@ class ClashRuleProvider(_PluginBase):
).put(url)
def proxy_groups_by_region(self) -> List[Dict[str, Any]]:
return ClashRuleProvider.__group_by_region(self._countries, self.all_proxies())
return self.__group_by_region(self._countries, self.all_proxies())
@staticmethod
def __load_countries(file_path: str) -> List:
@@ -1301,40 +1307,71 @@ class ClashRuleProvider(_PluginBase):
return []
return countries
@staticmethod
def __group_by_region(countries: List, proxies) -> List[Dict[str, Any]]:
continents_nodes = {'Asia': [], 'Europe': [], 'SouthAmerica': [], 'NorthAmerica': [], 'Africa': [],
'Oceania': [], 'AsiaExceptChina': []}
def __group_by_region(self, countries: List, proxies) -> List[Dict[str, Any]]:
continent_groups = {}
country_groups = {}
continent_map = {
'欧洲': 'Europe',
'亚洲': 'Asia',
'大洋洲': 'Oceania',
'非洲': 'Africa',
'北美洲': 'NorthAmerica',
'南美洲': 'SouthAmerica'
}
proxy_groups = []
hk = next(filter(lambda c: c['abbr'] == 'HK', countries),
{"abbr": "HK", "chinese": "中国香港特别行政区", "emoji": "🇭🇰"})
tw = next(filter(lambda c: c['abbr'] == 'TW', countries),
{"abbr": "TW", "chinese": "中国台湾", "emoji": "🇹🇼"})
for proxy_node in proxies:
continent = ClashRuleProvider.__continent_name_from_node(countries, proxy_node['name'])
if not continent:
country = ClashRuleProvider.__country_from_node(countries, proxy_node['name'])
if not country:
continue
continents_nodes[continent].append(proxy_node['name'])
for continent_nodes in continents_nodes:
if len(continents_nodes[continent_nodes]):
proxy_group = {'name': continent_nodes, 'type': 'select', 'proxies': continents_nodes[continent_nodes]}
if country.get("abbr") == "CN":
if any(key in proxy_node["name"] for key in ("🇭🇰", "HK", "香港")):
country = hk
if any(key in proxy_node["name"] for key in ("🇹🇼", "TW", "台湾")):
country = tw
continent = continent_map[country.get('continent')]
if self._group_by_region:
continent_groups.setdefault(continent, []).append(proxy_node['name'])
if self._group_by_country:
country_groups.setdefault(f"{country.get('emoji')} {country.get('chinese')}", []).append(
proxy_node['name'])
for continent, nodes in continent_groups.items():
if len(nodes):
proxy_group = {'name': continent, 'type': 'select', 'proxies': nodes}
proxy_groups.append(proxy_group)
for continent_node in continents_nodes['Asia']:
if any(x in continent_node for x in ('中国', '香港', 'CN')):
excluded = ('中国', '香港', 'CN', 'HK', '🇨🇳', '🇭🇰')
for continent_node in continent_groups.get('Asia', []):
if any(x in continent_node for x in excluded):
continue
continents_nodes['AsiaExceptChina'].append(continent_node)
if continents_nodes['AsiaExceptChina']:
proxy_group = {'name': 'AsiaExceptChina', 'type': 'select', 'proxies': continents_nodes['AsiaExceptChina']}
continent_groups.setdefault('AsiaExceptChina', []).append(continent_node)
if continent_groups.get('AsiaExceptChina'):
proxy_group = {'name': 'AsiaExceptChina', 'type': 'select', 'proxies': continent_groups['AsiaExceptChina']}
proxy_groups.append(proxy_group)
for country, nodes in country_groups.items():
if len(nodes):
proxy_group = {'name': country, 'type': 'select', 'proxies': nodes}
proxy_groups.append(proxy_group)
country_group = list(country_groups.keys())
if country_group:
proxy_groups.append({'name': '🏴‍☠️国家分组', 'type': 'select', 'proxies': country_group})
return proxy_groups
@staticmethod
def __continent_name_from_node(countries: List[Dict[str, str]], node_name: str) -> Optional[str]:
continents_names = {'欧洲': 'Europe',
'亚洲': 'Asia',
'大洋洲': 'Oceania',
'非洲': 'Africa',
'北美洲': 'NorthAmerica',
'南美洲': 'SouthAmerica'}
def __country_from_node(countries: List[Dict[str, str]], node_name: str) -> Optional[Dict[str, str]]:
node_name_lower = node_name.lower()
for country in countries:
if country['chinese'] in node_name or country['english'].lower() in node_name.lower():
return continents_names[country['continent']]
if country['emoji'] and country['emoji'] in node_name:
return country
elif (
country['chinese'] in node_name
or country['english'].lower() in node_name_lower
):
return country
return None
def __add_notification_job(self, ruleset_names: List[str]):
@@ -1432,7 +1469,7 @@ class ClashRuleProvider(_PluginBase):
clash_config['proxy-groups'] = ClashRuleProvider.extend_with_name_checking(clash_config['proxy-groups'],
proxy_groups)
# 添加按大洲代理组
if self._group_by_region:
if self._group_by_region or self._group_by_country:
groups_by_region = self.proxy_groups_by_region()
if groups_by_region:
clash_config['proxy-groups'] = ClashRuleProvider.extend_with_name_checking(clash_config['proxy-groups'],

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +0,0 @@
.plugin-config[data-v-929102b8] {
margin: 0 auto;
}

View File

@@ -0,0 +1,4 @@
.plugin-config[data-v-c2db3dad] {
margin: 0 auto;
}

View File

@@ -1,13 +1,13 @@
.plugin-page[data-v-d6db167c] {
.plugin-page[data-v-6aba879d] {
margin: 0 auto;
}
/* 使卡片等宽并适应移动端 */
.d-flex.flex-wrap[data-v-d6db167c] {
.d-flex.flex-wrap[data-v-6aba879d] {
gap: 16px;
}
.url-display[data-v-d6db167c] {
.url-display[data-v-6aba879d] {
word-break: break-all;
padding: 8px;
background: rgba(0, 0, 0, 0.05);
@@ -16,19 +16,19 @@
/* 移动端堆叠布局 */
@media (max-width: 768px) {
.d-flex.flex-wrap[data-v-d6db167c] {
.d-flex.flex-wrap[data-v-6aba879d] {
flex-direction: column;
}
}
/* Add visual distinction between sections */
.ruleset-section[data-v-d6db167c] {
.ruleset-section[data-v-6aba879d] {
border: 1px solid #e0e0e0;
border-radius: 4px;
padding: 16px;
background-color: #f5f5f5;
}
.top-section[data-v-d6db167c] {
.top-section[data-v-6aba879d] {
border: 1px solid #e0e0e0;
border-radius: 4px;
padding: 16px;
@@ -36,15 +36,15 @@
}
/* Optional: Add different border colors to further distinguish */
.ruleset-section[data-v-d6db167c] {
.ruleset-section[data-v-6aba879d] {
border-left: 4px solid #2196F3; /* Blue accent */
}
.top-section[data-v-d6db167c] {
.top-section[data-v-6aba879d] {
border-left: 4px solid #4CAF50; /* Green accent */
}
.drag-handle[data-v-d6db167c] {
.drag-handle[data-v-6aba879d] {
cursor: move;
}
.gap-2[data-v-d6db167c] {
.gap-2[data-v-6aba879d] {
gap: 8px;
}

View File

@@ -4733,7 +4733,7 @@ const importRuleTypes = ['YAML'];
const importProxiesTypes = ['YAML', 'LINK'];
const ruleProviderTypes = ['http', 'file', 'inline'];
const ruleProviderBehaviorTypes = ['domain', 'ipcidr', 'classical'];
const ruleProviderFormatTypes = ['yaml', 'text'];
const ruleProviderFormatTypes = ['yaml', 'text', 'mrs'];
// 修改actions为计算属性合并内置动作和自定义出站
const actions = computed(() => [
'DIRECT', 'REJECT', 'REJECT-DROP', 'PASS', 'COMPATIBLE',
@@ -5601,39 +5601,75 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_tab, null, {
default: _withCtx(() => _cache[92] || (_cache[92] = [
_createTextVNode("规则集规则")
])),
default: _withCtx(() => [
_createVNode(_component_v_icon, { start: "" }, {
default: _withCtx(() => _cache[92] || (_cache[92] = [
_createTextVNode("mdi-format-list-bulleted")
])),
_: 1
}),
_cache[93] || (_cache[93] = _createTextVNode(" 规则集规则 "))
]),
_: 1
}),
_createVNode(_component_v_tab, null, {
default: _withCtx(() => _cache[93] || (_cache[93] = [
_createTextVNode("置顶规则")
])),
default: _withCtx(() => [
_createVNode(_component_v_icon, { start: "" }, {
default: _withCtx(() => _cache[94] || (_cache[94] = [
_createTextVNode("mdi-pin")
])),
_: 1
}),
_cache[95] || (_cache[95] = _createTextVNode(" 置顶规则 "))
]),
_: 1
}),
_createVNode(_component_v_tab, null, {
default: _withCtx(() => _cache[94] || (_cache[94] = [
_createTextVNode("代理组")
])),
default: _withCtx(() => [
_createVNode(_component_v_icon, { start: "" }, {
default: _withCtx(() => _cache[96] || (_cache[96] = [
_createTextVNode("mdi-source-branch")
])),
_: 1
}),
_cache[97] || (_cache[97] = _createTextVNode(" 代理组 "))
]),
_: 1
}),
_createVNode(_component_v_tab, null, {
default: _withCtx(() => _cache[95] || (_cache[95] = [
_createTextVNode("出站代理")
])),
default: _withCtx(() => [
_createVNode(_component_v_icon, { start: "" }, {
default: _withCtx(() => _cache[98] || (_cache[98] = [
_createTextVNode("mdi-rocket-launch")
])),
_: 1
}),
_cache[99] || (_cache[99] = _createTextVNode(" 出站代理 "))
]),
_: 1
}),
_createVNode(_component_v_tab, null, {
default: _withCtx(() => _cache[96] || (_cache[96] = [
_createTextVNode("规则集合")
])),
default: _withCtx(() => [
_createVNode(_component_v_icon, { start: "" }, {
default: _withCtx(() => _cache[100] || (_cache[100] = [
_createTextVNode("mdi-folder-multiple")
])),
_: 1
}),
_cache[101] || (_cache[101] = _createTextVNode(" 规则集合 "))
]),
_: 1
}),
_createVNode(_component_v_tab, null, {
default: _withCtx(() => _cache[97] || (_cache[97] = [
_createTextVNode("Hosts")
])),
default: _withCtx(() => [
_createVNode(_component_v_icon, { start: "" }, {
default: _withCtx(() => _cache[102] || (_cache[102] = [
_createTextVNode("mdi-lan")
])),
_: 1
}),
_cache[103] || (_cache[103] = _createTextVNode(" Hosts "))
]),
_: 1
})
]),
@@ -5649,7 +5685,7 @@ return (_ctx, _cache) => {
_createElementVNode("div", _hoisted_3, [
_createElementVNode("div", _hoisted_4, [
_createElementVNode("div", _hoisted_5, [
_cache[100] || (_cache[100] = _createElementVNode("div", { class: "text-h6" }, "规则集规则", -1)),
_cache[106] || (_cache[106] = _createElementVNode("div", { class: "text-h6" }, "规则集规则", -1)),
_createElementVNode("div", _hoisted_6, [
_createVNode(_component_v_text_field, {
modelValue: searchRulesetRule.value,
@@ -5668,12 +5704,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[98] || (_cache[98] = [
default: _withCtx(() => _cache[104] || (_cache[104] = [
_createTextVNode("mdi-plus")
])),
_: 1
}),
_cache[99] || (_cache[99] = _createTextVNode(" 添加规则 "))
_cache[105] || (_cache[105] = _createTextVNode(" 添加规则 "))
]),
_: 1
})
@@ -5702,7 +5738,7 @@ return (_ctx, _cache) => {
}, [
_createElementVNode("td", null, [
_createVNode(_component_v_icon, { class: "drag-handle" }, {
default: _withCtx(() => _cache[101] || (_cache[101] = [
default: _withCtx(() => _cache[107] || (_cache[107] = [
_createTextVNode("mdi-drag")
])),
_: 1
@@ -5733,7 +5769,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[102] || (_cache[102] = [
default: _withCtx(() => _cache[108] || (_cache[108] = [
_createTextVNode("mdi-pencil")
])),
_: 1
@@ -5750,7 +5786,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[103] || (_cache[103] = [
default: _withCtx(() => _cache[109] || (_cache[109] = [
_createTextVNode("mdi-delete")
])),
_: 1
@@ -5790,7 +5826,7 @@ return (_ctx, _cache) => {
]),
_: 1
}, 8, ["headers", "items", "search", "page", "items-per-page", "items-per-page-options"]),
_cache[104] || (_cache[104] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, " *对规则集中规则的修改可以在Clash中立即生效。 ", -1))
_cache[110] || (_cache[110] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, " *对规则集中规则的修改可以在Clash中立即生效。 ", -1))
])
]),
_: 1
@@ -5800,7 +5836,7 @@ return (_ctx, _cache) => {
_createElementVNode("div", _hoisted_11, [
_createElementVNode("div", _hoisted_12, [
_createElementVNode("div", _hoisted_13, [
_cache[109] || (_cache[109] = _createElementVNode("div", { class: "text-h6" }, "置顶规则", -1)),
_cache[115] || (_cache[115] = _createElementVNode("div", { class: "text-h6" }, "置顶规则", -1)),
_createElementVNode("div", _hoisted_14, [
_createVNode(_component_v_text_field, {
modelValue: searchTopRule.value,
@@ -5820,12 +5856,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[105] || (_cache[105] = [
default: _withCtx(() => _cache[111] || (_cache[111] = [
_createTextVNode("mdi-import")
])),
_: 1
}),
_cache[106] || (_cache[106] = _createTextVNode(" 导入规则 "))
_cache[112] || (_cache[112] = _createTextVNode(" 导入规则 "))
]),
_: 1
}),
@@ -5835,12 +5871,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[107] || (_cache[107] = [
default: _withCtx(() => _cache[113] || (_cache[113] = [
_createTextVNode("mdi-plus")
])),
_: 1
}),
_cache[108] || (_cache[108] = _createTextVNode(" 添加规则 "))
_cache[114] || (_cache[114] = _createTextVNode(" 添加规则 "))
]),
_: 1
})
@@ -5869,7 +5905,7 @@ return (_ctx, _cache) => {
}, [
_createElementVNode("td", null, [
_createVNode(_component_v_icon, { class: "drag-handle" }, {
default: _withCtx(() => _cache[110] || (_cache[110] = [
default: _withCtx(() => _cache[116] || (_cache[116] = [
_createTextVNode("mdi-drag")
])),
_: 1
@@ -5900,7 +5936,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[111] || (_cache[111] = [
default: _withCtx(() => _cache[117] || (_cache[117] = [
_createTextVNode("mdi-pencil")
])),
_: 1
@@ -5918,7 +5954,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[112] || (_cache[112] = [
default: _withCtx(() => _cache[118] || (_cache[118] = [
_createTextVNode("mdi-delete")
])),
_: 1
@@ -5932,7 +5968,7 @@ return (_ctx, _cache) => {
activator: "parent",
location: "top"
}, {
default: _withCtx(() => _cache[113] || (_cache[113] = [
default: _withCtx(() => _cache[119] || (_cache[119] = [
_createTextVNode(" 根据规则集自动添加 ")
])),
_: 1
@@ -5970,8 +6006,8 @@ return (_ctx, _cache) => {
]),
_: 1
}, 8, ["headers", "search", "items", "page", "items-per-page"]),
_cache[114] || (_cache[114] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, " *置顶规则用于管理来自规则集的匹配规则,这些规则会动态更新。 ", -1)),
_cache[115] || (_cache[115] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, " *对置顶规则的修改只有Clash更新配置后才会生效。 ", -1))
_cache[120] || (_cache[120] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, " *置顶规则用于管理来自规则集的匹配规则,这些规则会动态更新。 ", -1)),
_cache[121] || (_cache[121] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, " *对置顶规则的修改只有Clash更新配置后才会生效。 ", -1))
])
]),
_: 1
@@ -5981,7 +6017,7 @@ return (_ctx, _cache) => {
_createElementVNode("div", _hoisted_19, [
_createElementVNode("div", _hoisted_20, [
_createElementVNode("div", _hoisted_21, [
_cache[118] || (_cache[118] = _createElementVNode("div", { class: "text-h6" }, "代理组", -1)),
_cache[124] || (_cache[124] = _createElementVNode("div", { class: "text-h6" }, "代理组", -1)),
_createElementVNode("div", _hoisted_22, [
_createVNode(_component_v_btn, {
color: "primary",
@@ -5989,12 +6025,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[116] || (_cache[116] = [
default: _withCtx(() => _cache[122] || (_cache[122] = [
_createTextVNode("mdi-plus")
])),
_: 1
}),
_cache[117] || (_cache[117] = _createTextVNode(" 添加代理组 "))
_cache[123] || (_cache[123] = _createTextVNode(" 添加代理组 "))
]),
_: 1
})
@@ -6026,7 +6062,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[119] || (_cache[119] = [
default: _withCtx(() => _cache[125] || (_cache[125] = [
_createTextVNode("mdi-code-json")
])),
_: 1
@@ -6044,7 +6080,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[120] || (_cache[120] = [
default: _withCtx(() => _cache[126] || (_cache[126] = [
_createTextVNode("mdi-pencil")
])),
_: 1
@@ -6062,7 +6098,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[121] || (_cache[121] = [
default: _withCtx(() => _cache[127] || (_cache[127] = [
_createTextVNode("mdi-delete")
])),
_: 1
@@ -6076,7 +6112,7 @@ return (_ctx, _cache) => {
activator: "parent",
location: "top"
}, {
default: _withCtx(() => _cache[122] || (_cache[122] = [
default: _withCtx(() => _cache[128] || (_cache[128] = [
_createTextVNode(" 非手动添加 ")
])),
_: 1
@@ -6114,7 +6150,7 @@ return (_ctx, _cache) => {
]),
_: 1
}, 8, ["headers", "items", "page", "items-per-page"]),
_cache[123] || (_cache[123] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, null, -1))
_cache[129] || (_cache[129] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, null, -1))
])
]),
_: 1
@@ -6124,7 +6160,7 @@ return (_ctx, _cache) => {
_createElementVNode("div", _hoisted_26, [
_createElementVNode("div", _hoisted_27, [
_createElementVNode("div", _hoisted_28, [
_cache[126] || (_cache[126] = _createElementVNode("div", { class: "text-h6" }, "出站代理", -1)),
_cache[132] || (_cache[132] = _createElementVNode("div", { class: "text-h6" }, "出站代理", -1)),
_createElementVNode("div", _hoisted_29, [
_createVNode(_component_v_btn, {
color: "primary",
@@ -6132,12 +6168,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[124] || (_cache[124] = [
default: _withCtx(() => _cache[130] || (_cache[130] = [
_createTextVNode("mdi-plus")
])),
_: 1
}),
_cache[125] || (_cache[125] = _createTextVNode(" 导入节点 "))
_cache[131] || (_cache[131] = _createTextVNode(" 导入节点 "))
]),
_: 1
})
@@ -6171,7 +6207,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[127] || (_cache[127] = [
default: _withCtx(() => _cache[133] || (_cache[133] = [
_createTextVNode("mdi-code-json")
])),
_: 1
@@ -6189,7 +6225,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[128] || (_cache[128] = [
default: _withCtx(() => _cache[134] || (_cache[134] = [
_createTextVNode("mdi-delete")
])),
_: 1
@@ -6203,7 +6239,7 @@ return (_ctx, _cache) => {
activator: "parent",
location: "top"
}, {
default: _withCtx(() => _cache[129] || (_cache[129] = [
default: _withCtx(() => _cache[135] || (_cache[135] = [
_createTextVNode(" 非手动添加 ")
])),
_: 1
@@ -6241,7 +6277,7 @@ return (_ctx, _cache) => {
]),
_: 1
}, 8, ["headers", "items", "page", "items-per-page"]),
_cache[130] || (_cache[130] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, null, -1))
_cache[136] || (_cache[136] = _createElementVNode("div", { class: "text-caption text-grey mt-2" }, null, -1))
])
]),
_: 1
@@ -6251,7 +6287,7 @@ return (_ctx, _cache) => {
_createElementVNode("div", _hoisted_33, [
_createElementVNode("div", _hoisted_34, [
_createElementVNode("div", _hoisted_35, [
_cache[133] || (_cache[133] = _createElementVNode("div", { class: "text-h6" }, "规则集合", -1)),
_cache[139] || (_cache[139] = _createElementVNode("div", { class: "text-h6" }, "规则集合", -1)),
_createElementVNode("div", _hoisted_36, [
_createVNode(_component_v_text_field, {
modelValue: searchRuleProviders.value,
@@ -6270,12 +6306,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[131] || (_cache[131] = [
default: _withCtx(() => _cache[137] || (_cache[137] = [
_createTextVNode("mdi-plus")
])),
_: 1
}),
_cache[132] || (_cache[132] = _createTextVNode(" 添加规则集合 "))
_cache[138] || (_cache[138] = _createTextVNode(" 添加规则集合 "))
]),
_: 1
})
@@ -6311,7 +6347,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[134] || (_cache[134] = [
default: _withCtx(() => _cache[140] || (_cache[140] = [
_createTextVNode("mdi-pencil")
])),
_: 1
@@ -6329,7 +6365,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[135] || (_cache[135] = [
default: _withCtx(() => _cache[141] || (_cache[141] = [
_createTextVNode("mdi-delete")
])),
_: 1
@@ -6343,7 +6379,7 @@ return (_ctx, _cache) => {
activator: "parent",
location: "top"
}, {
default: _withCtx(() => _cache[136] || (_cache[136] = [
default: _withCtx(() => _cache[142] || (_cache[142] = [
_createTextVNode(" 非手动添加 ")
])),
_: 1
@@ -6390,7 +6426,7 @@ return (_ctx, _cache) => {
_createElementVNode("div", _hoisted_40, [
_createElementVNode("div", _hoisted_41, [
_createElementVNode("div", _hoisted_42, [
_cache[139] || (_cache[139] = _createElementVNode("div", { class: "text-h6" }, "Hosts", -1)),
_cache[145] || (_cache[145] = _createElementVNode("div", { class: "text-h6" }, "Hosts", -1)),
_createElementVNode("div", _hoisted_43, [
_createVNode(_component_v_text_field, {
modelValue: searchHosts.value,
@@ -6409,12 +6445,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[137] || (_cache[137] = [
default: _withCtx(() => _cache[143] || (_cache[143] = [
_createTextVNode("mdi-plus")
])),
_: 1
}),
_cache[138] || (_cache[138] = _createTextVNode(" 添加Hosts "))
_cache[144] || (_cache[144] = _createTextVNode(" 添加Hosts "))
]),
_: 1
})
@@ -6470,7 +6506,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[140] || (_cache[140] = [
default: _withCtx(() => _cache[146] || (_cache[146] = [
_createTextVNode("mdi-pencil")
])),
_: 1
@@ -6487,7 +6523,7 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[141] || (_cache[141] = [
default: _withCtx(() => _cache[147] || (_cache[147] = [
_createTextVNode("mdi-delete")
])),
_: 1
@@ -6548,7 +6584,7 @@ return (_ctx, _cache) => {
_createVNode(_component_v_card, { class: "h-100" }, {
default: _withCtx(() => [
_createVNode(_component_v_card_title, { class: "text-h6 font-weight-medium" }, {
default: _withCtx(() => _cache[142] || (_cache[142] = [
default: _withCtx(() => _cache[148] || (_cache[148] = [
_createTextVNode("状态信息")
])),
_: 1
@@ -6557,7 +6593,7 @@ return (_ctx, _cache) => {
default: _withCtx(() => [
_createElementVNode("div", _hoisted_47, [
_createElementVNode("div", _hoisted_48, [
_cache[143] || (_cache[143] = _createElementVNode("span", null, "状态", -1)),
_cache[149] || (_cache[149] = _createElementVNode("span", null, "状态", -1)),
_createVNode(_component_v_chip, {
size: "small",
color: status.value === 'running' ? 'success' : 'warning'
@@ -6569,23 +6605,23 @@ return (_ctx, _cache) => {
}, 8, ["color"])
]),
_createElementVNode("div", _hoisted_49, [
_cache[144] || (_cache[144] = _createElementVNode("span", null, "订阅配置规则数", -1)),
_cache[150] || (_cache[150] = _createElementVNode("span", null, "订阅配置规则数", -1)),
_createElementVNode("span", null, _toDisplayString(subscriptionInfo.value.rule_size), 1)
]),
_createElementVNode("div", _hoisted_50, [
_cache[145] || (_cache[145] = _createElementVNode("span", null, "置顶规则数", -1)),
_cache[151] || (_cache[151] = _createElementVNode("span", null, "置顶规则数", -1)),
_createElementVNode("span", null, _toDisplayString(sortedRules.value.length), 1)
]),
_createElementVNode("div", _hoisted_51, [
_cache[146] || (_cache[146] = _createElementVNode("span", null, "规则集规则数", -1)),
_cache[152] || (_cache[152] = _createElementVNode("span", null, "规则集规则数", -1)),
_createElementVNode("span", null, _toDisplayString(sortedRulesetRules.value.length), 1)
]),
_createElementVNode("div", _hoisted_52, [
_cache[147] || (_cache[147] = _createElementVNode("span", null, "代理组数", -1)),
_cache[153] || (_cache[153] = _createElementVNode("span", null, "代理组数", -1)),
_createElementVNode("span", null, _toDisplayString(proxyGroups.value.length), 1)
]),
_createElementVNode("div", _hoisted_53, [
_cache[148] || (_cache[148] = _createElementVNode("span", null, "最后更新", -1)),
_cache[154] || (_cache[154] = _createElementVNode("span", null, "最后更新", -1)),
_createElementVNode("span", null, _toDisplayString(lastUpdated.value), 1)
])
])
@@ -6607,7 +6643,7 @@ return (_ctx, _cache) => {
default: _withCtx(() => [
_createVNode(_component_v_card_title, { class: "d-flex justify-space-between align-center" }, {
default: _withCtx(() => [
_cache[150] || (_cache[150] = _createElementVNode("span", { class: "text-h6 font-weight-medium" }, "订阅链接", -1)),
_cache[156] || (_cache[156] = _createElementVNode("span", { class: "text-h6 font-weight-medium" }, "订阅链接", -1)),
_createVNode(_component_v_tooltip, {
location: "top",
text: "复制链接"
@@ -6623,7 +6659,7 @@ return (_ctx, _cache) => {
}), {
default: _withCtx(() => [
_createVNode(_component_v_icon, null, {
default: _withCtx(() => _cache[149] || (_cache[149] = [
default: _withCtx(() => _cache[155] || (_cache[155] = [
_createTextVNode("mdi-content-copy")
])),
_: 1
@@ -6647,12 +6683,12 @@ return (_ctx, _cache) => {
color: "grey",
class: "mr-2"
}, {
default: _withCtx(() => _cache[151] || (_cache[151] = [
default: _withCtx(() => _cache[157] || (_cache[157] = [
_createTextVNode("mdi-link")
])),
_: 1
}),
_cache[152] || (_cache[152] = _createElementVNode("span", { class: "text-grey-darken-1" }, "原始链接:", -1))
_cache[158] || (_cache[158] = _createElementVNode("span", { class: "text-grey-darken-1" }, "原始链接:", -1))
]),
_createElementVNode("div", _hoisted_56, [
(Object.keys(subscriptionsInfo.value).length > 0)
@@ -6673,7 +6709,7 @@ return (_ctx, _cache) => {
]),
_createElementVNode("div", _hoisted_58, [
_createVNode(_component_v_icon, { color: "blue" }, {
default: _withCtx(() => _cache[153] || (_cache[153] = [
default: _withCtx(() => _cache[159] || (_cache[159] = [
_createTextVNode("mdi-arrow-down-bold")
])),
_: 1
@@ -6684,12 +6720,12 @@ return (_ctx, _cache) => {
color: "primary",
class: "mr-2"
}, {
default: _withCtx(() => _cache[154] || (_cache[154] = [
default: _withCtx(() => _cache[160] || (_cache[160] = [
_createTextVNode("mdi-link-variant")
])),
_: 1
}),
_cache[155] || (_cache[155] = _createElementVNode("span", { class: "text-grey-darken-1" }, "生成链接:", -1))
_cache[161] || (_cache[161] = _createElementVNode("span", { class: "text-grey-darken-1" }, "生成链接:", -1))
]),
_createElementVNode("div", _hoisted_60, [
_createElementVNode("a", {
@@ -6723,12 +6759,12 @@ return (_ctx, _cache) => {
_createVNode(_component_v_expansion_panel_title, null, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[156] || (_cache[156] = [
default: _withCtx(() => _cache[162] || (_cache[162] = [
_createTextVNode("mdi-cloud-download")
])),
_: 1
}),
_cache[157] || (_cache[157] = _createElementVNode("span", { class: "text-subtitle-1 font-weight-medium" }, "订阅管理", -1))
_cache[163] || (_cache[163] = _createElementVNode("span", { class: "text-subtitle-1 font-weight-medium" }, "订阅管理", -1))
]),
_: 1
}),
@@ -6741,7 +6777,7 @@ return (_ctx, _cache) => {
variant: "tonal",
class: "mb-4"
}, {
default: _withCtx(() => _cache[158] || (_cache[158] = [
default: _withCtx(() => _cache[164] || (_cache[164] = [
_createTextVNode(" 暂无订阅信息,请先添加订阅链接 ")
])),
_: 1
@@ -6827,11 +6863,11 @@ return (_ctx, _cache) => {
: _createCommentVNode("", true)
]),
_createElementVNode("div", _hoisted_64, [
_cache[159] || (_cache[159] = _createElementVNode("span", null, "已用流量:", -1)),
_cache[165] || (_cache[165] = _createElementVNode("span", null, "已用流量:", -1)),
_createElementVNode("strong", null, _toDisplayString(formatBytes(info.download + info.upload)), 1)
]),
_createElementVNode("div", _hoisted_65, [
_cache[160] || (_cache[160] = _createElementVNode("span", null, "剩余流量:", -1)),
_cache[166] || (_cache[166] = _createElementVNode("span", null, "剩余流量:", -1)),
_createElementVNode("strong", null, _toDisplayString(formatBytes(info.total - info.download)), 1)
]),
_createVNode(_component_v_progress_linear, {
@@ -6860,12 +6896,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[161] || (_cache[161] = [
default: _withCtx(() => _cache[167] || (_cache[167] = [
_createTextVNode("mdi-cloud-sync")
])),
_: 1
}),
_cache[162] || (_cache[162] = _createTextVNode(" 更新订阅 "))
_cache[168] || (_cache[168] = _createTextVNode(" 更新订阅 "))
]),
_: 2
}, 1032, ["onClick", "loading"])
@@ -6899,12 +6935,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[163] || (_cache[163] = [
default: _withCtx(() => _cache[169] || (_cache[169] = [
_createTextVNode("mdi-refresh")
])),
_: 1
}),
_cache[164] || (_cache[164] = _createTextVNode(" 刷新数据 "))
_cache[170] || (_cache[170] = _createTextVNode(" 刷新数据 "))
]),
_: 1
}, 8, ["loading"]),
@@ -6915,12 +6951,12 @@ return (_ctx, _cache) => {
}, {
default: _withCtx(() => [
_createVNode(_component_v_icon, { left: "" }, {
default: _withCtx(() => _cache[165] || (_cache[165] = [
default: _withCtx(() => _cache[171] || (_cache[171] = [
_createTextVNode("mdi-cog")
])),
_: 1
}),
_cache[166] || (_cache[166] = _createTextVNode(" 配置 "))
_cache[172] || (_cache[172] = _createTextVNode(" 配置 "))
]),
_: 1
})
@@ -7075,7 +7111,7 @@ return (_ctx, _cache) => {
color: "secondary",
onClick: closeRuleDialog
}, {
default: _withCtx(() => _cache[167] || (_cache[167] = [
default: _withCtx(() => _cache[173] || (_cache[173] = [
_createTextVNode("取消")
])),
_: 1
@@ -7084,7 +7120,7 @@ return (_ctx, _cache) => {
color: "primary",
type: "submit"
}, {
default: _withCtx(() => _cache[168] || (_cache[168] = [
default: _withCtx(() => _cache[174] || (_cache[174] = [
_createTextVNode("保存")
])),
_: 1
@@ -7300,7 +7336,7 @@ return (_ctx, _cache) => {
}, {
"prepend-inner": _withCtx(() => [
_createVNode(_component_v_icon, { color: "warning" }, {
default: _withCtx(() => _cache[169] || (_cache[169] = [
default: _withCtx(() => _cache[175] || (_cache[175] = [
_createTextVNode("mdi-timer")
])),
_: 1
@@ -7330,7 +7366,7 @@ return (_ctx, _cache) => {
}, {
"prepend-inner": _withCtx(() => [
_createVNode(_component_v_icon, { color: "warning" }, {
default: _withCtx(() => _cache[170] || (_cache[170] = [
default: _withCtx(() => _cache[176] || (_cache[176] = [
_createTextVNode("mdi-timer")
])),
_: 1
@@ -7461,7 +7497,7 @@ return (_ctx, _cache) => {
text: "",
variant: "tonal"
}, {
default: _withCtx(() => _cache[171] || (_cache[171] = [
default: _withCtx(() => _cache[177] || (_cache[177] = [
_createTextVNode(" 参考"),
_createElementVNode("a", {
href: "https://wiki.metacubex.one/config/proxy-groups/",
@@ -7477,7 +7513,7 @@ return (_ctx, _cache) => {
color: "secondary",
onClick: _cache[59] || (_cache[59] = $event => (proxyGroupDialog.value = false))
}, {
default: _withCtx(() => _cache[172] || (_cache[172] = [
default: _withCtx(() => _cache[178] || (_cache[178] = [
_createTextVNode("取消")
])),
_: 1
@@ -7486,7 +7522,7 @@ return (_ctx, _cache) => {
color: "primary",
type: "submit"
}, {
default: _withCtx(() => _cache[173] || (_cache[173] = [
default: _withCtx(() => _cache[179] || (_cache[179] = [
_createTextVNode("保存")
])),
_: 1
@@ -7512,7 +7548,7 @@ return (_ctx, _cache) => {
_createVNode(_component_v_card, null, {
default: _withCtx(() => [
_createVNode(_component_v_card_title, { class: "headline" }, {
default: _withCtx(() => _cache[174] || (_cache[174] = [
default: _withCtx(() => _cache[180] || (_cache[180] = [
_createTextVNode("YAML 配置")
])),
_: 1
@@ -7538,7 +7574,7 @@ return (_ctx, _cache) => {
color: "primary",
onClick: _cache[62] || (_cache[62] = $event => (copyToClipboard(displayedYaml.value)))
}, {
default: _withCtx(() => _cache[175] || (_cache[175] = [
default: _withCtx(() => _cache[181] || (_cache[181] = [
_createTextVNode("复制")
])),
_: 1
@@ -7547,7 +7583,7 @@ return (_ctx, _cache) => {
color: "primary",
onClick: _cache[63] || (_cache[63] = $event => (yamlDialog.value = false))
}, {
default: _withCtx(() => _cache[176] || (_cache[176] = [
default: _withCtx(() => _cache[182] || (_cache[182] = [
_createTextVNode("关闭")
])),
_: 1
@@ -7570,7 +7606,7 @@ return (_ctx, _cache) => {
_createVNode(_component_v_card, null, {
default: _withCtx(() => [
_createVNode(_component_v_card_title, null, {
default: _withCtx(() => _cache[177] || (_cache[177] = [
default: _withCtx(() => _cache[183] || (_cache[183] = [
_createTextVNode("导入规则")
])),
_: 1
@@ -7601,7 +7637,7 @@ return (_ctx, _cache) => {
class: "mb-4",
variant: "tonal"
}, {
default: _withCtx(() => _cache[178] || (_cache[178] = [
default: _withCtx(() => _cache[184] || (_cache[184] = [
_createTextVNode(" 请输入 Clash 规则中的 "),
_createElementVNode("strong", null, "rules", -1),
_createTextVNode(" 字段,例如:"),
@@ -7624,7 +7660,7 @@ return (_ctx, _cache) => {
color: "secondary",
onClick: _cache[67] || (_cache[67] = $event => (importRuleDialog.value = false, error.value=null))
}, {
default: _withCtx(() => _cache[179] || (_cache[179] = [
default: _withCtx(() => _cache[185] || (_cache[185] = [
_createTextVNode("取消")
])),
_: 1
@@ -7633,7 +7669,7 @@ return (_ctx, _cache) => {
color: "primary",
onClick: importRule
}, {
default: _withCtx(() => _cache[180] || (_cache[180] = [
default: _withCtx(() => _cache[186] || (_cache[186] = [
_createTextVNode("导入")
])),
_: 1
@@ -7656,7 +7692,7 @@ return (_ctx, _cache) => {
_createVNode(_component_v_card, null, {
default: _withCtx(() => [
_createVNode(_component_v_card_title, null, {
default: _withCtx(() => _cache[181] || (_cache[181] = [
default: _withCtx(() => _cache[187] || (_cache[187] = [
_createTextVNode("导入节点")
])),
_: 1
@@ -7702,7 +7738,7 @@ return (_ctx, _cache) => {
class: "mb-4",
variant: "tonal"
}, {
default: _withCtx(() => _cache[182] || (_cache[182] = [
default: _withCtx(() => _cache[188] || (_cache[188] = [
_createTextVNode(" 请输入 Clash 规则中的 "),
_createElementVNode("strong", null, "proxies", -1),
_createTextVNode(" 字段,例如:"),
@@ -7724,7 +7760,7 @@ return (_ctx, _cache) => {
class: "mb-4",
variant: "tonal"
}, {
default: _withCtx(() => _cache[183] || (_cache[183] = [
default: _withCtx(() => _cache[189] || (_cache[189] = [
_createTextVNode(" 请输入 V2RayN 格式的分享链接,例如:"),
_createElementVNode("br", null, null, -1),
_createElementVNode("code", null, "vmess://xxxx", -1),
@@ -7744,7 +7780,7 @@ return (_ctx, _cache) => {
color: "secondary",
onClick: _cache[72] || (_cache[72] = $event => (importExtraProxiesDialog.value=false, error.value=null))
}, {
default: _withCtx(() => _cache[184] || (_cache[184] = [
default: _withCtx(() => _cache[190] || (_cache[190] = [
_createTextVNode("取消")
])),
_: 1
@@ -7754,7 +7790,7 @@ return (_ctx, _cache) => {
onClick: importExtraProxiesFun,
loading: importProxiesLoading.value
}, {
default: _withCtx(() => _cache[185] || (_cache[185] = [
default: _withCtx(() => _cache[191] || (_cache[191] = [
_createTextVNode(" 导入 ")
])),
_: 1
@@ -7828,7 +7864,7 @@ return (_ctx, _cache) => {
required: "",
rules: [v => !!v || '当类型为文件时,路径不能为空'],
class: "mb-4",
hint: "文件路径,必须是唯一的"
hint: "文件路径,不填写时会使用 url 的 MD5 作为文件名"
}, null, 8, ["modelValue", "rules"]))
: _createCommentVNode("", true),
_createVNode(_component_v_text_field, {
@@ -7911,7 +7947,7 @@ return (_ctx, _cache) => {
color: "secondary",
onClick: _cache[83] || (_cache[83] = $event => (ruleProviderDialog.value = false, error.value=null))
}, {
default: _withCtx(() => _cache[186] || (_cache[186] = [
default: _withCtx(() => _cache[192] || (_cache[192] = [
_createTextVNode("取消")
])),
_: 1
@@ -7920,7 +7956,7 @@ return (_ctx, _cache) => {
color: "primary",
type: "submit"
}, {
default: _withCtx(() => _cache[187] || (_cache[187] = [
default: _withCtx(() => _cache[193] || (_cache[193] = [
_createTextVNode("保存")
])),
_: 1
@@ -8028,7 +8064,7 @@ return (_ctx, _cache) => {
variant: "outlined",
class: "mb-2"
}, {
default: _withCtx(() => _cache[188] || (_cache[188] = [
default: _withCtx(() => _cache[194] || (_cache[194] = [
_createTextVNode(" 请在「高级选项」配置 Cloudflare CDN 优选 IPs ")
])),
_: 1
@@ -8039,7 +8075,7 @@ return (_ctx, _cache) => {
text: "",
variant: "tonal"
}, {
default: _withCtx(() => _cache[189] || (_cache[189] = [
default: _withCtx(() => _cache[195] || (_cache[195] = [
_createTextVNode(" 支持"),
_createElementVNode("a", {
href: "https://wiki.metacubex.one/handbook/syntax/#_8",
@@ -8055,7 +8091,7 @@ return (_ctx, _cache) => {
color: "secondary",
onClick: _cache[88] || (_cache[88] = $event => (hostDialog.value = false, error.value=null))
}, {
default: _withCtx(() => _cache[190] || (_cache[190] = [
default: _withCtx(() => _cache[196] || (_cache[196] = [
_createTextVNode("取消")
])),
_: 1
@@ -8064,7 +8100,7 @@ return (_ctx, _cache) => {
color: "primary",
type: "submit"
}, {
default: _withCtx(() => _cache[191] || (_cache[191] = [
default: _withCtx(() => _cache[197] || (_cache[197] = [
_createTextVNode("保存")
])),
_: 1
@@ -8086,6 +8122,6 @@ return (_ctx, _cache) => {
}
};
const PageComponent = /*#__PURE__*/_export_sfc(_sfc_main, [['__scopeId',"data-v-d6db167c"]]);
const PageComponent = /*#__PURE__*/_export_sfc(_sfc_main, [['__scopeId',"data-v-6aba879d"]]);
export { PageComponent as default };

View File

@@ -2,11 +2,11 @@ const currentImports = {};
const exportSet = new Set(['Module', '__esModule', 'default', '_export_sfc']);
let moduleMap = {
"./Page":()=>{
dynamicLoadingCss(["__federation_expose_Page-BOym_1fV.css"], false, './Page');
return __federation_import('./__federation_expose_Page-D5l2MyNA.js').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},
dynamicLoadingCss(["__federation_expose_Page-D1PURE3U.css"], false, './Page');
return __federation_import('./__federation_expose_Page-DfeoSpny.js').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},
"./Config":()=>{
dynamicLoadingCss(["__federation_expose_Config-BrXQaadr.css"], false, './Config');
return __federation_import('./__federation_expose_Config-NH09p1Am.js').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},
dynamicLoadingCss(["__federation_expose_Config-rtAetK-O.css"], false, './Config');
return __federation_import('./__federation_expose_Config-DcObTkjA.js').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},
"./Dashboard":()=>{
dynamicLoadingCss(["__federation_expose_Dashboard-vS9Qm2ZB.css"], false, './Dashboard');
return __federation_import('./__federation_expose_Dashboard-BDSt5WaH.js').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},};

View File

@@ -29,7 +29,7 @@ class ImdbSource(_PluginBase):
# 插件图标
plugin_icon = "IMDb_IOS-OSX_App.png"
# 插件版本
plugin_version = "1.5.6"
plugin_version = "1.5.8"
# 插件作者
plugin_author = "wumode"
# 作者主页
@@ -60,7 +60,7 @@ class ImdbSource(_PluginBase):
def init_plugin(self, config: dict = None):
plugin_instance = self
plugin_instance: ImdbSource = self
def patched_recognize_media(chain_self, meta: MetaBase = None,
mtype: Optional[MediaType] = None,
@@ -822,6 +822,14 @@ class ImdbSource(_PluginBase):
ChainBase.async_recognize_media._patched_by == id(self) and
self._original_async_method):
ChainBase.async_recognize_media = self._original_async_method
if self._scheduler:
try:
self._scheduler.remove_all_jobs()
if self._scheduler.running:
self._scheduler.shutdown()
self._scheduler = None
except Exception as e:
logger.error(f"退出插件失败:{e}")
def get_module(self) -> Dict[str, Any]:
"""

File diff suppressed because one or more lines are too long

View File

@@ -7,6 +7,7 @@
![](https://images2.imgbox.com/d6/b6/kZu6EH2a_o.png)
![](https://images2.imgbox.com/c8/3a/rEJBWu5v_o.png)
![](https://images2.imgbox.com/97/b7/d6RXFtwD_o.png)
![](https://images2.imgbox.com/8a/d4/AtgOe265_o.jpg)
# Gemini
@@ -38,7 +39,7 @@ CEFR全称是Common European Framework of Reference for Languages。
# 计划
- 双语字幕支持
- 考试词汇标注
- ~~考试词汇标注~~
# FAQ

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,5 @@
pysubs2~=1.8.0
langdetect~=1.0.9
pymediainfo~=7.0.1
pymediainfo~=7.0.1
thinc==8.3.4
spacy==3.8.7

View File

@@ -0,0 +1,326 @@
from pathlib import Path
from typing import Any, List, Dict, Tuple
from app.core.context import MediaInfo
from app.core.event import eventmanager, Event
from app.log import logger
from app.plugins import _PluginBase
from app.schemas.types import ChainEventType, MediaType, NotificationType
class MultiClass(_PluginBase):
# 插件名称
plugin_name = "视频多级分类"
# 插件描述
plugin_desc = "支持电影按照评分,年代和系列分类"
# 插件图标
plugin_icon = "Calibreweb_B.png"
# 插件版本
plugin_version = "0.1"
# 插件作者
plugin_author = "liuhangbin"
# 作者主页
author_url = "https://github.com/liuhangbin"
# 插件配置项ID前缀
plugin_config_prefix = "multiclass_"
# 加载顺序
plugin_order = 1
# 可使用的用户级别
auth_level = 1
_enabled = False
_notify = False
_year_class = False
_vote_class = False
_collection_class = False
def init_plugin(self, config: dict = None):
if config:
self._enabled = config.get("enabled", False)
self._notify = config.get("notify", False)
self._year_class = config.get("year_class", False)
self._vote_class = config.get("vote_class", False)
self._collection_class = config.get("collection_class", False)
def get_state(self) -> bool:
return self._enabled
def get_api(self) -> List[Dict[str, Any]]:
pass
def get_form(self) -> Tuple[List[dict], Dict[str, Any]]:
"""
拼装插件配置页面需要返回两块数据1、页面配置2、数据结构
"""
return [
{
'component': 'VForm',
'content': [
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'enabled',
'label': '启用插件',
}
}
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'year_class',
'label': '按照年代分类',
}
}
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'vote_class',
'label': '按照评分分类',
}
}
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'collection_class',
'label': '按照系列分类',
}
}
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'notify',
'label': '发送消息',
}
}
]
}
]
},
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
},
'content': [
{
'component': 'VAlert',
'props': {
'type': 'info',
'variant': 'tonal',
'text': '插件目前仅支持电影(需要开启智能重命名)。如果按评分分类7-9 高分4-6 一般1-3 垃圾。 系列电影不参与评分, 不按年代分类。'
}
}
]
}
]
}
]
}
], {
"enabled": False,
"notify": False,
"year_class": False,
"vote_class": False,
"collection_class": False
}
def get_page(self) -> List[dict]:
pass
@eventmanager.register(ChainEventType.TransferRename)
def category_handler(self, event: Event):
"""
根据多级分类规则重新分类组装地址
"""
logger.debug(f"多级分类插件触发!")
# 基础验证
if not self.get_state():
logger.debug(f"多级分类插件未启用!")
return
if not event:
logger.warning(f"多级分类异常:事件对象为空")
return
if not hasattr(event, 'event_data'):
logger.warning(f"多级分类异常:事件数据为空")
return
try:
data = event.event_data
# 验证必要的数据字段
if not hasattr(data, 'render_str') or not data.render_str:
logger.warning(f"多级分类异常render_str为空")
return
else:
render_str = data.render_str
# 暂时只支持电影分类
if not hasattr(data, 'rename_dict') or not data.rename_dict:
logger.warning(f"多级分类异常rename_dict为空")
return
else:
rename_dict = data.rename_dict
video_type = rename_dict.get("type", "")
if video_type != "电影":
logger.debug(f"多级分类异常:不支持的媒体类型: {video_type}, 只支持电影分类")
return
# 安全获取数据字段
title = rename_dict.get("title", "")
en_title = rename_dict.get("en_title", "")
year = rename_dict.get("year")
vote_average = rename_dict.get("vote_average")
media_info = rename_dict.get("__mediainfo__")
# 初始化默认值
vote_count = 0
c_name = None
vote_path = "未知评分"
decade = 0
# 安全处理媒体信息
if media_info and hasattr(media_info, 'vote_count'):
try:
vote_count = int(media_info.vote_count) if media_info.vote_count else 0
except (ValueError, TypeError):
vote_count = 0
if hasattr(media_info, 'tmdb_info') and media_info.tmdb_info:
collection = media_info.tmdb_info.get("belongs_to_collection")
if collection and isinstance(collection, dict):
c_name = collection.get("name")
# 安全处理评分数据
try:
if vote_average is not None:
vote_average = float(vote_average)
else:
vote_average = 0
except (ValueError, TypeError):
vote_average = 0
# 评分分类逻辑
if vote_count < 10:
vote_average = 0
vote_path = "评分不足"
elif vote_average >= 7:
vote_path = "高分电影"
elif vote_average >= 4:
vote_path = "一般电影"
else:
vote_path = "垃圾电影"
# 安全处理年份数据
try:
if year and str(year).isdigit():
year_int = int(year)
if 1900 <= year_int <= 2100: # 合理的年份范围
decade = (year_int // 10) * 10
else:
decade = 0
logger.warning(f"年份超出合理范围: {year}")
else:
decade = 0
except (ValueError, TypeError):
decade = 0
logger.warning(f"年份转换失败: {year}")
# 构建分类路径
path_parts = []
if self._collection_class and c_name:
# 当collection为true时只添加collection name
# 清理collection名称移除特殊字符
clean_c_name = str(c_name).strip()
if clean_c_name:
path_parts.append("系列电影")
path_parts.append(clean_c_name)
else:
# 当collection不为true时根据其他配置添加路径
if self._vote_class and vote_path:
path_parts.append(vote_path)
if self._year_class and decade > 0:
path_parts.append(f"{decade}s")
# 构建最终的路径
if path_parts:
# 确保render_str不为空
safe_render_str = str(render_str).strip() if render_str else ""
event.event_data.updated_str = f"{'/'.join(path_parts)}/{safe_render_str}"
# 更新事件数据
event.event_data.updated = True
event.event_data.source = "MultiClass"
# 发送消息
if self._notify:
self.post_message(
mtype=NotificationType.Organize,
title="多级分类完成",
text=f"已重新分类: {event.event_data.updated_str}",
)
else:
event.event_data.updated = False
logger.warning(f"多级分类失败: 未找到分类路径,请检查配置是否已开启")
except Exception as e:
logger.error(f"多级分类异常: {str(e)}", exc_info=True)
# 确保即使出错也不会影响原始数据
if hasattr(event, 'event_data') and event.event_data:
event.event_data.updated = False
event.event_data.updated_str = getattr(data, 'render_str', '') if data else ''
def stop_service(self):
"""
停止服务
"""
pass

View File

@@ -29,7 +29,7 @@ class ToBypassTrackers(_PluginBase):
# 插件图标
plugin_icon = "Clash_A.png"
# 插件版本
plugin_version = "1.4.2"
plugin_version = "1.4.3"
# 插件作者
plugin_author = "wumode"
# 作者主页
@@ -68,7 +68,8 @@ class ToBypassTrackers(_PluginBase):
self.ipv6_txt = self.get_data("ipv6_txt") if self.get_data("ipv6_txt") else ""
self.ipv4_txt = self.get_data("ipv4_txt") if self.get_data("ipv4_txt") else ""
try:
with open(f"{settings.ROOT_PATH}/app/plugins/tobypasstrackers/sites/trackers", "r", encoding="utf-8") as f:
site_file = settings.ROOT_PATH/'app'/'plugins'/'tobypasstrackers'/'sites'/'trackers'
with open(site_file, "r", encoding="utf-8") as f:
base64_str = f.read()
self.trackers = json.loads(base64.b64decode(base64_str).decode("utf-8"))
except Exception as e:
@@ -101,7 +102,6 @@ class ToBypassTrackers(_PluginBase):
)
self._onlyonce = False
self.__update_config()
# self._scheduler.print_jobs()
self._scheduler.start()
def get_state(self) -> bool:
@@ -619,16 +619,14 @@ class ToBypassTrackers(_PluginBase):
# Load Chnroute6 Lists
res = RequestUtils().get_res(url=chnroute6_lists_url)
if res is not None and res.status_code == 200:
chnroute6_lists = res.text[:-1].split('\n')
for ipr in chnroute6_lists:
ipv6_list.append(ipr)
chnroute6_lists = res.text.strip().split('\n')
ipv6_list = [*chnroute6_lists]
if self._china_ip_route:
# Load Chnroute Lists
res = RequestUtils().get_res(url=chnroute_lists_url)
if res is not None and res.status_code == 200:
chnroute_lists = res.text[:-1].split('\n')
for ipr in chnroute_lists:
ip_list.append(ipr)
chnroute_lists = res.text.strip().split('\n')
ip_list = [*chnroute_lists]
do_sites = {site.domain: site.name for site in SiteOper().list_order_by_pri() if
site.id in self._bypassed_sites}
domain_name_map = {}

View File

@@ -1 +1 @@
eyJoZGRvbGJ5LmNvbSI6IFsidC5oZGRvbGJ5LmNvbSJdLCAidGp1cHQub3JnIjogWyJ0cmFja2VyLXB1YmxpYy50anVwdC5vcmciXSwgIm5pY2VwdC5uZXQiOiBbInd3dy5uaWNlcHQubmV0Il0sICJyb3VzaS56aXAiOiBbImhpdHB0LmNvbSJdLCAicHRob21lLm5ldCI6IFsicHRob21lLm5ldCJdLCAiaGR0aW1lLm9yZyI6IFsiaGR0aW1lLm9yZyJdLCAiZWFzdGdhbWUub3JnIjogWyJwdC5lYXN0Z2FtZS5vcmciXSwgInB0dGltZS5vcmciOiBbInd3dy5wdHRpbWUub3JnIl0sICJtLXRlYW0uY2MiOiBbInRyYWNrZXIubS10ZWFtLmNjIiwgInRyYWNrZXIubS10ZWFtLmlvIl0sICI1MnB0LnNpdGUiOiBbIjUycHQuc2l0ZSJdLCAicWluZ3dhcHQuY29tIjogWyJ0cmFja2VyLnFpbmd3YS5wcm8iLCAidHJhY2tlci5xaW5nd2FwdC5jb20iXSwgImhka3lsLmluIjogWyJ0cmFja2VyLmhka3lsLmluIl0sICJyYWluZ2ZoLnRvcCI6IFsicmFpbmdmaC50b3AiXSwgImhkZmFucy5vcmciOiBbImhkZmFucy5vcmciXSwgInB0bGdzLm9yZyI6IFsicHRsLmdzIiwgInJlbGF5MDEucHRsLmdzIl0sICJtb25pa2FkZXNpZ24udWsiOiBbInRyYWNrZXIubW9uaWthZGVzaWduLnVrIiwgImRhaWtpcmFpLm1vbmlrYWRlc2lnbi51ayIsICJhbmltZS1uby1pbmRleC5jb20iXSwgInB0c2Jhby5jbHViIjogWyJwdHNiYW8uY2x1YiJdLCAidG90aGVnbG9yeS5pbSI6IFsidHJhY2tlci50b3RoZWdsb3J5LmltIl0sICJ1Mi5kbWh5Lm9yZyI6IFsiZGF5ZHJlYW0uZG1oeS5iZXN0Il0sICJieXIucHQiOiBbInRyYWNrZXIuYnlyLnB0Il0sICJodWRidC5odXN0LmVkdS5jbiI6IFsiaHVkYnQuaHVzdC5lZHUuY24iXSwgImlsb2xpY29uLmNvbSI6IFsidHJhY2tlci5pbG9saWNvbi5jYyJdLCAiaGl0cHQuY29tIjogWyJoaXRwdC5jb20iXSwgImJ0c2Nob29sLmNsdWIiOiBbInB0LmJ0c2Nob29sLmNsdWIiXSwgImhkYXJlYS5jbHViIjogWyJ0cmFja2VyLmhkYXJlYS5jbHViIl0sICJzcHJpbmdzdW5kYXkubmV0IjogWyJvbjYuc3ByaW5nc3VuZGF5Lm5ldCIsICJvbi5zcHJpbmdzdW5kYXkubmV0Il0sICJ6bXB0LmNjIjogWyJ6bXB0LmNjIl0sICJjYXJwdC5uZXQiOiBbInRyYWNrZXIuY2FycHQubmV0Il0sICJpY2MyMDIyLmNvbSI6IFsidHJhY2tlci5pY2MyMDIyLnh5eiJdLCAia2VlcGZyZHMuY29tIjogWyJ0cmFja2VyLmtlZXBmcmRzLmNvbSJdLCAicHR6b25lLnh5eiI6IFsicHR6b25lLnh5eiJdLCAiY3NwdC50b3AiOiBbInRyYWNrZXIuY3NwdC50b3AiLCAidHJhY2tlci5jc3B0LmNjIiwgInRyYWNrZXIuY3NwdC5kYXRlIl0sICJjcmFicHQudmlwIjogWyJjcmFicHQudmlwIl0sICJva3B0Lm5ldCI6IFsid3d3Lm9rcHQubmV0Il0sICJnYW1lZ2FtZXB0LmNvbSI6IFsid3d3LmdhbWVnYW1lcHQuY29tIl0sICJhdWRpZW5jZXMubWUiOiBbInQuYXVkaWVuY2VzLm1lIiwgInRyYWNrZXIuY2luZWZpbGVzLmluZm8iXSwgInhpbmd5dW5nZS50b3AiOiBbInRyYWNrZXIueGluZ3l1bmdlLnRvcCIsICJ0cmFja2VyLnhpbmd5dW5nZS5zYnMiXSwgImV0OC5vcmciOiBbImV0OC5vcmciLCAidC5ldDgub3JnIl0sICJkaXNjZmFuLm5ldCI6IFsiZGlzY2Zhbi54eXoiXX0=
eyI1MnB0LnNpdGUiOiBbIjUycHQuc2l0ZSJdLCAiYXVkaWVuY2VzLm1lIjogWyJ0LmF1ZGllbmNlcy5tZSIsICJ0cmFja2VyLmNpbmVmaWxlcy5pbmZvIl0sICJidHNjaG9vbC5jbHViIjogWyJwdC5idHNjaG9vbC5jbHViIl0sICJieXIucHQiOiBbInRyYWNrZXIuYnlyLnB0Il0sICJjYXJwdC5uZXQiOiBbInRyYWNrZXIuY2FycHQubmV0Il0sICJjcmFicHQudmlwIjogWyJjcmFicHQudmlwIl0sICJjc3B0LnRvcCI6IFsidHJhY2tlci5jc3B0LnRvcCIsICJ0cmFja2VyLmNzcHQuY2MiLCAidHJhY2tlci5jc3B0LmRhdGUiXSwgImRpc2NmYW4ubmV0IjogWyJkaXNjZmFuLnh5eiJdLCAiZWFzdGdhbWUub3JnIjogWyJwdC5lYXN0Z2FtZS5vcmciXSwgImV0OC5vcmciOiBbImV0OC5vcmciLCAidC5ldDgub3JnIl0sICJnYW1lZ2FtZXB0LmNvbSI6IFsid3d3LmdhbWVnYW1lcHQuY29tIl0sICJoZGFyZWEuY2x1YiI6IFsidHJhY2tlci5oZGFyZWEuY2x1YiJdLCAiaGRkb2xieS5jb20iOiBbInQuaGRkb2xieS5jb20iXSwgImhkZmFucy5vcmciOiBbImhkZmFucy5vcmciXSwgImhka3lsLmluIjogWyJ0cmFja2VyLmhka3lsLmluIl0sICJoZHRpbWUub3JnIjogWyJoZHRpbWUub3JnIl0sICJoaXRwdC5jb20iOiBbImhpdHB0LmNvbSJdLCAiaHVkYnQuaHVzdC5lZHUuY24iOiBbImh1ZGJ0Lmh1c3QuZWR1LmNuIl0sICJpY2MyMDIyLmNvbSI6IFsidHJhY2tlci5pY2MyMDIyLnh5eiJdLCAiaWxvbGljb24uY29tIjogWyJ0cmFja2VyLmlsb2xpY29uLmNjIl0sICJrZWVwZnJkcy5jb20iOiBbInRyYWNrZXIua2VlcGZyZHMuY29tIl0sICJtLXRlYW0uY2MiOiBbInRyYWNrZXIubS10ZWFtLmNjIiwgInRyYWNrZXIubS10ZWFtLmlvIl0sICJtb25pa2FkZXNpZ24udWsiOiBbInRyYWNrZXIubW9uaWthZGVzaWduLnVrIiwgImRhaWtpcmFpLm1vbmlrYWRlc2lnbi51ayIsICJhbmltZS1uby1pbmRleC5jb20iXSwgIm5pY2VwdC5uZXQiOiBbInd3dy5uaWNlcHQubmV0Il0sICJva3B0Lm5ldCI6IFsid3d3Lm9rcHQubmV0Il0sICJwdGhvbWUubmV0IjogWyJwdGhvbWUubmV0Il0sICJwdGxncy5vcmciOiBbInB0bC5ncyIsICJyZWxheTAxLnB0bC5ncyJdLCAicHRzYmFvLmNsdWIiOiBbInB0c2Jhby5jbHViIl0sICJwdHRpbWUub3JnIjogWyJ3d3cucHR0aW1lLm9yZyJdLCAicHR6b25lLnh5eiI6IFsicHR6b25lLnh5eiJdLCAicWluZ3dhcHQuY29tIjogWyJ0cmFja2VyLnFpbmd3YS5wcm8iLCAidHJhY2tlci5xaW5nd2FwdC5jb20iXSwgInJhaW5nZmgudG9wIjogWyJyYWluZ2ZoLnRvcCJdLCAicm91c2kuemlwIjogWyJoaXRwdC5jb20iXSwgInNwcmluZ3N1bmRheS5uZXQiOiBbIm9uNi5zcHJpbmdzdW5kYXkubmV0IiwgIm9uLnNwcmluZ3N1bmRheS5uZXQiXSwgInRqdXB0Lm9yZyI6IFsidHJhY2tlci1wdWJsaWMudGp1cHQub3JnIl0sICJ0b3RoZWdsb3J5LmltIjogWyJ0cmFja2VyLnRvdGhlZ2xvcnkuaW0iXSwgInUyLmRtaHkub3JnIjogWyJkYXlkcmVhbS5kbWh5LmJlc3QiXSwgInhpbmd5dW5nZS50b3AiOiBbInRyYWNrZXIueGluZ3l1bmdlLnRvcCIsICJ0cmFja2VyLnhpbmd5dW5nZS5zYnMiXSwgInptcHQuY2MiOiBbInptcHQuY2MiXSwgImhoYW5jbHViLnRvcCI6IFsidHJhY2tlci5oaGFuY2x1Yi50b3AiXSwgImhkY2l0eS5jaXR5IjogWyJzeW5jLmxlbml0ZXIub3JnIl19

View File

@@ -21,7 +21,7 @@ class DingdingMsg(_PluginBase):
# 插件图标
plugin_icon = "Dingding_A.png"
# 插件版本
plugin_version = "1.12"
plugin_version = "1.13"
# 插件作者
plugin_author = "nnlegenda"
# 作者主页
@@ -209,6 +209,8 @@ class DingdingMsg(_PluginBase):
if text:
# 对text进行Markdown特殊字符转义
text = re.sub(r"([_`])", r"\\\1", text)
# 钉钉中需要在换行前有两个空格,才能够正常换行
text = re.sub(r"\n", r" \n", text)
else:
text = ""