From fffad33cc5ebc496f73904f9a99915618cf9f0fa Mon Sep 17 00:00:00 2001 From: xiaoQQya Date: Wed, 14 Jan 2026 19:23:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(AutoSignIn):=20=E9=80=82=E9=85=8D=E7=AB=99?= =?UTF-8?q?=E7=82=B9=20Rousi=20Pro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 3 +- plugins.v2/autosignin/__init__.py | 2 +- plugins.v2/autosignin/sites/rousipro.py | 114 ++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 plugins.v2/autosignin/sites/rousipro.py diff --git a/package.v2.json b/package.v2.json index 4cbdcbe..dd7a099 100644 --- a/package.v2.json +++ b/package.v2.json @@ -44,12 +44,13 @@ "name": "站点自动签到", "description": "自动模拟登录、签到站点。", "labels": "站点", - "version": "2.7", + "version": "2.8", "icon": "signin.png", "author": "thsrite", "level": 2, "release": true, "history": { + "v2.8": "适配站点 Rousi Pro", "v2.7": "站点请求使用站点设置的超时时间", "v2.6": "感谢madrays佬提供的UI!", "v2.5.4": "增加保号风险提示", diff --git a/plugins.v2/autosignin/__init__.py b/plugins.v2/autosignin/__init__.py index 231d2a8..a8e5700 100644 --- a/plugins.v2/autosignin/__init__.py +++ b/plugins.v2/autosignin/__init__.py @@ -35,7 +35,7 @@ class AutoSignIn(_PluginBase): # 插件图标 plugin_icon = "signin.png" # 插件版本 - plugin_version = "2.7" + plugin_version = "2.8" # 插件作者 plugin_author = "thsrite" # 作者主页 diff --git a/plugins.v2/autosignin/sites/rousipro.py b/plugins.v2/autosignin/sites/rousipro.py new file mode 100644 index 0000000..66ec3e4 --- /dev/null +++ b/plugins.v2/autosignin/sites/rousipro.py @@ -0,0 +1,114 @@ +from typing import Tuple + +from ruamel.yaml import CommentedMap + +from app.log import logger +from app.core.config import settings +from app.utils.http import RequestUtils +from app.utils.string import StringUtils +from app.plugins.autosignin.sites import _ISiteSigninHandler + + +class RousiPro(_ISiteSigninHandler): + """ + rousi pro 签到 + """ + # 匹配的站点Url,每一个实现类都需要设置为自己的站点Url + site_url = "rousi.pro" + + @classmethod + def match(cls, url: str) -> bool: + """ + 根据站点Url判断是否匹配当前站点签到类,大部分情况使用默认实现即可 + :param url: 站点Url + :return: 是否匹配,如匹配则会调用该类的signin方法 + """ + return True if StringUtils.url_equal(url, cls.site_url) else False + + def signin(self, site_info: CommentedMap) -> Tuple[bool, str]: + """ + 执行签到操作,固定签到 + :param site_info: 站点信息,含有站点Url、站点Cookie、UA等信息 + :return: 签到结果信息 + """ + site = site_info.get("name") + ua = site_info.get("ua") + token = site_info.get("token") + timeout = site_info.get("timeout") + if not token or token.strip() == "": + logger.error(f"{site} 签到失败,缺少 Authorization 信息") + return False, "签到失败,缺少 Authorization 信息" + + headers = { + "Content-Type": "application/json", + "User-Agent": ua, + "Accept": "application/json, text/plain, */*", + "Authorization": token if token.startswith("Bearer ") else f"Bearer {token}" + } + body = { + "mode": "fixed" + } + res = RequestUtils( + headers=headers, + timeout=timeout, + proxies=settings.PROXY if site_info.get("proxy") else None, + ).post_res( + url="https://rousi.pro/api/points/attendance", + json=body + ) + + if res is not None and res.status_code == 200 and "签到成功" in res.json().get("message", ""): + logger.info(f"{site} 签到成功") + return True, "签到成功" + elif res is not None and res.status_code == 400 and res.json().get("error", "") == "今日已签到": + logger.info(f"{site} 今日已签到") + return True, "今日已签到" + elif res is not None and res.status_code == 401: + logger.error(f"{site} 签到失败,登录状态无效") + return False, "签到失败,登录状态无效" + elif res is not None: + logger.error(f"{site} 签到失败,状态码:{res.status_code}") + return False, f"签到失败,状态码:{res.status_code}" + else: + logger.error(f"{site} 签到失败,无法访问网站") + return False, "签到失败,无法访问网站" + + def login(self, site_info: CommentedMap) -> Tuple[bool, str]: + """ + 执行登录操作,访问签到统计接口更新站点最后活跃时间 + :param site_info: 站点信息,含有站点Url、站点Cookie、UA等信息 + :return: 登录结果信息 + """ + site = site_info.get("name") + ua = site_info.get("ua") + token = site_info.get("token") + timeout = site_info.get("timeout") + if not token or token.strip() == "": + logger.error(f"{site} 模拟登录失败,缺少 Authorization 信息") + return False, "模拟登录失败,缺少 Authorization 信息" + + headers = { + "User-Agent": ua, + "Accept": "application/json, text/plain, */*", + "Authorization": token if token.startswith("Bearer ") else f"Bearer {token}" + } + res = RequestUtils( + headers=headers, + timeout=timeout, + proxies=settings.PROXY if site_info.get("proxy") else None, + ).get_res( + url="https://rousi.pro/api/points/attendance/stats" + ) + + if res is not None and res.status_code == 200 and "attended_dates" in res.json(): + logger.info(f"{site} 模拟登录成功") + return True, "模拟登录成功" + elif res is not None and res.status_code == 401: + logger.error(f"{site} 模拟登录失败,登录状态无效") + return False, "模拟登录失败,登录状态无效" + elif res is not None: + logger.error(f"{site} 模拟登录失败,状态码:{res.status_code}") + return False, f"模拟登录失败,状态码:{res.status_code}" + else: + logger.error(f"{site} 模拟登录失败,无法访问网站") + return False, "模拟登录失败,无法访问网站"