2025-11-12 00:28:07 +08:00

216 lines
5.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
平台适配器基类
定义了所有平台适配器的通用接口。
"""
from abc import ABC, abstractmethod
from typing import Optional, Dict, Any
from playwright.async_api import Page
from ..core.models import (
PlatformType,
AccountInfo,
Content,
PublishResult,
UploadStatus,
PublishStatus
)
from ..auth.base_auth import BaseAuth
class BaseAdapter(ABC):
"""平台适配器基类"""
def __init__(self, platform: PlatformType):
self.platform = platform
self.platform_name = platform.value
@abstractmethod
async def login(self, account_info: AccountInfo, headless: bool = False) -> bool:
"""
登录平台
Args:
account_info: 账号信息
headless: 是否使用无头模式
Returns:
登录是否成功
"""
pass
@abstractmethod
async def publish_content(self, page: Page, content: Content, account_info: AccountInfo) -> PublishResult:
"""
发布内容
Args:
page: Playwright页面对象
content: 要发布的内容
account_info: 账号信息
Returns:
发布结果
"""
pass
@abstractmethod
async def check_login_status(self, page: Page) -> bool:
"""
检查登录状态
Args:
page: Playwright页面对象
Returns:
是否已登录
"""
pass
@abstractmethod
def get_authenticator(self) -> BaseAuth:
"""
获取认证器实例
Returns:
认证器实例
"""
pass
async def validate_content(self, content: Content) -> tuple[bool, str]:
"""
验证内容是否符合平台要求
Args:
content: 要验证的内容
Returns:
(是否有效, 错误信息)
"""
# 基础验证
if not content.title.strip():
return False, "标题不能为空"
if not content.description.strip():
return False, "内容描述不能为空"
if len(content.title) > 100:
return False, "标题过长最多100个字符"
if len(content.description) > 1000:
return False, "内容过长最多1000个字符"
return True, ""
async def wait_for_upload_complete(
self,
page: Page,
timeout: int = 300,
check_interval: float = 2.0
) -> bool:
"""
等待上传完成
Args:
page: Playwright页面对象
timeout: 超时时间(秒)
check_interval: 检查间隔(秒)
Returns:
上传是否完成
"""
import asyncio
start_time = asyncio.get_event_loop().time()
while asyncio.get_event_loop().time() - start_time < timeout:
if await self._check_upload_status(page):
return True
await asyncio.sleep(check_interval)
return False
async def _check_upload_status(self, page: Page) -> bool:
"""
检查上传状态(子类实现)
Args:
page: Playwright页面对象
Returns:
上传是否完成
"""
# 默认实现,子类应该重写
return True
async def wait_for_publish_complete(
self,
page: Page,
timeout: int = 60,
check_interval: float = 2.0
) -> bool:
"""
等待发布完成
Args:
page: Playwright页面对象
timeout: 超时时间(秒)
check_interval: 检查间隔(秒)
Returns:
发布是否完成
"""
import asyncio
start_time = asyncio.get_event_loop().time()
while asyncio.get_event_loop().time() - start_time < timeout:
if await self._check_publish_status(page):
return True
await asyncio.sleep(check_interval)
return False
async def _check_publish_status(self, page: Page) -> bool:
"""
检查发布状态(子类实现)
Args:
page: Playwright页面对象
Returns:
发布是否完成
"""
# 默认实现,子类应该重写
return True
def create_publish_result(
self,
success: bool,
message: str,
task_id: str,
account: str,
error_details: Optional[Dict[str, Any]] = None,
duration: Optional[float] = None
) -> PublishResult:
"""
创建发布结果对象
Args:
success: 是否成功
message: 结果消息
task_id: 任务ID
account: 账号名称
error_details: 错误详情
duration: 执行耗时
Returns:
发布结果对象
"""
return PublishResult(
task_id=task_id,
platform=self.platform,
account=account,
success=success,
message=message,
error_details=error_details,
duration=duration
)