127 lines
3.5 KiB
Python
127 lines
3.5 KiB
Python
"""
|
|
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())
|