add-files
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
"""
|
||||
CookieCloud数据模型
|
||||
"""
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional, Dict, List
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class CookieConfig:
|
||||
"""CookieCloud配置"""
|
||||
server: str
|
||||
username: str
|
||||
password: str
|
||||
timeout: int = 30
|
||||
verify_ssl: bool = True
|
||||
ignore_cookies: List[str] = field(default_factory=lambda: [
|
||||
"CookieAutoDeleteBrowsingDataCleanup",
|
||||
"CookieAutoDeleteCleaningDiscarded"
|
||||
])
|
||||
|
||||
def __post_init__(self):
|
||||
"""验证配置参数"""
|
||||
if not self.server:
|
||||
raise ValueError("服务器地址不能为空")
|
||||
if not self.username:
|
||||
raise ValueError("用户名不能为空")
|
||||
if not self.password:
|
||||
raise ValueError("密码不能为空")
|
||||
if not self.server.startswith(('http://', 'https://')):
|
||||
self.server = f"https://{self.server}"
|
||||
|
||||
|
||||
@dataclass
|
||||
class CookieData:
|
||||
"""Cookie数据"""
|
||||
domain: str
|
||||
name: str
|
||||
value: str
|
||||
path: str = "/"
|
||||
secure: bool = False
|
||||
http_only: bool = False
|
||||
expiry: Optional[datetime] = None
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
"""转换为字典"""
|
||||
return {
|
||||
'domain': self.domain,
|
||||
'name': self.name,
|
||||
'value': self.value,
|
||||
'path': self.path,
|
||||
'secure': self.secure,
|
||||
'httpOnly': self.http_only,
|
||||
'expiry': self.expiry.isoformat() if self.expiry else None
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict) -> 'CookieData':
|
||||
"""从字典创建"""
|
||||
expiry = None
|
||||
if data.get('expiry'):
|
||||
try:
|
||||
expiry = datetime.fromisoformat(data['expiry'])
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
return cls(
|
||||
domain=data.get('domain', ''),
|
||||
name=data.get('name', ''),
|
||||
value=data.get('value', ''),
|
||||
path=data.get('path', '/'),
|
||||
secure=data.get('secure', False),
|
||||
http_only=data.get('httpOnly', False),
|
||||
expiry=expiry
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class CookieCollection:
|
||||
"""Cookie集合"""
|
||||
domain: str
|
||||
cookies: List[CookieData] = field(default_factory=list)
|
||||
|
||||
def to_cookie_string(self, ignore_list: List[str] = None) -> str:
|
||||
"""转换为cookie字符串"""
|
||||
ignore_list = ignore_list or []
|
||||
cookie_parts = []
|
||||
|
||||
for cookie in self.cookies:
|
||||
if cookie.name not in ignore_list:
|
||||
cookie_parts.append(f"{cookie.name}={cookie.value}")
|
||||
|
||||
return ";".join(cookie_parts)
|
||||
|
||||
def add_cookie(self, cookie: CookieData):
|
||||
"""添加cookie"""
|
||||
self.cookies.append(cookie)
|
||||
|
||||
def get_cookie_by_name(self, name: str) -> Optional[CookieData]:
|
||||
"""根据名称获取cookie"""
|
||||
for cookie in self.cookies:
|
||||
if cookie.name == name:
|
||||
return cookie
|
||||
return None
|
||||
|
||||
|
||||
@dataclass
|
||||
class DownloadResult:
|
||||
"""下载结果"""
|
||||
success: bool
|
||||
cookies: Dict[str, CookieCollection] = field(default_factory=dict)
|
||||
error_message: str = ""
|
||||
total_domains: int = 0
|
||||
total_cookies: int = 0
|
||||
download_time: float = 0.0
|
||||
|
||||
def get_cookie_string(self, domain: str) -> Optional[str]:
|
||||
"""获取指定域名的cookie字符串"""
|
||||
collection = self.cookies.get(domain)
|
||||
if collection:
|
||||
return collection.to_cookie_string()
|
||||
return None
|
||||
|
||||
def get_domains(self) -> List[str]:
|
||||
"""获取所有域名列表"""
|
||||
return list(self.cookies.keys())
|
||||
Reference in New Issue
Block a user