mirror of
https://github.com/jxxghp/MoviePilot-Plugins.git
synced 2026-06-13 23:16:49 +00:00
Compare commits
6 Commits
ClashRuleP
...
AutoSignIn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2503648a9 | ||
|
|
fffad33cc5 | ||
|
|
ae99671190 | ||
|
|
528b938f0f | ||
|
|
722f8da96d | ||
|
|
c53a3dc152 |
@@ -44,12 +44,13 @@
|
||||
"name": "站点自动签到",
|
||||
"description": "自动模拟登录、签到站点。",
|
||||
"labels": "站点",
|
||||
"version": "2.7",
|
||||
"version": "2.8",
|
||||
"icon": "signin.png",
|
||||
"author": "thsrite",
|
||||
"level": 2,
|
||||
"release": true,
|
||||
"history": {
|
||||
"v2.8": "适配站点 Rousi Pro",
|
||||
"v2.7": "站点请求使用站点设置的超时时间",
|
||||
"v2.6": "感谢madrays佬提供的UI!",
|
||||
"v2.5.4": "增加保号风险提示",
|
||||
@@ -508,12 +509,13 @@
|
||||
"name": "Clash Rule Provider",
|
||||
"description": "随时为Clash添加一些额外的规则。",
|
||||
"labels": "工具",
|
||||
"version": "2.1.1",
|
||||
"version": "2.1.2",
|
||||
"icon": "Mihomo_Meta_A.png",
|
||||
"author": "wumode",
|
||||
"level": 1,
|
||||
"release": true,
|
||||
"history": {
|
||||
"v2.1.2": "修复规则集序列化错误",
|
||||
"v2.1.1": "增强数据管理功能",
|
||||
"v2.0.10": "适配 MoviePilot 2.8.4",
|
||||
"v2.0.9": "适配 Pydantic V2 (主程序版本需高于 2.8.1-1)",
|
||||
@@ -551,12 +553,12 @@
|
||||
"name": "美剧生词标注",
|
||||
"description": "根据CEFR等级,为英语影视剧标注高级词汇。",
|
||||
"labels": "英语",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"icon": "LexiAnnot.png",
|
||||
"author": "wumode",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.2.2": "优化提示词",
|
||||
"v1.2.3": "优化提示词",
|
||||
"v1.2.1": "改进字幕样式获取方法",
|
||||
"v1.2.0": "引入大模型候选词决策和词义丰富处理链; 支持读取系统智能体配置; 添加智能体工具; 优化通知样式; 改进 UI",
|
||||
"v1.1.4": "优化字幕选择决策",
|
||||
|
||||
@@ -35,7 +35,7 @@ class AutoSignIn(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "signin.png"
|
||||
# 插件版本
|
||||
plugin_version = "2.7"
|
||||
plugin_version = "2.8"
|
||||
# 插件作者
|
||||
plugin_author = "thsrite"
|
||||
# 作者主页
|
||||
|
||||
114
plugins.v2/autosignin/sites/rousipro.py
Normal file
114
plugins.v2/autosignin/sites/rousipro.py
Normal file
@@ -0,0 +1,114 @@
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.log import logger
|
||||
from app.core.config import settings
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
|
||||
|
||||
class RousiPro(_ISiteSigninHandler):
|
||||
"""
|
||||
rousi pro 签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "rousi.pro"
|
||||
|
||||
@classmethod
|
||||
def match(cls, url: str) -> bool:
|
||||
"""
|
||||
根据站点Url判断是否匹配当前站点签到类,大部分情况使用默认实现即可
|
||||
:param url: 站点Url
|
||||
:return: 是否匹配,如匹配则会调用该类的signin方法
|
||||
"""
|
||||
return True if StringUtils.url_equal(url, cls.site_url) else False
|
||||
|
||||
def signin(self, site_info: CommentedMap) -> Tuple[bool, str]:
|
||||
"""
|
||||
执行签到操作,固定签到
|
||||
:param site_info: 站点信息,含有站点Url、站点Cookie、UA等信息
|
||||
:return: 签到结果信息
|
||||
"""
|
||||
site = site_info.get("name")
|
||||
ua = site_info.get("ua")
|
||||
token = site_info.get("token")
|
||||
timeout = site_info.get("timeout")
|
||||
if not token or token.strip() == "":
|
||||
logger.error(f"{site} 签到失败,缺少 Authorization 信息")
|
||||
return False, "签到失败,缺少 Authorization 信息"
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": ua,
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"Authorization": token if token.startswith("Bearer ") else f"Bearer {token}"
|
||||
}
|
||||
body = {
|
||||
"mode": "fixed"
|
||||
}
|
||||
res = RequestUtils(
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
proxies=settings.PROXY if site_info.get("proxy") else None,
|
||||
).post_res(
|
||||
url="https://rousi.pro/api/points/attendance",
|
||||
json=body
|
||||
)
|
||||
|
||||
if res is not None and res.status_code == 200 and "签到成功" in res.json().get("message", ""):
|
||||
logger.info(f"{site} 签到成功")
|
||||
return True, "签到成功"
|
||||
elif res is not None and res.status_code == 400 and res.json().get("error", "") == "今日已签到":
|
||||
logger.info(f"{site} 今日已签到")
|
||||
return True, "今日已签到"
|
||||
elif res is not None and res.status_code == 401:
|
||||
logger.error(f"{site} 签到失败,登录状态无效")
|
||||
return False, "签到失败,登录状态无效"
|
||||
elif res is not None:
|
||||
logger.error(f"{site} 签到失败,状态码:{res.status_code}")
|
||||
return False, f"签到失败,状态码:{res.status_code}"
|
||||
else:
|
||||
logger.error(f"{site} 签到失败,无法访问网站")
|
||||
return False, "签到失败,无法访问网站"
|
||||
|
||||
def login(self, site_info: CommentedMap) -> Tuple[bool, str]:
|
||||
"""
|
||||
执行登录操作,访问签到统计接口更新站点最后活跃时间
|
||||
:param site_info: 站点信息,含有站点Url、站点Cookie、UA等信息
|
||||
:return: 登录结果信息
|
||||
"""
|
||||
site = site_info.get("name")
|
||||
ua = site_info.get("ua")
|
||||
token = site_info.get("token")
|
||||
timeout = site_info.get("timeout")
|
||||
if not token or token.strip() == "":
|
||||
logger.error(f"{site} 模拟登录失败,缺少 Authorization 信息")
|
||||
return False, "模拟登录失败,缺少 Authorization 信息"
|
||||
|
||||
headers = {
|
||||
"User-Agent": ua,
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"Authorization": token if token.startswith("Bearer ") else f"Bearer {token}"
|
||||
}
|
||||
res = RequestUtils(
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
proxies=settings.PROXY if site_info.get("proxy") else None,
|
||||
).get_res(
|
||||
url="https://rousi.pro/api/points/attendance/stats"
|
||||
)
|
||||
|
||||
if res is not None and res.status_code == 200 and "attended_dates" in res.json():
|
||||
logger.info(f"{site} 模拟登录成功")
|
||||
return True, "模拟登录成功"
|
||||
elif res is not None and res.status_code == 401:
|
||||
logger.error(f"{site} 模拟登录失败,登录状态无效")
|
||||
return False, "模拟登录失败,登录状态无效"
|
||||
elif res is not None:
|
||||
logger.error(f"{site} 模拟登录失败,状态码:{res.status_code}")
|
||||
return False, f"模拟登录失败,状态码:{res.status_code}"
|
||||
else:
|
||||
logger.error(f"{site} 模拟登录失败,无法访问网站")
|
||||
return False, "模拟登录失败,无法访问网站"
|
||||
@@ -36,7 +36,7 @@ class ClashRuleProvider(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "Mihomo_Meta_A.png"
|
||||
# 插件版本
|
||||
plugin_version = "2.1.1"
|
||||
plugin_version = "2.1.2"
|
||||
# 插件作者
|
||||
plugin_author = "wumode"
|
||||
# 作者主页
|
||||
@@ -92,6 +92,8 @@ class ClashRuleProvider(_PluginBase):
|
||||
logger.error("Invalid clash template yaml")
|
||||
except yaml.YAMLError as exc:
|
||||
logger.error(f"Error loading clash template yaml: {exc}")
|
||||
except Exception as ve:
|
||||
logger.error(f"Error validating clash template config: {ve}")
|
||||
|
||||
self.services.load_rules()
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
|
||||
.rule-card[data-v-da4a3497]:hover {
|
||||
.rule-card[data-v-5bf9d562]:hover {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
.proxy-group-card[data-v-ef6241d5]:hover {
|
||||
.proxy-group-card[data-v-88bfc397]:hover {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
.proxy-card[data-v-ca5a79a2]:hover {
|
||||
.proxy-card[data-v-e80a10d3]:hover {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.rule-provider-card[data-v-24eb2895]:hover {
|
||||
.rule-provider-card[data-v-01e2e8ef]:hover {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,8 @@ const currentImports = {};
|
||||
const exportSet = new Set(['Module', '__esModule', 'default', '_export_sfc']);
|
||||
let moduleMap = {
|
||||
"./Page":()=>{
|
||||
dynamicLoadingCss(["__federation_expose_Page-BLBLx7jX.css"], false, './Page');
|
||||
return __federation_import('./__federation_expose_Page-KIk8A7rq.js').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},
|
||||
dynamicLoadingCss(["__federation_expose_Page-CJILOVp4.css"], false, './Page');
|
||||
return __federation_import('./__federation_expose_Page-DeAFYy3o.js').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},
|
||||
"./Config":()=>{
|
||||
dynamicLoadingCss(["__federation_expose_Config-CwbjkOP2.css"], false, './Config');
|
||||
return __federation_import('./__federation_expose_Config-CY46uj5g.js').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},
|
||||
|
||||
@@ -6,6 +6,7 @@ import jsonpatch
|
||||
from pydantic import ValidationError
|
||||
|
||||
from app.db.plugindata_oper import PluginDataOper
|
||||
from app.log import logger
|
||||
|
||||
from ..configconverter import Converter
|
||||
from ..utilsprovider import UtilsProvider
|
||||
@@ -39,6 +40,7 @@ def upgrade(plugin_id: str):
|
||||
new_pg.append(obj.model_dump(by_alias=True, exclude_none=True))
|
||||
names.add(obj.name)
|
||||
except ValidationError:
|
||||
logger.error(f"升级代理组失败: {pg}")
|
||||
invalid_pg.append(pg)
|
||||
|
||||
data_oper.save(plugin_id, DataKey.PROXY_GROUPS, new_pg)
|
||||
@@ -53,6 +55,7 @@ def upgrade(plugin_id: str):
|
||||
obj = RuleProviderData(meta=Metadata(source=DataSource.MANUAL), name=name, data=rp)
|
||||
new_rp.append(obj.model_dump(by_alias=True, exclude_none=True))
|
||||
except ValidationError:
|
||||
logger.error(f"升级规则集失败: {rp}")
|
||||
invalid_rp.append(rp)
|
||||
|
||||
data_oper.save(plugin_id, DataKey.RULE_PROVIDERS, new_rp)
|
||||
@@ -83,6 +86,7 @@ def upgrade(plugin_id: str):
|
||||
all_proxies.append(p_data.data)
|
||||
names.add(p_data.name)
|
||||
except Exception:
|
||||
logger.error(f"升级代理失败: {proxy}")
|
||||
invalid_proxies.append(proxy)
|
||||
|
||||
data_oper.save(plugin_id, DataKey.PROXIES, new_proxies)
|
||||
|
||||
@@ -156,6 +156,13 @@ class ClashConfig(BaseModel):
|
||||
|
||||
return serialized_groups
|
||||
|
||||
@field_validator("mode", mode="before")
|
||||
@classmethod
|
||||
def validate_mode(cls, v):
|
||||
if isinstance(v, str):
|
||||
return v.lower()
|
||||
return v
|
||||
|
||||
@field_validator("rules", mode="before")
|
||||
@classmethod
|
||||
def validate_rules(cls, v):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import List, Optional, Literal
|
||||
from typing import Annotated, List, Optional, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, model_validator, HttpUrl
|
||||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||||
|
||||
from .generics import ResourceItem, ResourceList
|
||||
from .types import VehicleType
|
||||
@@ -14,15 +14,17 @@ class RuleProvider(BaseModel):
|
||||
)
|
||||
|
||||
type: VehicleType = Field(..., description="Provider type")
|
||||
url: Optional[HttpUrl] = Field(default=None, description="Must be configured if the type is http")
|
||||
url: Optional[str] = Field(default=None, description="Must be configured if the type is http")
|
||||
path: Optional[str] = Field(default=None, description="Optional, file path, must be unique.")
|
||||
interval: Optional[int] = Field(default=None, ge=0, description="The update interval for the provider, in seconds.")
|
||||
proxy: Optional[str] = Field(default=None, description="Download/update through the specified proxy.")
|
||||
behavior: Optional[Literal["domain", "ipcidr", "classical"]] = Field(None,
|
||||
description="Behavior of the rule provider")
|
||||
format: Literal["yaml", "text", "mrs"] = Field("yaml", description="Format of the rule provider file")
|
||||
size_limit: int = Field(default=0, ge=0, alias="size-limit",
|
||||
description="The maximum size of downloadable files in bytes (0 for no limit)")
|
||||
size_limit: Annotated[int, Field(
|
||||
default=0, ge=0, validation_alias="size-limit", serialization_alias="size-limit",
|
||||
description="The maximum size of downloadable files in bytes (0 for no limit)")
|
||||
] = 0
|
||||
payload: Optional[List[str]] = Field(default=None, description="Content, only effective when type is inline")
|
||||
|
||||
@model_validator(mode="before")
|
||||
|
||||
@@ -11,7 +11,6 @@ from typing import Any, Dict, List, Optional, Tuple, Iterable, TypeVar
|
||||
import jsonpatch
|
||||
from fastapi import HTTPException
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from pydantic import HttpUrl
|
||||
|
||||
from app.core.cache import cached
|
||||
from app.core.config import settings
|
||||
@@ -106,7 +105,7 @@ class ClashRuleProviderService:
|
||||
sub_url = (f"{self.state.config.movie_pilot_url}/api/v1/plugin/{self.plugin_id}/ruleset?"
|
||||
f"name={path_name}&apikey={self.state.config.apikey or settings.API_TOKEN}")
|
||||
auto_rule_provider[rule_provider_name] = RuleProvider(
|
||||
type=VehicleType.HTTP, behavior="classical", url=HttpUrl(sub_url), path=f"./CRP/{path_name}.yaml",
|
||||
type=VehicleType.HTTP, behavior="classical", url=sub_url, path=f"./CRP/{path_name}.yaml",
|
||||
interval=3600, format="yaml"
|
||||
)
|
||||
config.rule_providers = config.rule_providers | auto_rule_provider
|
||||
|
||||
@@ -60,7 +60,7 @@ class LexiAnnot(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "LexiAnnot.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.2.2"
|
||||
plugin_version = "1.2.3"
|
||||
# 插件作者
|
||||
plugin_author = "wumode"
|
||||
# 作者主页
|
||||
@@ -1904,7 +1904,7 @@ class LexiAnnot(_PluginBase):
|
||||
segments=segments,
|
||||
shutdown_event=self._shutdown_event,
|
||||
context_window=self._context_window,
|
||||
leaner_level=learner_level,
|
||||
learner_level=learner_level,
|
||||
media_context=mediainfo,
|
||||
translate_sentences=self._sentence_translation
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user