Merge branch 'Womsxd:master' into master

This commit is contained in:
hinak0 2022-10-21 08:32:02 +08:00 committed by GitHub
commit 5e297cf252
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 193 additions and 50 deletions

View File

@ -180,6 +180,54 @@ docker-compose pull && docker-compose up -d
2. 点击`测试函数` 2. 点击`测试函数`
7. 完成 7. 完成
## 使用青龙面板运行V2.12+
### 1.拉取仓库
方式1订阅管理
```
名称:米游社签到
类型:公开仓库
链接https://github.com/Womsxd/AutoMihoyoBBS.git
定时类型crontab
定时规则2 2 28 * *
白名单ql_main.py
依赖文件error|mihoyo|genshin|honkai3rd|log|push|req|set|tools|con|acc|honkai2|tearsofthemis|captcha|main
```
方式2指令拉取
```sh
ql repo https://github.com/Womsxd/AutoMihoyoBBS.git "ql_main.py" "" "error|mihoyo|genshin|honkai3rd|log|push|req|set|tools|con|acc|honkai2|tearsofthemis|captcha|main"
```
### 2.环境变量添加
在config.sh中添加
```sh
export AutoMihoyoBBS_config_path="/ql/data/config/"
```
### 3.复制配置文件
**进入容器后运行以下命令**docker exec -it ql bash修改ql为你的青龙容器名字
```sh
cp /ql/data/repo/Womsxd_AutoMihoyoBBS/config/config.yaml.example /ql/data/config/config.yaml
```
### 4.添加依赖
在青龙面板依赖管理中添加httpx及PyYAML
### 5.编辑配置文件
在配置文件内config.yaml中编辑信息
*注通知配置为青龙config.sh中配置*
## 使用的第三方库 ## 使用的第三方库
requests: [github](https://github.com/psf/requests) [pypi](https://pypi.org/project/requests/) (当httpx无法使用时使用) requests: [github](https://github.com/psf/requests) [pypi](https://pypi.org/project/requests/) (当httpx无法使用时使用)

9
captcha.py Normal file
View File

@ -0,0 +1,9 @@
from request import http
def game_captcha(gt: str, challenge: str):
return None # 失败返回None 成功返回validate
def bbs_captcha(gt: str, challenge: str):
return None

View File

@ -25,9 +25,9 @@ class CloudGenshin:
} }
# 分钟转小时 # 分钟转小时
def time_conversion(self,minute : int) -> str: def time_conversion(self, minute: int) -> str:
h = minute//60 h = minute // 60
s = minute%60 s = minute % 60
return f"{h}小时{s}分钟" return f"{h}小时{s}分钟"
def sign_account(self) -> str: def sign_account(self) -> str:
@ -42,7 +42,7 @@ class CloudGenshin:
log.info('签到失败,未获得免费时长,可能是已经签到过了或者超出免费时长上线') log.info('签到失败,未获得免费时长,可能是已经签到过了或者超出免费时长上线')
ret_msg += '签到失败,未获得免费时长,可能是已经签到过了或者超出免费时长上线\n' ret_msg += '签到失败,未获得免费时长,可能是已经签到过了或者超出免费时长上线\n'
ret_msg += f'你当前拥有免费时长 {self.time_conversion(int(data["data"]["free_time"]["free_time"]))} ,' \ ret_msg += f'你当前拥有免费时长 {self.time_conversion(int(data["data"]["free_time"]["free_time"]))} ,' \
f'畅玩卡状态为 {data["data"]["play_card"]["short_msg"]},拥有米云币 {data["data"]["coin"]["coin_num"]}' f'畅玩卡状态为 {data["data"]["play_card"]["short_msg"]},拥有米云币 {data["data"]["coin"]["coin_num"]}'
log.info(ret_msg) log.info(ret_msg)
elif data['retcode'] == -100: elif data['retcode'] == -100:
ret_msg = "云原神token失效/防沉迷" ret_msg = "云原神token失效/防沉迷"

View File

@ -42,6 +42,8 @@ config = {
} }
} }
} }
config_raw = {}
config_raw.update(config)
path = os.path.dirname(os.path.realpath(__file__)) + "/config" path = os.path.dirname(os.path.realpath(__file__)) + "/config"
if os.getenv("AutoMihoyoBBS_config_path") is not None: if os.getenv("AutoMihoyoBBS_config_path") is not None:
@ -51,7 +53,7 @@ config_Path = f"{path}/config.yaml"
def copy_config(): def copy_config():
return config return config_raw
def load_config_json(): def load_config_json():

View File

@ -1,9 +1,9 @@
[setting] [setting]
enable=true enable=true
#共有 cqhttp ftqq(sever酱) pushplus telegram wecom dingrobot bark pushdeer gotify smtp(邮件推送) # 共有 cqhttp ftqq(sever酱) pushplus telegram wecom dingrobot feishubot bark pushdeer gotify smtp(邮件推送)
push_server=cqhttp push_server=pushplus
#server酱 pushplus dingrobot 的推送token # server酱 pushplus dingrobot 的推送token
push_token=123456 push_token=XXXXXX
[cqhttp] [cqhttp]
#cqhttp的服务端地址 #cqhttp的服务端地址
@ -32,6 +32,9 @@ token=
webhook=https://oapi.dingtalk.com/robot/send?access_token=XXX webhook=https://oapi.dingtalk.com/robot/send?access_token=XXX
secret= secret=
[feishubot]
webhook=https://open.feishu.cn/open-apis/bot/v2/hook/XXX
[bark] [bark]
api_url=https://api.day.app api_url=https://api.day.app
token=ssXXX token=ssXXX

View File

@ -2,6 +2,7 @@ import time
import tools import tools
import config import config
import random import random
import captcha
import setting import setting
from error import * from error import *
from request import http from request import http
@ -46,10 +47,12 @@ class Genshin:
return data["data"] return data["data"]
def check_in(self, account): def check_in(self, account):
header = {}
header.update(self.headers)
for i in range(4): for i in range(4):
if i != 0: if i != 0:
log.info(f'触发验证码,即将进行第{i}次重试最多3次') log.info(f'触发验证码,即将进行第{i}次重试最多3次')
req = http.post(url=setting.genshin_Signurl, headers=self.headers, req = http.post(url=setting.genshin_Signurl, headers=header,
json={'act_id': setting.genshin_Act_id, 'region': account[2], 'uid': account[1]}) json={'act_id': setting.genshin_Act_id, 'region': account[2], 'uid': account[1]})
if req.status_code == 429: if req.status_code == 429:
time.sleep(10) # 429同ip请求次数过多尝试sleep10s进行解决 time.sleep(10) # 429同ip请求次数过多尝试sleep10s进行解决
@ -57,6 +60,11 @@ class Genshin:
continue continue
data = req.json() data = req.json()
if data["retcode"] == 0 and data["data"]["success"] == 1: if data["retcode"] == 0 and data["data"]["success"] == 1:
validate = captcha.game_captcha(data["data"]["gt"], data["data"]["challenge"])
if validate is not None:
header["x-rpc-challenge"] = data["data"]["challenge"]
header["x-rpc-validate"] = validate
header["x-rpc-seccode"] = f'{validate}|jordan'
time.sleep(random.randint(6, 15)) time.sleep(random.randint(6, 15))
else: else:
break break

View File

@ -18,10 +18,10 @@ def login():
config.config["account"]["login_ticket"] = i.split("=")[1] config.config["account"]["login_ticket"] = i.split("=")[1]
break break
# 这里获取Stuid但是实际是可以直接拿cookie里面的Uid # 这里获取Stuid但是实际是可以直接拿cookie里面的Uid
data = http.get(url=setting.bbs_Cookie_url.format(config.config["account"]["login_ticket"])).json() data = http.get(url=setting.bbs_cookie_url.format(config.config["account"]["login_ticket"])).json()
if "成功" in data["data"]["msg"]: if "成功" in data["data"]["msg"]:
config.config["account"]["stuid"] = str(data["data"]["cookie_info"]["account_id"]) config.config["account"]["stuid"] = str(data["data"]["cookie_info"]["account_id"])
data = http.get(url=setting.bbs_Cookie_url2.format( data = http.get(url=setting.bbs_cookie_url2.format(
config.config["account"]["login_ticket"], config.config["account"]["stuid"])).json() config.config["account"]["login_ticket"], config.config["account"]["stuid"])).json()
config.config["account"]["stoken"] = data["data"]["list"][0]["token"] config.config["account"]["stoken"] = data["data"]["list"][0]["token"]
log.info("登录成功!") log.info("登录成功!")

View File

@ -3,6 +3,7 @@ import time
import tools import tools
import config import config
import random import random
import captcha
import setting import setting
from request import http from request import http
from loghelper import log from loghelper import log
@ -47,13 +48,29 @@ class Mihoyobbs:
def refresh_list(self) -> None: def refresh_list(self) -> None:
self.postsList = self.get_list() self.postsList = self.get_list()
def get_pass_challenge(self):
req = http.get(url=setting.bbs_get_captcha, headers=self.headers)
data = req.json()
if data["retcode"] != 0:
return None
validate = captcha.bbs_captcha(data["data"]["gt"], data["data"]["challenge"])
if validate is not None:
check_req = http.post(url=setting.bbs_captcha_verify, headers=self.headers,
json={"geetest_challenge": data["data"]["challenge"],
"geetest_seccode": validate+"|jordan",
"geetest_validate": validate})
check = check_req.json()
if check["retcode"] == 0:
return check["data"]["challenge"]
return None
# 获取任务列表,用来判断做了哪些任务 # 获取任务列表,用来判断做了哪些任务
def get_tasks_list(self): def get_tasks_list(self):
global today_get_coins global today_get_coins
global today_have_get_coins global today_have_get_coins
global Have_coins global Have_coins
log.info("正在获取任务列表") log.info("正在获取任务列表")
req = http.get(url=setting.bbs_Tasks_list, headers=self.headers) req = http.get(url=setting.bbs_tasks_list, headers=self.headers)
data = req.json() data = req.json()
if "err" in data["message"] or data["retcode"] == -100: if "err" in data["message"] or data["retcode"] == -100:
log.error("获取任务列表失败你的cookie可能已过期请重新设置cookie。") log.error("获取任务列表失败你的cookie可能已过期请重新设置cookie。")
@ -104,7 +121,7 @@ class Mihoyobbs:
def get_list(self) -> list: def get_list(self) -> list:
temp_list = [] temp_list = []
log.info("正在获取帖子列表......") log.info("正在获取帖子列表......")
req = http.get(url=setting.bbs_List_url.format(setting.mihoyobbs_List_Use[0]["forumId"]), req = http.get(url=setting.bbs_post_list_url.format(setting.mihoyobbs_List_Use[0]["forumId"]),
headers=self.headers) headers=self.headers)
data = req.json()["data"]["list"] data = req.json()["data"]["list"]
for n in range(5): for n in range(5):
@ -125,17 +142,32 @@ class Mihoyobbs:
log.info("正在签到......") log.info("正在签到......")
header = {} header = {}
header.update(self.headers) header.update(self.headers)
challenge = None
for i in setting.mihoyobbs_List_Use: for i in setting.mihoyobbs_List_Use:
header["DS"] = tools.get_ds2("", json.dumps({"gids": i["id"]})) challenge = None
req = http.post(url=setting.bbs_Sign_url, json={"gids": i["id"]}, headers=header) check_pass = False
data = req.json() for i2 in range(2):
if "err" not in data["message"]: if check_pass:
log.info(str(i["name"] + data["message"])) continue
time.sleep(random.randint(2, 8)) header["DS"] = tools.get_ds2("", json.dumps({"gids": i["id"]}))
else: req = http.post(url=setting.bbs_sign_url, json={"gids": i["id"]}, headers=header)
log.error("签到失败你的cookie可能已过期请重新设置cookie。") data = req.json()
config.clear_cookies() if data["retcode"] == 1034:
raise CookieError('Cookie expires') log.warning("社区签到触发验证码")
challenge = self.get_pass_challenge()
if challenge is not None:
header["x-rpc-challenge"] = challenge
elif "err" not in data["message"] and data["retcode"] == 0:
log.info(str(i["name"] + data["message"]))
check_pass = True
if challenge is not None:
challenge = None
header.pop("x-rpc-challenge")
time.sleep(random.randint(2, 8))
else:
log.error("签到失败你的cookie可能已过期请重新设置cookie。")
config.clear_cookies()
raise CookieError('Cookie expires')
# 看帖子 # 看帖子
def read_posts(self): def read_posts(self):
@ -144,7 +176,7 @@ class Mihoyobbs:
else: else:
log.info("正在看帖......") log.info("正在看帖......")
for i in range(self.Task_do["bbs_Read_posts_num"]): for i in range(self.Task_do["bbs_Read_posts_num"]):
req = http.get(url=setting.bbs_Detail_url.format(self.postsList[i][0]), headers=self.headers) req = http.get(url=setting.bbs_detail_url.format(self.postsList[i][0]), headers=self.headers)
data = req.json() data = req.json()
if data["message"] == "OK": if data["message"] == "OK":
log.debug("看帖:{} 成功".format(self.postsList[i][1])) log.debug("看帖:{} 成功".format(self.postsList[i][1]))
@ -152,20 +184,31 @@ class Mihoyobbs:
# 点赞 # 点赞
def like_posts(self): def like_posts(self):
header = {}
header.update(self.headers)
challenge = None
if self.Task_do["bbs_Like_posts"]: if self.Task_do["bbs_Like_posts"]:
log.info("点赞任务已经完成过了~") log.info("点赞任务已经完成过了~")
else: else:
log.info("正在点赞......") log.info("正在点赞......")
for i in range(self.Task_do["bbs_Like_posts_num"]): for i in range(self.Task_do["bbs_Like_posts_num"]):
req = http.post(url=setting.bbs_Like_url, headers=self.headers, req = http.post(url=setting.bbs_like_url, headers=header,
json={"post_id": self.postsList[i][0], "is_cancel": False}) json={"post_id": self.postsList[i][0], "is_cancel": False})
data = req.json() data = req.json()
if data["message"] == "OK": if data["message"] == "OK":
log.debug("点赞:{} 成功".format(self.postsList[i][1])) log.debug("点赞:{} 成功".format(self.postsList[i][1]))
# 判断取消点赞是否打开 if challenge is not None:
challenge = None
header.pop("x-rpc-challenge")
elif data["retcode"] == 1034:
log.warning("点赞触发验证码")
challenge = self.get_pass_challenge()
if challenge is not None:
header["x-rpc-challenge"] = challenge
# 判断取消点赞是否打开
if config.config["mihoyobbs"]["cancel_like_posts"]: if config.config["mihoyobbs"]["cancel_like_posts"]:
time.sleep(random.randint(2, 8)) time.sleep(random.randint(2, 8))
req = http.post(url=setting.bbs_Like_url, headers=self.headers, req = http.post(url=setting.bbs_like_url, headers=self.headers,
json={"post_id": self.postsList[i][0], "is_cancel": True}) json={"post_id": self.postsList[i][0], "is_cancel": True})
data = req.json() data = req.json()
if data["message"] == "OK": if data["message"] == "OK":
@ -180,7 +223,7 @@ class Mihoyobbs:
else: else:
log.info("正在执行分享任务......") log.info("正在执行分享任务......")
for i in range(3): for i in range(3):
req = http.get(url=setting.bbs_Share_url.format(self.postsList[0][0]), headers=self.headers) req = http.get(url=setting.bbs_share_url.format(self.postsList[0][0]), headers=self.headers)
data = req.json() data = req.json()
if data["message"] == "OK": if data["message"] == "OK":
log.debug("分享:{} 成功".format(self.postsList[0][1])) log.debug("分享:{} 成功".format(self.postsList[0][1]))

11
push.py
View File

@ -170,6 +170,17 @@ def dingrobot(send_title, push_message):
).json() ).json()
log.info(f"推送结果:{rep.get('errmsg')}") log.info(f"推送结果:{rep.get('errmsg')}")
# 飞书机器人
def feishubot(send_title, push_message):
api_url = cfg.get('feishubot', 'webhook') # https://open.feishu.cn/open-apis/bot/v2/hook/XXX
rep = http.post(
url=api_url,
headers={"Content-Type": "application/json; charset=utf-8"},
json={
"msg_type": "text", "content": {"text": send_title + "\r\n" + push_message}
}
).json()
log.info(f"推送结果:{rep.get('msg')}")
# Bark # Bark
def bark(send_title, push_message): def bark(send_title, push_message):

17
ql_main.py Normal file
View File

@ -0,0 +1,17 @@
"""
new Env('米游社');
"""
import notify
from loghelper import log
from error import CookieError
from main import main
if __name__ == "__main__":
try:
status_code, message = main()
except CookieError:
status_code = 1
message = "账号Cookie出错"
log.error("账号Cookie有问题")
notify.send("米游社", message)

View File

@ -76,43 +76,45 @@ headers = {
} }
# 通用设置 # 通用设置
bbs_Api = "https://bbs-api.mihoyo.com" bbs_api = "https://bbs-api.mihoyo.com"
web_Api = "https://api-takumi.mihoyo.com" web_api = "https://api-takumi.mihoyo.com"
account_Info_url = web_Api + "/binding/api/getUserGameRolesByCookie?game_biz=" account_Info_url = web_api + "/binding/api/getUserGameRolesByCookie?game_biz="
# 米游社的API列表 # 米游社的API列表
bbs_Cookie_url = "https://webapi.account.mihoyo.com/Api/cookie_accountinfo_by_loginticket?login_ticket={}" bbs_cookie_url = "https://webapi.account.mihoyo.com/Api/cookie_accountinfo_by_loginticket?login_ticket={}"
bbs_Cookie_url2 = web_Api + "/auth/api/getMultiTokenByLoginTicket?login_ticket={}&token_types=3&uid={}" bbs_cookie_url2 = web_api + "/auth/api/getMultiTokenByLoginTicket?login_ticket={}&token_types=3&uid={}"
bbs_Tasks_list = bbs_Api + "/apihub/sapi/getUserMissionsState" # 获取任务列表 bbs_tasks_list = bbs_api + "/apihub/sapi/getUserMissionsState" # 获取任务列表
bbs_Sign_url = bbs_Api + "/apihub/app/api/signIn" # post bbs_sign_url = bbs_api + "/apihub/app/api/signIn" # post
bbs_List_url = bbs_Api + "/post/api/getForumPostList?forum_id={}&is_good=false&is_hot=false&page_size=20&sort_type=1" bbs_post_list_url = bbs_api + "/post/api/getForumPostList?forum_id={}&is_good=false&is_hot=false&page_size=20&sort_type=1"
bbs_Detail_url = bbs_Api + "/post/api/getPostFull?post_id={}" bbs_detail_url = bbs_api + "/post/api/getPostFull?post_id={}"
bbs_Share_url = bbs_Api + "/apihub/api/getShareConf?entity_id={}&entity_type=1" bbs_share_url = bbs_api + "/apihub/api/getShareConf?entity_id={}&entity_type=1"
bbs_Like_url = bbs_Api + "/apihub/sapi/upvotePost" # post json bbs_like_url = bbs_api + "/apihub/sapi/upvotePost" # post json
bbs_get_captcha = bbs_api + "/misc/api/createVerification?is_high=true"
bbs_captcha_verify = bbs_api + "/misc/api/verifyVerification"
# 崩坏2自动签到相关的相关设置 # 崩坏2自动签到相关的相关设置
honkai2_Act_id = "e202203291431091" honkai2_Act_id = "e202203291431091"
honkai2_checkin_rewards = f'{web_Api}/event/luna/home?lang=zh-cn&act_id={honkai2_Act_id}' honkai2_checkin_rewards = f'{web_api}/event/luna/home?lang=zh-cn&act_id={honkai2_Act_id}'
honkai2_Is_signurl = web_Api + "/event/luna/info?lang=zh-cn&act_id={}&region={}&uid={}" honkai2_Is_signurl = web_api + "/event/luna/info?lang=zh-cn&act_id={}&region={}&uid={}"
honkai2_Sign_url = web_Api + "/event/luna/sign" honkai2_Sign_url = web_api + "/event/luna/sign"
# 崩坏3自动签到相关的设置 # 崩坏3自动签到相关的设置
honkai3rd_Act_id = "e202207181446311" honkai3rd_Act_id = "e202207181446311"
honkai3rd_checkin_rewards = f'{web_Api}/event/luna/home?lang=zh-cn&act_id={honkai3rd_Act_id}' honkai3rd_checkin_rewards = f'{web_api}/event/luna/home?lang=zh-cn&act_id={honkai3rd_Act_id}'
honkai3rd_Is_signurl = web_Api + "/event/luna/info?lang=zh-cn&act_id={}&region={}&uid={}" honkai3rd_Is_signurl = web_api + "/event/luna/info?lang=zh-cn&act_id={}&region={}&uid={}"
honkai3rd_Sign_url = web_Api + "/event/luna/sign" honkai3rd_Sign_url = web_api + "/event/luna/sign"
# 未定事件簿自动签到相关设置 # 未定事件簿自动签到相关设置
tearsofthemis_Act_id = "e202202251749321" tearsofthemis_Act_id = "e202202251749321"
tearsofthemis_checkin_rewards = f'{web_Api}/event/luna/home?lang=zh-cn&act_id={tearsofthemis_Act_id}' tearsofthemis_checkin_rewards = f'{web_api}/event/luna/home?lang=zh-cn&act_id={tearsofthemis_Act_id}'
tearsofthemis_Is_signurl = honkai2_Is_signurl tearsofthemis_Is_signurl = honkai2_Is_signurl
tearsofthemis_Sign_url = honkai2_Sign_url # 和二崩完全一致 tearsofthemis_Sign_url = honkai2_Sign_url # 和二崩完全一致
# 原神自动签到相关的设置 # 原神自动签到相关的设置
genshin_Act_id = "e202009291139501" genshin_Act_id = "e202009291139501"
genshin_checkin_rewards = f'{web_Api}/event/bbs_sign_reward/home?act_id={genshin_Act_id}' genshin_checkin_rewards = f'{web_api}/event/bbs_sign_reward/home?act_id={genshin_Act_id}'
genshin_Is_signurl = web_Api + "/event/bbs_sign_reward/info?act_id={}&region={}&uid={}" genshin_Is_signurl = web_api + "/event/bbs_sign_reward/info?act_id={}&region={}&uid={}"
genshin_Signurl = web_Api + "/event/bbs_sign_reward/sign" genshin_Signurl = web_api + "/event/bbs_sign_reward/sign"
# 云原神相关api # 云原神相关api
cloud_genshin_Api = "https://api-cloudgame.mihoyo.com" cloud_genshin_Api = "https://api-cloudgame.mihoyo.com"