mirror of
https://github.com/jxxghp/MoviePilot-Plugins.git
synced 2026-05-23 07:26:47 +00:00
111 lines
4.0 KiB
Python
111 lines
4.0 KiB
Python
from typing import Optional, Dict, Literal, List, Union
|
|
|
|
from pydantic import Field, BaseModel, field_validator, ValidationInfo
|
|
|
|
from .proxybase import ProxyBase
|
|
|
|
|
|
ShadowsocksCipherType = Literal[
|
|
# AES 相关
|
|
'aes-128-ctr', 'aes-192-ctr', 'aes-256-ctr',
|
|
'aes-128-cfb', 'aes-192-cfb', 'aes-256-cfb',
|
|
'aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm',
|
|
'aes-128-com', 'aes-192-com', 'aes-256-com',
|
|
'aes-128-gcm-siv', 'aes-256-gcm-siv',
|
|
# CHACHA 相关
|
|
'chacha20-ietf', 'chacha20', 'xchacha20',
|
|
'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305',
|
|
'chacha8-ietf-poly1305', 'xchacha8-ietf-poly1305',
|
|
# 2022 Blake3 相关
|
|
'2022-blake3-aes-128-gcm', '2022-blake3-aes-256-gcm', '2022-blake3-chacha20-poly1305',
|
|
# LEA 相关
|
|
'lea-128-gcm', 'lea-192-gcm', 'lea-256-gcm',
|
|
# 其他
|
|
'rabbit128-poly1305', 'aegis-128l', 'aegis-256', 'aez-384', 'deoxys-ii-256-128', 'rc4-md5', 'none'
|
|
]
|
|
|
|
|
|
class ObfsPluginOpts(BaseModel):
|
|
mode: Literal['tls', 'http']
|
|
host: Optional[str] = Field(default="bing.com")
|
|
|
|
|
|
class V2rayPluginOpts(BaseModel):
|
|
mode: Literal['websocket'] = 'websocket'
|
|
host: Optional[str] = Field(default="bing.com")
|
|
path: Optional[str] = None
|
|
tls: Optional[bool] = False
|
|
fingerprint: Optional[str] = None
|
|
headers: Optional[Dict[str, str]] = None
|
|
skip_cert_verify: Optional[bool] = Field(False, alias='skip-cert-verify')
|
|
mux: Optional[bool] = True
|
|
v2ray_http_upgrade: Optional[bool] = Field(False, alias='v2ray-http-upgrade')
|
|
v2ray_http_upgrade_fast_open: Optional[bool] = Field(False, alias='v2ray-http-upgrade-fast-open')
|
|
|
|
|
|
class GostPluginOpts(BaseModel):
|
|
mode: Literal['websocket'] = 'websocket'
|
|
host: Optional[str] = Field(default="bing.com")
|
|
path: Optional[str] = None
|
|
tls: Optional[bool] = False
|
|
fingerprint: Optional[str] = None
|
|
headers: Optional[Dict[str, str]] = None
|
|
skip_cert_verify: Optional[bool] = Field(False, alias='skip-cert-verify')
|
|
mux: Optional[bool] = True
|
|
|
|
|
|
class ShadowTlsPluginOpts(BaseModel):
|
|
password: Optional[str] = None
|
|
host: str
|
|
fingerprint: Optional[str] = None
|
|
skip_cert_verify: Optional[bool] = Field(False, alias='skip-cert-verify')
|
|
version: Optional[Literal[1, 2, 3]] = 2
|
|
alpn: Optional[List[str]] = None
|
|
|
|
|
|
class RestlsPluginOpts(BaseModel):
|
|
password: str
|
|
host: str
|
|
version_hint: str = Field(alias='version-hint')
|
|
restls_script: Optional[str] = Field(None, alias='restls-script')
|
|
|
|
|
|
class ShadowsocksProxy(ProxyBase):
|
|
type: Literal['ss'] = 'ss'
|
|
cipher: ShadowsocksCipherType
|
|
password: str
|
|
udp_over_tcp: Optional[bool] = Field(None, alias='udp-over-tcp')
|
|
udp_over_tcp_version: Optional[Literal[1, 2]] = Field(1, alias='udp-over-tcp-version')
|
|
client_fingerprint: Optional[Literal['chrome', 'ios', 'firefox', 'safari']] = Field(None,
|
|
alias='client-fingerprint')
|
|
plugin: Optional[Literal['obfs', 'v2ray-plugin', 'shadow-tls', 'restls', 'gost-plugin']] = None
|
|
plugin_opts: Optional[Union[
|
|
ObfsPluginOpts,
|
|
V2rayPluginOpts,
|
|
GostPluginOpts,
|
|
ShadowTlsPluginOpts,
|
|
RestlsPluginOpts,
|
|
]] = Field(None, alias='plugin-opts')
|
|
|
|
|
|
@field_validator("plugin_opts")
|
|
@classmethod
|
|
def validate_plugin_opts(cls, v, info: ValidationInfo):
|
|
plugin = info.data.get("plugin")
|
|
if plugin and v:
|
|
if not isinstance(plugin, str):
|
|
raise ValueError("plugin must be a string")
|
|
plugin_model_map = {
|
|
"obfs": "ObfsPluginOpts",
|
|
"v2ray-plugin": "V2rayPluginOpts",
|
|
"gost-plugin": "GostPluginOpts",
|
|
"shadow-tls": "ShadowTlsPluginOpts",
|
|
"restls": "RestlsPluginOpts",
|
|
}
|
|
|
|
expected_model = plugin_model_map.get(plugin)
|
|
if expected_model and v.__class__.__name__ != expected_model:
|
|
raise ValueError(f"{plugin} plugin requires {expected_model}")
|
|
|
|
return v
|