add plugins
This commit is contained in:
145
app/plugins/autosignin/sites/52pt.py
Normal file
145
app/plugins/autosignin/sites/52pt.py
Normal file
@@ -0,0 +1,145 @@
|
||||
import random
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class FWpt(_ISiteSigninHandler):
|
||||
"""
|
||||
52pt
|
||||
如果填写openai key则调用chatgpt获取答案
|
||||
否则随机
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "52pt.site"
|
||||
|
||||
# 已签到
|
||||
_sign_regex = ['今天已经签过到了']
|
||||
|
||||
# 签到成功,待补充
|
||||
_success_regex = ['\\d+点魔力值']
|
||||
|
||||
@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: dict) -> Tuple[bool, str]:
|
||||
"""
|
||||
执行签到操作
|
||||
:param site_info: 站点信息,含有站点Url、站点Cookie、UA等信息
|
||||
:return: 签到结果信息
|
||||
"""
|
||||
site = site_info.get("name")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 判断今日是否已签到
|
||||
index_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url='https://52pt.site/bakatest.php')
|
||||
|
||||
if not index_res or index_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in index_res.text:
|
||||
logger.error(f"签到失败,Cookie失效")
|
||||
return False, f'【{site}】签到失败,Cookie失效'
|
||||
|
||||
sign_status = self.sign_in_result(html_res=index_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 没有签到则解析html
|
||||
html = etree.HTML(index_res.text)
|
||||
|
||||
if not html:
|
||||
return False, f'【{site}】签到失败'
|
||||
|
||||
# 获取页面问题、答案
|
||||
questionid = html.xpath("//input[@name='questionid']/@value")[0]
|
||||
option_ids = html.xpath("//input[@name='choice[]']/@value")
|
||||
question_str = html.xpath("//td[@class='text' and contains(text(),'请问:')]/text()")[0]
|
||||
|
||||
# 正则获取问题
|
||||
match = re.search(r'请问:(.+)', question_str)
|
||||
if match:
|
||||
question_str = match.group(1)
|
||||
logger.debug(f"获取到签到问题 {question_str}")
|
||||
else:
|
||||
logger.error(f"未获取到签到问题")
|
||||
return False, f"【{site}】签到失败,未获取到签到问题"
|
||||
|
||||
# 正确答案,默认随机,如果gpt返回则用gpt返回的答案提交
|
||||
choice = [option_ids[random.randint(0, len(option_ids) - 1)]]
|
||||
|
||||
# 签到
|
||||
return self.__signin(questionid=questionid,
|
||||
choice=choice,
|
||||
site_cookie=site_cookie,
|
||||
ua=ua,
|
||||
proxy=proxy,
|
||||
site=site)
|
||||
|
||||
def __signin(self, questionid: str,
|
||||
choice: list,
|
||||
site: str,
|
||||
site_cookie: str,
|
||||
ua: str,
|
||||
proxy: dict) -> Tuple[bool, str]:
|
||||
"""
|
||||
签到请求
|
||||
questionid: 450
|
||||
choice[]: 8
|
||||
choice[]: 4
|
||||
usercomment: 此刻心情:无
|
||||
submit: 提交
|
||||
多选会有多个choice[]....
|
||||
"""
|
||||
data = {
|
||||
'questionid': questionid,
|
||||
'choice[]': choice[0] if len(choice) == 1 else choice,
|
||||
'usercomment': '太难了!',
|
||||
'wantskip': '不会'
|
||||
}
|
||||
logger.debug(f"签到请求参数 {data}")
|
||||
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
ua=ua,
|
||||
proxies=proxy
|
||||
).post_res(url='https://52pt.site/bakatest.php', data=data)
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,签到接口请求失败'
|
||||
|
||||
# 判断是否签到成功
|
||||
sign_status = self.sign_in_result(html_res=sign_res.text,
|
||||
regexs=self._success_regex)
|
||||
if sign_status:
|
||||
logger.info(f"{site}签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
else:
|
||||
sign_status = self.sign_in_result(html_res=sign_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
logger.error(f"签到失败,请到页面查看")
|
||||
return False, f'【{site}】签到失败,请到页面查看'
|
||||
46
app/plugins/autosignin/sites/__init__.py
Normal file
46
app/plugins/autosignin/sites/__init__.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class _ISiteSigninHandler(metaclass=ABCMeta):
|
||||
"""
|
||||
实现站点签到的基类,所有站点签到类都需要继承此类,并实现match和signin方法
|
||||
实现类放置到sitesignin目录下将会自动加载
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = ""
|
||||
|
||||
@abstractmethod
|
||||
def match(self, url: str) -> bool:
|
||||
"""
|
||||
根据站点Url判断是否匹配当前站点签到类,大部分情况使用默认实现即可
|
||||
:param url: 站点Url
|
||||
:return: 是否匹配,如匹配则会调用该类的signin方法
|
||||
"""
|
||||
return True if StringUtils.url_equal(url, self.site_url) else False
|
||||
|
||||
@abstractmethod
|
||||
def signin(self, site_info: CommentedMap) -> Tuple[bool, str]:
|
||||
"""
|
||||
执行签到操作
|
||||
:param site_info: 站点信息,含有站点Url、站点Cookie、UA等信息
|
||||
:return: True|False,签到结果信息
|
||||
"""
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def sign_in_result(html_res: str, regexs: list) -> bool:
|
||||
"""
|
||||
判断是否签到成功
|
||||
"""
|
||||
html_text = re.sub(r"#\d+", "", re.sub(r"\d+px", "", html_res))
|
||||
for regex in regexs:
|
||||
if re.search(str(regex), html_text):
|
||||
return True
|
||||
return False
|
||||
73
app/plugins/autosignin/sites/btschool.py
Normal file
73
app/plugins/autosignin/sites/btschool.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class BTSchool(_ISiteSigninHandler):
|
||||
"""
|
||||
学校签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "pt.btschool.club"
|
||||
|
||||
# 已签到
|
||||
_sign_text = '每日签到'
|
||||
|
||||
@classmethod
|
||||
def match(cls, url) -> 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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
logger.info(f"{site} 开始签到")
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://pt.btschool.club")
|
||||
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in html_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
# 已签到
|
||||
if self._sign_text not in html_res.text:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://pt.btschool.club/index.php?action=addbonus")
|
||||
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,签到接口请求失败'
|
||||
|
||||
# 签到成功
|
||||
if self._sign_text not in sign_res.text:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
146
app/plugins/autosignin/sites/chdbits.py
Normal file
146
app/plugins/autosignin/sites/chdbits.py
Normal file
@@ -0,0 +1,146 @@
|
||||
import random
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
from lxml import etree
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class CHDBits(_ISiteSigninHandler):
|
||||
"""
|
||||
彩虹岛签到
|
||||
如果填写openai key则调用chatgpt获取答案
|
||||
否则随机
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "chdbits.co"
|
||||
|
||||
# 已签到
|
||||
_sign_regex = ['今天已经签过到了']
|
||||
|
||||
# 签到成功,待补充
|
||||
_success_regex = ['\\d+点魔力值']
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 判断今日是否已签到
|
||||
index_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url='https://chdbits.co/bakatest.php')
|
||||
|
||||
if not index_res or index_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in index_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
sign_status = self.sign_in_result(html_res=index_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 没有签到则解析html
|
||||
html = etree.HTML(index_res.text)
|
||||
|
||||
if not html:
|
||||
return False, f'【{site}】签到失败'
|
||||
|
||||
# 获取页面问题、答案
|
||||
questionid = html.xpath("//input[@name='questionid']/@value")[0]
|
||||
option_ids = html.xpath("//input[@name='choice[]']/@value")
|
||||
question_str = html.xpath("//td[@class='text' and contains(text(),'请问:')]/text()")[0]
|
||||
|
||||
# 正则获取问题
|
||||
match = re.search(r'请问:(.+)', question_str)
|
||||
if match:
|
||||
question_str = match.group(1)
|
||||
logger.debug(f"获取到签到问题 {question_str}")
|
||||
else:
|
||||
logger.error(f"未获取到签到问题")
|
||||
return False, f"【{site}】签到失败,未获取到签到问题"
|
||||
|
||||
# 正确答案,默认随机,如果gpt返回则用gpt返回的答案提交
|
||||
choice = [option_ids[random.randint(0, len(option_ids) - 1)]]
|
||||
|
||||
# 签到
|
||||
return self.__signin(questionid=questionid,
|
||||
choice=choice,
|
||||
site_cookie=site_cookie,
|
||||
ua=ua,
|
||||
proxy=proxy,
|
||||
site=site)
|
||||
|
||||
def __signin(self, questionid: str,
|
||||
choice: list,
|
||||
site: str,
|
||||
site_cookie: str,
|
||||
ua: str,
|
||||
proxy: dict) -> Tuple[bool, str]:
|
||||
"""
|
||||
签到请求
|
||||
questionid: 450
|
||||
choice[]: 8
|
||||
choice[]: 4
|
||||
usercomment: 此刻心情:无
|
||||
submit: 提交
|
||||
多选会有多个choice[]....
|
||||
"""
|
||||
data = {
|
||||
'questionid': questionid,
|
||||
'choice[]': choice[0] if len(choice) == 1 else choice,
|
||||
'usercomment': '太难了!',
|
||||
'wantskip': '不会'
|
||||
}
|
||||
logger.debug(f"签到请求参数 {data}")
|
||||
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
ua=ua,
|
||||
proxies=proxy
|
||||
).post_res(url='https://chdbits.co/bakatest.php', data=data)
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,签到接口请求失败'
|
||||
|
||||
# 判断是否签到成功
|
||||
sign_status = self.sign_in_result(html_res=sign_res.text,
|
||||
regexs=self._success_regex)
|
||||
if sign_status:
|
||||
logger.info(f"{site} 签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
else:
|
||||
sign_status = self.sign_in_result(html_res=sign_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
logger.error(f"签到失败,请到页面查看")
|
||||
return False, f'【{site}】签到失败,请到页面查看'
|
||||
65
app/plugins/autosignin/sites/haidan.py
Normal file
65
app/plugins/autosignin/sites/haidan.py
Normal file
@@ -0,0 +1,65 @@
|
||||
import random
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
from lxml import etree
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class HaiDan(_ISiteSigninHandler):
|
||||
"""
|
||||
海胆签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "haidan.video"
|
||||
|
||||
# 签到成功
|
||||
_succeed_regex = ['(?<=value=")已经打卡(?=")']
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 签到
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://www.haidan.video/signin.php")
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in sign_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
sign_status = self.sign_in_result(html_res=sign_res.text,
|
||||
regexs=self._succeed_regex)
|
||||
if sign_status:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
|
||||
logger.error(f"签到失败,签到接口返回 {sign_res.text}")
|
||||
return False, f'【{site}】签到失败'
|
||||
80
app/plugins/autosignin/sites/hares.py
Normal file
80
app/plugins/autosignin/sites/hares.py
Normal file
@@ -0,0 +1,80 @@
|
||||
import json
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class Hares(_ISiteSigninHandler):
|
||||
"""
|
||||
白兔签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "club.hares.top"
|
||||
|
||||
# 已签到
|
||||
_sign_text = '已签到'
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 获取页面html
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://club.hares.top")
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"模拟访问失败,请检查站点连通性")
|
||||
return False, f'【{site}】模拟访问失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in html_res.text:
|
||||
logger.error(f"模拟访问失败,cookie失效")
|
||||
return False, f'【{site}】模拟访问失败,cookie失效'
|
||||
|
||||
# if self._sign_text in html_res.text:
|
||||
# logger.info(f"今日已签到")
|
||||
# return True, f'【{site}】今日已签到'
|
||||
|
||||
headers = {
|
||||
'Accept': 'application/json',
|
||||
"User-Agent": ua
|
||||
}
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=headers,
|
||||
proxies=proxy
|
||||
).get_res(url="https://club.hares.top/attendance.php?action=sign")
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,签到接口请求失败'
|
||||
|
||||
# {"code":1,"msg":"您今天已经签到过了"}
|
||||
# {"code":0,"msg":"签到成功"}
|
||||
sign_dict = json.loads(sign_res.text)
|
||||
if sign_dict['code'] == 0:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
else:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
69
app/plugins/autosignin/sites/hdarea.py
Normal file
69
app/plugins/autosignin/sites/hdarea.py
Normal file
@@ -0,0 +1,69 @@
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class HDArea(_ISiteSigninHandler):
|
||||
"""
|
||||
好大签到
|
||||
"""
|
||||
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "hdarea.co"
|
||||
|
||||
# 签到成功
|
||||
_success_text = "此次签到您获得"
|
||||
_repeat_text = "请不要重复签到哦"
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 获取页面html
|
||||
data = {
|
||||
'action': 'sign_in'
|
||||
}
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url="https://www.hdarea.co/sign_in.php", data=data)
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in html_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
# 判断是否已签到
|
||||
# '已连续签到278天,此次签到您获得了100魔力值奖励!'
|
||||
if self._success_text in html_res.text:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
if self._repeat_text in html_res.text:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
logger.error(f"签到失败,签到接口返回 {html_res.text}")
|
||||
return False, f'【{site}】签到失败'
|
||||
117
app/plugins/autosignin/sites/hdchina.py
Normal file
117
app/plugins/autosignin/sites/hdchina.py
Normal file
@@ -0,0 +1,117 @@
|
||||
import json
|
||||
from typing import Tuple
|
||||
|
||||
from lxml import etree
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class HDChina(_ISiteSigninHandler):
|
||||
"""
|
||||
瓷器签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "hdchina.org"
|
||||
|
||||
# 已签到
|
||||
_sign_regex = ['<a class="label label-default" href="#">已签到</a>']
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 尝试解决瓷器cookie每天签到后过期,只保留hdchina=部分
|
||||
cookie = ""
|
||||
# 按照分号进行字符串拆分
|
||||
sub_strs = site_cookie.split(";")
|
||||
# 遍历每个子字符串
|
||||
for sub_str in sub_strs:
|
||||
if "hdchina=" in sub_str:
|
||||
# 如果子字符串包含"hdchina=",则保留该子字符串
|
||||
cookie += sub_str + ";"
|
||||
|
||||
if "hdchina=" not in cookie:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
site_cookie = cookie
|
||||
# 获取页面html
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://hdchina.org/index.php")
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in html_res.text or "阻断页面" in html_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
# 获取新返回的cookie进行签到
|
||||
site_cookie = ';'.join(['{}={}'.format(k, v) for k, v in html_res.cookies.get_dict().items()])
|
||||
|
||||
# 判断是否已签到
|
||||
html_res.encoding = "utf-8"
|
||||
sign_status = self.sign_in_result(html_res=html_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 没有签到则解析html
|
||||
html = etree.HTML(html_res.text)
|
||||
|
||||
if not html:
|
||||
return False, f'【{site}】签到失败'
|
||||
|
||||
# x_csrf
|
||||
x_csrf = html.xpath("//meta[@name='x-csrf']/@content")[0]
|
||||
if not x_csrf:
|
||||
logger.error("签到失败,获取x-csrf失败")
|
||||
return False, f'【{site}】签到失败'
|
||||
logger.debug(f"获取到x-csrf {x_csrf}")
|
||||
|
||||
# 签到
|
||||
data = {
|
||||
'csrf': x_csrf
|
||||
}
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url="https://hdchina.org/plugin_sign-in.php?cmd=signin", data=data)
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,签到接口请求失败'
|
||||
|
||||
sign_dict = json.loads(sign_res.text)
|
||||
logger.debug(f"签到返回结果 {sign_dict}")
|
||||
if sign_dict['state']:
|
||||
# {'state': 'success', 'signindays': 10, 'integral': 20}
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
else:
|
||||
# {'state': False, 'msg': '不正确的CSRF / Incorrect CSRF token'}
|
||||
logger.error(f"签到失败,不正确的CSRF / Incorrect CSRF token")
|
||||
return False, f'【{site}】签到失败'
|
||||
66
app/plugins/autosignin/sites/hdcity.py
Normal file
66
app/plugins/autosignin/sites/hdcity.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class HDCity(_ISiteSigninHandler):
|
||||
"""
|
||||
城市签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "hdcity.city"
|
||||
|
||||
# 签到成功
|
||||
_success_text = '本次签到获得魅力'
|
||||
# 重复签到
|
||||
_repeat_text = '已签到'
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 获取页面html
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://hdcity.city/sign")
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login" in html_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
# 判断是否已签到
|
||||
# '已连续签到278天,此次签到您获得了100魔力值奖励!'
|
||||
if self._success_text in html_res.text:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
if self._repeat_text in html_res.text:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
logger.error(f"签到失败,签到接口返回 {html_res.text}")
|
||||
return False, f'【{site}】签到失败'
|
||||
131
app/plugins/autosignin/sites/hdsky.py
Normal file
131
app/plugins/autosignin/sites/hdsky.py
Normal file
@@ -0,0 +1,131 @@
|
||||
import json
|
||||
import time
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.helper.ocr import OcrHelper
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class HDSky(_ISiteSigninHandler):
|
||||
"""
|
||||
天空ocr签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "hdsky.me"
|
||||
|
||||
# 已签到
|
||||
_sign_regex = ['已签到']
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 判断今日是否已签到
|
||||
index_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url='https://hdsky.me')
|
||||
if not index_res or index_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in index_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
sign_status = self.sign_in_result(html_res=index_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 获取验证码请求,考虑到网络问题获取失败,多获取几次试试
|
||||
res_times = 0
|
||||
img_hash = None
|
||||
while not img_hash and res_times <= 3:
|
||||
image_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url='https://hdsky.me/image_code_ajax.php',
|
||||
data={'action': 'new'})
|
||||
if image_res and image_res.status_code == 200:
|
||||
image_json = json.loads(image_res.text)
|
||||
if image_json["success"]:
|
||||
img_hash = image_json["code"]
|
||||
break
|
||||
res_times += 1
|
||||
logger.debug(f"获取{site}验证码失败,正在进行重试,目前重试次数 {res_times}")
|
||||
time.sleep(1)
|
||||
|
||||
# 获取到二维码hash
|
||||
if img_hash:
|
||||
# 完整验证码url
|
||||
img_get_url = 'https://hdsky.me/image.php?action=regimage&imagehash=%s' % img_hash
|
||||
logger.debug(f"获取到{site}验证码链接 {img_get_url}")
|
||||
# ocr识别多次,获取6位验证码
|
||||
times = 0
|
||||
ocr_result = None
|
||||
# 识别几次
|
||||
while times <= 3:
|
||||
# ocr二维码识别
|
||||
ocr_result = OcrHelper().get_captcha_text(image_url=img_get_url,
|
||||
cookie=site_cookie,
|
||||
ua=ua)
|
||||
logger.debug(f"ocr识别{site}验证码 {ocr_result}")
|
||||
if ocr_result:
|
||||
if len(ocr_result) == 6:
|
||||
logger.info(f"ocr识别{site}验证码成功 {ocr_result}")
|
||||
break
|
||||
times += 1
|
||||
logger.debug(f"ocr识别{site}验证码失败,正在进行重试,目前重试次数 {times}")
|
||||
time.sleep(1)
|
||||
|
||||
if ocr_result:
|
||||
# 组装请求参数
|
||||
data = {
|
||||
'action': 'showup',
|
||||
'imagehash': img_hash,
|
||||
'imagestring': ocr_result
|
||||
}
|
||||
# 访问签到链接
|
||||
res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url='https://hdsky.me/showup.php', data=data)
|
||||
if res and res.status_code == 200:
|
||||
if json.loads(res.text)["success"]:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
elif str(json.loads(res.text)["message"]) == "date_unmatch":
|
||||
# 重复签到
|
||||
logger.warn(f"重复成功")
|
||||
return True, f'【{site}】今日已签到'
|
||||
elif str(json.loads(res.text)["message"]) == "invalid_imagehash":
|
||||
# 验证码错误
|
||||
logger.warn(f"签到失败:验证码错误")
|
||||
return False, f'【{site}】签到失败:验证码错误'
|
||||
|
||||
logger.error(f'签到失败:未获取到验证码')
|
||||
return False, f'【{site}】签到失败:未获取到验证码'
|
||||
81
app/plugins/autosignin/sites/hdupt.py
Normal file
81
app/plugins/autosignin/sites/hdupt.py
Normal file
@@ -0,0 +1,81 @@
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class HDUpt(_ISiteSigninHandler):
|
||||
"""
|
||||
hdu签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "pt.hdupt.com"
|
||||
|
||||
# 已签到
|
||||
_sign_regex = ['<span id="yiqiandao">']
|
||||
|
||||
# 签到成功
|
||||
_success_text = '本次签到获得魅力'
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 获取页面html
|
||||
index_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://pt.hdupt.com")
|
||||
if not index_res or index_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in index_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
sign_status = self.sign_in_result(html_res=index_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 签到
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url="https://pt.hdupt.com/added.php?action=qiandao")
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
logger.debug(f"签到接口返回 {sign_res.text}")
|
||||
# 判断是否已签到 sign_res.text = ".23"
|
||||
if len(list(map(int, re.findall(r"\d+", sign_res.text)))) > 0:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
|
||||
logger.error(f"签到失败,签到接口返回 {sign_res.text}")
|
||||
return False, f'【{site}】签到失败'
|
||||
129
app/plugins/autosignin/sites/opencd.py
Normal file
129
app/plugins/autosignin/sites/opencd.py
Normal file
@@ -0,0 +1,129 @@
|
||||
import json
|
||||
import time
|
||||
from typing import Tuple
|
||||
|
||||
from lxml import etree
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.helper.ocr import OcrHelper
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class Opencd(_ISiteSigninHandler):
|
||||
"""
|
||||
皇后ocr签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "open.cd"
|
||||
|
||||
# 已签到
|
||||
_repeat_text = "/plugin_sign-in.php?cmd=show-log"
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 判断今日是否已签到
|
||||
index_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url='https://www.open.cd')
|
||||
if not index_res or index_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in index_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
if self._repeat_text in index_res.text:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 获取签到参数
|
||||
sign_param_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url='https://www.open.cd/plugin_sign-in.php')
|
||||
if not sign_param_res or sign_param_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
# 没有签到则解析html
|
||||
html = etree.HTML(sign_param_res.text)
|
||||
if not html:
|
||||
return False, f'【{site}】签到失败'
|
||||
|
||||
# 签到参数
|
||||
img_url = html.xpath('//form[@id="frmSignin"]//img/@src')[0]
|
||||
img_hash = html.xpath('//form[@id="frmSignin"]//input[@name="imagehash"]/@value')[0]
|
||||
if not img_url or not img_hash:
|
||||
logger.error(f"签到失败,获取签到参数失败")
|
||||
return False, f'【{site}】签到失败,获取签到参数失败'
|
||||
|
||||
# 完整验证码url
|
||||
img_get_url = 'https://www.open.cd/%s' % img_url
|
||||
logger.debug(f"获取到{site}验证码链接 {img_get_url}")
|
||||
|
||||
# ocr识别多次,获取6位验证码
|
||||
times = 0
|
||||
ocr_result = None
|
||||
# 识别几次
|
||||
while times <= 3:
|
||||
# ocr二维码识别
|
||||
ocr_result = OcrHelper().get_captcha_text(image_url=img_get_url,
|
||||
cookie=site_cookie,
|
||||
ua=ua)
|
||||
logger.debug(f"ocr识别{site}验证码 {ocr_result}")
|
||||
if ocr_result:
|
||||
if len(ocr_result) == 6:
|
||||
logger.info(f"ocr识别{site}验证码成功 {ocr_result}")
|
||||
break
|
||||
times += 1
|
||||
logger.debug(f"ocr识别{site}验证码失败,正在进行重试,目前重试次数 {times}")
|
||||
time.sleep(1)
|
||||
|
||||
if ocr_result:
|
||||
# 组装请求参数
|
||||
data = {
|
||||
'imagehash': img_hash,
|
||||
'imagestring': ocr_result
|
||||
}
|
||||
# 访问签到链接
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url='https://www.open.cd/plugin_sign-in.php?cmd=signin', data=data)
|
||||
if sign_res and sign_res.status_code == 200:
|
||||
logger.debug(f"sign_res返回 {sign_res.text}")
|
||||
# sign_res.text = '{"state":"success","signindays":"0","integral":"10"}'
|
||||
sign_dict = json.loads(sign_res.text)
|
||||
if sign_dict['state']:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
else:
|
||||
logger.error(f"签到失败,签到接口返回 {sign_dict}")
|
||||
return False, f'【{site}】签到失败'
|
||||
|
||||
logger.error(f'签到失败:未获取到验证码')
|
||||
return False, f'【{site}】签到失败:未获取到验证码'
|
||||
58
app/plugins/autosignin/sites/pterclub.py
Normal file
58
app/plugins/autosignin/sites/pterclub.py
Normal file
@@ -0,0 +1,58 @@
|
||||
import json
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class PTerClub(_ISiteSigninHandler):
|
||||
"""
|
||||
猫签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "pterclub.com"
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 签到
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://pterclub.com/attendance-ajax.php")
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,请检查cookie是否失效'
|
||||
|
||||
sign_dict = json.loads(sign_res.text)
|
||||
if sign_dict['status'] == '1':
|
||||
# {"status":"1","data":" (签到已成功300)","message":"<p>这是您的第<b>237</b>次签到,
|
||||
# 已连续签到<b>237</b>天。</p><p>本次签到获得<b>300</b>克猫粮。</p>"}
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
else:
|
||||
# {"status":"0","data":"抱歉","message":"您今天已经签到过了,请勿重复刷新。"}
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
272
app/plugins/autosignin/sites/tjupt.py
Normal file
272
app/plugins/autosignin/sites/tjupt.py
Normal file
@@ -0,0 +1,272 @@
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
from io import BytesIO
|
||||
from typing import Tuple
|
||||
|
||||
from PIL import Image
|
||||
from lxml import etree
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class Tjupt(_ISiteSigninHandler):
|
||||
"""
|
||||
北洋签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "tjupt.org"
|
||||
|
||||
# 签到地址
|
||||
_sign_in_url = 'https://www.tjupt.org/attendance.php'
|
||||
|
||||
# 已签到
|
||||
_sign_regex = ['<a href="attendance.php">今日已签到</a>']
|
||||
|
||||
# 签到成功
|
||||
_succeed_regex = ['这是您的首次签到,本次签到获得\\d+个魔力值。',
|
||||
'签到成功,这是您的第\\d+次签到,已连续签到\\d+天,本次签到获得\\d+个魔力值。',
|
||||
'重新签到成功,本次签到获得\\d+个魔力值']
|
||||
|
||||
# 存储正确的答案,后续可直接查
|
||||
_answer_path = settings.TEMP_PATH / "signin/"
|
||||
_answer_file = _answer_path / "tjupt.json"
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 创建正确答案存储目录
|
||||
if not os.path.exists(os.path.dirname(self._answer_file)):
|
||||
os.makedirs(os.path.dirname(self._answer_file))
|
||||
|
||||
# 获取北洋签到页面html
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url=self._sign_in_url)
|
||||
|
||||
# 获取签到后返回html,判断是否签到成功
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in html_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
sign_status = self.sign_in_result(html_res=html_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 没有签到则解析html
|
||||
html = etree.HTML(html_res.text)
|
||||
if not html:
|
||||
return False, f'【{site}】签到失败'
|
||||
img_url = html.xpath('//table[@class="captcha"]//img/@src')[0]
|
||||
|
||||
if not img_url:
|
||||
logger.error(f"签到失败,未获取到签到图片")
|
||||
return False, f'【{site}】签到失败,未获取到签到图片'
|
||||
|
||||
# 签到图片
|
||||
img_url = "https://www.tjupt.org" + img_url
|
||||
logger.info(f"获取到签到图片 {img_url}")
|
||||
# 获取签到图片hash
|
||||
captcha_img_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url=img_url)
|
||||
if not captcha_img_res or captcha_img_res.status_code != 200:
|
||||
logger.error(f"签到图片 {img_url} 请求失败")
|
||||
return False, f'【{site}】签到失败,未获取到签到图片'
|
||||
captcha_img = Image.open(BytesIO(captcha_img_res.content))
|
||||
captcha_img_hash = self._tohash(captcha_img)
|
||||
logger.debug(f"签到图片hash {captcha_img_hash}")
|
||||
|
||||
# 签到答案选项
|
||||
values = html.xpath("//input[@name='answer']/@value")
|
||||
options = html.xpath("//input[@name='answer']/following-sibling::text()")
|
||||
|
||||
if not values or not options:
|
||||
logger.error(f"签到失败,未获取到答案选项")
|
||||
return False, f'【{site}】签到失败,未获取到答案选项'
|
||||
|
||||
# value+选项
|
||||
answers = list(zip(values, options))
|
||||
logger.debug(f"获取到所有签到选项 {answers}")
|
||||
|
||||
# 查询已有答案
|
||||
exits_answers = {}
|
||||
try:
|
||||
with open(self._answer_file, 'r') as f:
|
||||
json_str = f.read()
|
||||
exits_answers = json.loads(json_str)
|
||||
# 查询本地本次验证码hash答案
|
||||
captcha_answer = exits_answers[captcha_img_hash]
|
||||
|
||||
# 本地存在本次hash对应的正确答案再遍历查询
|
||||
if captcha_answer:
|
||||
for value, answer in answers:
|
||||
if str(captcha_answer) == str(answer):
|
||||
# 确实是答案
|
||||
return self.__signin(answer=value,
|
||||
site_cookie=site_cookie,
|
||||
ua=ua,
|
||||
proxy=proxy,
|
||||
site=site)
|
||||
except (FileNotFoundError, IOError, OSError) as e:
|
||||
logger.debug(f"查询本地已知答案失败:{e},继续请求豆瓣查询")
|
||||
|
||||
# 本地不存在正确答案则请求豆瓣查询匹配
|
||||
for value, answer in answers:
|
||||
if answer:
|
||||
# 豆瓣检索
|
||||
db_res = RequestUtils().get_res(url=f'https://movie.douban.com/j/subject_suggest?q={answer}')
|
||||
if not db_res or db_res.status_code != 200:
|
||||
logger.debug(f"签到选项 {answer} 未查询到豆瓣数据")
|
||||
continue
|
||||
|
||||
# 豆瓣返回结果
|
||||
db_answers = json.loads(db_res.text)
|
||||
if not isinstance(db_answers, list):
|
||||
db_answers = [db_answers]
|
||||
|
||||
if len(db_answers) == 0:
|
||||
logger.debug(f"签到选项 {answer} 查询到豆瓣数据为空")
|
||||
|
||||
for db_answer in db_answers:
|
||||
answer_img_url = db_answer['img']
|
||||
|
||||
# 获取答案hash
|
||||
answer_img_res = RequestUtils().get_res(url=answer_img_url)
|
||||
if not answer_img_res or answer_img_res.status_code != 200:
|
||||
logger.debug(f"签到答案 {answer} {answer_img_url} 请求失败")
|
||||
continue
|
||||
|
||||
answer_img = Image.open(BytesIO(answer_img_res.content))
|
||||
answer_img_hash = self._tohash(answer_img)
|
||||
logger.debug(f"签到答案图片hash {answer} {answer_img_hash}")
|
||||
|
||||
# 获取选项图片与签到图片相似度,大于0.9默认是正确答案
|
||||
score = self._comparehash(captcha_img_hash, answer_img_hash)
|
||||
logger.info(f"签到图片与选项 {answer} 豆瓣图片相似度 {score}")
|
||||
if score > 0.9:
|
||||
# 确实是答案
|
||||
return self.__signin(answer=value,
|
||||
site_cookie=site_cookie,
|
||||
ua=ua,
|
||||
proxy=proxy,
|
||||
site=site,
|
||||
exits_answers=exits_answers,
|
||||
captcha_img_hash=captcha_img_hash)
|
||||
|
||||
# 间隔5s,防止请求太频繁被豆瓣屏蔽ip
|
||||
time.sleep(5)
|
||||
logger.error(f"豆瓣图片匹配,未获取到匹配答案")
|
||||
|
||||
# 没有匹配签到成功,则签到失败
|
||||
return False, f'【{site}】签到失败,未获取到匹配答案'
|
||||
|
||||
def __signin(self, answer, site_cookie, ua, proxy, site, exits_answers=None, captcha_img_hash=None):
|
||||
"""
|
||||
签到请求
|
||||
"""
|
||||
data = {
|
||||
'answer': answer,
|
||||
'submit': '提交'
|
||||
}
|
||||
logger.debug(f"提交data {data}")
|
||||
sign_in_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url=self._sign_in_url, data=data)
|
||||
if not sign_in_res or sign_in_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,签到接口请求失败'
|
||||
|
||||
# 获取签到后返回html,判断是否签到成功
|
||||
sign_status = self.sign_in_result(html_res=sign_in_res.text,
|
||||
regexs=self._succeed_regex)
|
||||
if sign_status:
|
||||
logger.info(f"签到成功")
|
||||
if exits_answers and captcha_img_hash:
|
||||
# 签到成功写入本地文件
|
||||
self.__write_local_answer(exits_answers=exits_answers or {},
|
||||
captcha_img_hash=captcha_img_hash,
|
||||
answer=answer)
|
||||
return True, f'【{site}】签到成功'
|
||||
else:
|
||||
logger.error(f"签到失败,请到页面查看")
|
||||
return False, f'【{site}】签到失败,请到页面查看'
|
||||
|
||||
def __write_local_answer(self, exits_answers, captcha_img_hash, answer):
|
||||
"""
|
||||
签到成功写入本地文件
|
||||
"""
|
||||
try:
|
||||
exits_answers[captcha_img_hash] = answer
|
||||
# 序列化数据
|
||||
formatted_data = json.dumps(exits_answers, indent=4)
|
||||
with open(self._answer_file, 'w') as f:
|
||||
f.write(formatted_data)
|
||||
except (FileNotFoundError, IOError, OSError) as e:
|
||||
logger.debug(f"签到成功写入本地文件失败:{e}")
|
||||
|
||||
@staticmethod
|
||||
def _tohash(img, shape=(10, 10)):
|
||||
"""
|
||||
获取图片hash
|
||||
"""
|
||||
img = img.resize(shape)
|
||||
gray = img.convert('L')
|
||||
s = 0
|
||||
hash_str = ''
|
||||
for i in range(shape[1]):
|
||||
for j in range(shape[0]):
|
||||
s = s + gray.getpixel((j, i))
|
||||
avg = s / (shape[0] * shape[1])
|
||||
for i in range(shape[1]):
|
||||
for j in range(shape[0]):
|
||||
if gray.getpixel((j, i)) > avg:
|
||||
hash_str = hash_str + '1'
|
||||
else:
|
||||
hash_str = hash_str + '0'
|
||||
return hash_str
|
||||
|
||||
@staticmethod
|
||||
def _comparehash(hash1, hash2, shape=(10, 10)):
|
||||
"""
|
||||
比较图片hash
|
||||
返回相似度
|
||||
"""
|
||||
n = 0
|
||||
if len(hash1) != len(hash2):
|
||||
return -1
|
||||
for i in range(len(hash1)):
|
||||
if hash1[i] == hash2[i]:
|
||||
n = n + 1
|
||||
return n / (shape[0] * shape[1])
|
||||
96
app/plugins/autosignin/sites/ttg.py
Normal file
96
app/plugins/autosignin/sites/ttg.py
Normal file
@@ -0,0 +1,96 @@
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class TTG(_ISiteSigninHandler):
|
||||
"""
|
||||
TTG签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "totheglory.im"
|
||||
|
||||
# 已签到
|
||||
_sign_regex = ['<b style="color:green;">已签到</b>']
|
||||
_sign_text = '亲,您今天已签到过,不要太贪哦'
|
||||
|
||||
# 签到成功
|
||||
_success_text = '您已连续签到'
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 获取页面html
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://totheglory.im")
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in html_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
# 判断是否已签到
|
||||
html_res.encoding = "utf-8"
|
||||
sign_status = self.sign_in_result(html_res=html_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 获取签到参数
|
||||
signed_timestamp = re.search('(?<=signed_timestamp: ")\\d{10}', html_res.text).group()
|
||||
signed_token = re.search('(?<=signed_token: ").*(?=")', html_res.text).group()
|
||||
logger.debug(f"signed_timestamp={signed_timestamp} signed_token={signed_token}")
|
||||
|
||||
data = {
|
||||
'signed_timestamp': signed_timestamp,
|
||||
'signed_token': signed_token
|
||||
}
|
||||
# 签到
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url="https://totheglory.im/signed.php",
|
||||
data=data)
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,签到接口请求失败'
|
||||
|
||||
sign_res.encoding = "utf-8"
|
||||
if self._success_text in sign_res.text:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
if self._sign_text in sign_res.text:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
logger.error(f"签到失败,未知原因")
|
||||
return False, f'【{site}】签到失败,未知原因'
|
||||
122
app/plugins/autosignin/sites/u2.py
Normal file
122
app/plugins/autosignin/sites/u2.py
Normal file
@@ -0,0 +1,122 @@
|
||||
import datetime
|
||||
import random
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
from lxml import etree
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class U2(_ISiteSigninHandler):
|
||||
"""
|
||||
U2签到 随机
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "u2.dmhy.org"
|
||||
|
||||
# 已签到
|
||||
_sign_regex = ['<a href="showup.php">已签到</a>',
|
||||
'<a href="showup.php">Show Up</a>',
|
||||
'<a href="showup.php">Показать</a>',
|
||||
'<a href="showup.php">已簽到</a>',
|
||||
'<a href="showup.php">已簽到</a>']
|
||||
|
||||
# 签到成功
|
||||
_success_text = "window.location.href = 'showup.php';</script>"
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
now = datetime.datetime.now()
|
||||
# 判断当前时间是否小于9点
|
||||
if now.hour < 9:
|
||||
logger.error(f"签到失败,9点前不签到")
|
||||
return False, f'【{site}】签到失败,9点前不签到'
|
||||
|
||||
# 获取页面html
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://u2.dmhy.org/showup.php")
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"签到失败,请检查站点连通性")
|
||||
return False, f'【{site}】签到失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in html_res.text:
|
||||
logger.error(f"签到失败,cookie失效")
|
||||
return False, f'【{site}】签到失败,cookie失效'
|
||||
|
||||
# 判断是否已签到
|
||||
html_res.encoding = "utf-8"
|
||||
sign_status = self.sign_in_result(html_res=html_res.text,
|
||||
regexs=self._sign_regex)
|
||||
if sign_status:
|
||||
logger.info(f"今日已签到")
|
||||
return True, f'【{site}】今日已签到'
|
||||
|
||||
# 没有签到则解析html
|
||||
html = etree.HTML(html_res.text)
|
||||
|
||||
if not html:
|
||||
return False, f'【{site}】签到失败'
|
||||
|
||||
# 获取签到参数
|
||||
req = html.xpath("//form//td/input[@name='req']/@value")[0]
|
||||
hash_str = html.xpath("//form//td/input[@name='hash']/@value")[0]
|
||||
form = html.xpath("//form//td/input[@name='form']/@value")[0]
|
||||
submit_name = html.xpath("//form//td/input[@type='submit']/@name")
|
||||
submit_value = html.xpath("//form//td/input[@type='submit']/@value")
|
||||
if not re or not hash_str or not form or not submit_name or not submit_value:
|
||||
logger.error("签到失败,未获取到相关签到参数")
|
||||
return False, f'【{site}】签到失败'
|
||||
|
||||
# 随机一个答案
|
||||
answer_num = random.randint(0, 3)
|
||||
data = {
|
||||
'req': req,
|
||||
'hash': hash_str,
|
||||
'form': form,
|
||||
'message': '一切随缘~',
|
||||
submit_name[answer_num]: submit_value[answer_num]
|
||||
}
|
||||
# 签到
|
||||
sign_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).post_res(url="https://u2.dmhy.org/showup.php?action=show",
|
||||
data=data)
|
||||
if not sign_res or sign_res.status_code != 200:
|
||||
logger.error(f"签到失败,签到接口请求失败")
|
||||
return False, f'【{site}】签到失败,签到接口请求失败'
|
||||
|
||||
# 判断是否签到成功
|
||||
# sign_res.text = "<script type="text/javascript">window.location.href = 'showup.php';</script>"
|
||||
if self._success_text in sign_res.text:
|
||||
logger.info(f"签到成功")
|
||||
return True, f'【{site}】签到成功'
|
||||
else:
|
||||
logger.error(f"签到失败,未知原因")
|
||||
return False, f'【{site}】签到失败,未知原因'
|
||||
86
app/plugins/autosignin/sites/zhuque.py
Normal file
86
app/plugins/autosignin/sites/zhuque.py
Normal file
@@ -0,0 +1,86 @@
|
||||
import json
|
||||
from typing import Tuple
|
||||
|
||||
from lxml import etree
|
||||
from ruamel.yaml import CommentedMap
|
||||
|
||||
from app.core import settings
|
||||
from app.log import logger
|
||||
from app.plugins.autosignin.sites import _ISiteSigninHandler
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class ZhuQue(_ISiteSigninHandler):
|
||||
"""
|
||||
ZHUQUE签到
|
||||
"""
|
||||
# 匹配的站点Url,每一个实现类都需要设置为自己的站点Url
|
||||
site_url = "zhuque.in"
|
||||
|
||||
@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")
|
||||
site_cookie = site_info.get("cookie")
|
||||
ua = site_info.get("ua")
|
||||
proxy = settings.PROXY if site_info.get("proxy") else None
|
||||
|
||||
# 获取页面html
|
||||
html_res = RequestUtils(cookies=site_cookie,
|
||||
headers=ua,
|
||||
proxies=proxy
|
||||
).get_res(url="https://zhuque.in")
|
||||
if not html_res or html_res.status_code != 200:
|
||||
logger.error(f"模拟登录失败,请检查站点连通性")
|
||||
return False, f'【{site}】模拟登录失败,请检查站点连通性'
|
||||
|
||||
if "login.php" in html_res.text:
|
||||
logger.error(f"模拟登录失败,cookie失效")
|
||||
return False, f'【{site}】模拟登录失败,cookie失效'
|
||||
|
||||
html = etree.HTML(html_res.text)
|
||||
|
||||
if not html:
|
||||
return False, f'【{site}】模拟登录失败'
|
||||
|
||||
# 释放技能
|
||||
msg = '失败'
|
||||
x_csrf_token = html.xpath("//meta[@name='x-csrf-token']/@content")[0]
|
||||
if x_csrf_token:
|
||||
data = {
|
||||
"all": 1,
|
||||
"resetModal": "true"
|
||||
}
|
||||
headers = {
|
||||
"x-csrf-token": str(x_csrf_token),
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
"User-Agent": ua
|
||||
}
|
||||
skill_res = RequestUtils(cookies=site_cookie,
|
||||
headers=headers,
|
||||
proxies=proxy
|
||||
).post_res(url="https://zhuque.in/api/gaming/fireGenshinCharacterMagic", json=data)
|
||||
if not skill_res or skill_res.status_code != 200:
|
||||
logger.error(f"模拟登录失败,释放技能失败")
|
||||
|
||||
# '{"status":200,"data":{"code":"FIRE_GENSHIN_CHARACTER_MAGIC_SUCCESS","bonus":0}}'
|
||||
skill_dict = json.loads(skill_res.text)
|
||||
if skill_dict['status'] == 200:
|
||||
bonus = int(skill_dict['data']['bonus'])
|
||||
msg = f'成功,获得{bonus}魔力'
|
||||
|
||||
logger.info(f'【{site}】模拟登录成功,技能释放{msg}')
|
||||
return True, f'【{site}】模拟登录成功,技能释放{msg}'
|
||||
Reference in New Issue
Block a user