import asyncio
|
import json
|
from pathlib import Path
|
from datetime import datetime, timedelta
|
from auto_media_publisher.config.conf_base import TASK_CONFIG_DIR,COOKIE_DIR,PLATFORM_LOGIN_CONCURRENT_COUNT,DATABASE_PATH
|
from auto_media_publisher.utils.logger import get_logger
|
from auto_media_publisher.utils.login_helper import create_and_run_login
|
from auto_media_publisher.utils.utils_network import check_proxy_valid
|
from auto_media_publisher.utils.utils_database import platform_operation_fail_insert
|
# ----------------- 任务生成器 -----------------
|
|
class PlatformLoginChecker:
|
def __init__(self):
|
self.config_dir_path = Path(TASK_CONFIG_DIR)
|
self.cookie_dir_path = Path(COOKIE_DIR)
|
self.logger = get_logger(self.__class__.__name__,"admin")
|
self.logger.info("PlatformLoginChecker started.")
|
|
def _check_need_login(self, user,platform,max_session_hour):
|
|
cookie_root = Path(COOKIE_DIR) # 把 COOKIE_DIR 变成 Path 对象,如果它是字符串的话
|
user_cookie_path = cookie_root / user / f"{platform}.json"
|
|
if not user_cookie_path.exists():
|
return False
|
|
mtime = user_cookie_path.stat().st_mtime
|
last_modified = datetime.fromtimestamp(mtime)
|
|
now = datetime.now()
|
# 计算时间差
|
delta = now - last_modified
|
|
# 如果超过指定小时数,返回 True
|
return delta > timedelta(hours=max_session_hour)
|
|
def _get_avalible_users(self):
|
all_need_logins = []
|
for config_file in self.config_dir_path.rglob("*.json"):
|
try:
|
user_config = json.loads(config_file.read_text(encoding="utf-8"))
|
if not user_config.get("enabled", True):
|
self.logger.info(f"跳过未启用用户:{config_file.name}")
|
continue
|
|
user = user_config.get("user")
|
proxy = user_config.get("proxy")
|
|
platforms = user_config.get("platforms", [])
|
|
for platform in platforms:
|
if not platform.get("enabled", True):
|
continue
|
|
platform_name = platform["name"]
|
max_session_hour = platform["max_session_hour"]
|
|
if self._check_need_login(user,platform_name,max_session_hour):
|
proxy_valid,ip,city = check_proxy_valid(proxy)
|
if proxy_valid:
|
all_need_logins.append({
|
"user":user,
|
"proxy":proxy,
|
"platform":platform_name
|
})
|
else:
|
platform_operation_fail_insert(user,platform,proxy,"proxy","")
|
self.logger.error(f"代理端口不可用,Proxy Port NOT valid。 {user} : {proxy}")
|
except Exception as e:
|
self.logger.warning(f"无法读取配置文件 {config_file.name}:{e}")
|
continue
|
return all_need_logins
|
|
async def _async_run(self):
|
need_logins = self._get_avalible_users()
|
self.logger.info(f"[PlatformLoginChecker] 待登录的用户/平台数量: {len(need_logins)}")
|
|
if not need_logins:
|
self.logger.info("[PlatformLoginChecker] 无任务,自动退出。")
|
return
|
|
login_task_queue = asyncio.Queue()
|
for row in need_logins:
|
await login_task_queue.put(row)
|
|
semaphore = asyncio.Semaphore(PLATFORM_LOGIN_CONCURRENT_COUNT)
|
|
async def worker_wrapper(task_row):
|
async with semaphore:
|
try:
|
user =task_row["user"]
|
platform = task_row["platform"]
|
proxy = task_row["proxy"]
|
|
if check_proxy_valid(proxy):
|
login_ok = await create_and_run_login(user,platform,proxy)
|
if not login_ok:
|
platform_operation_fail_insert(user,platform,proxy,"login_auth","")
|
else:
|
platform_operation_fail_insert(user,platform,proxy,"proxy fail","")
|
|
except Exception as e:
|
self.logger.error(f"[PlatformLoginChecker] 任务处理异常: {e}")
|
|
# 创建所有任务
|
tasks = []
|
while not login_task_queue.empty():
|
row = await login_task_queue.get()
|
tasks.append(asyncio.create_task(worker_wrapper(row)))
|
|
# 等待所有任务完成
|
await asyncio.gather(*tasks)
|
|
def run(self):
|
asyncio.run(self._async_run())
|