This commit is contained in:
Womsxd 2021-05-23 21:24:20 +08:00
parent f011f38422
commit 3517364a63
12 changed files with 560 additions and 0 deletions

129
.gitignore vendored Normal file
View File

@ -0,0 +1,129 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Womsxd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

17
config.json Normal file
View File

@ -0,0 +1,17 @@
{
"mihoyobbs_Login_ticket": "",
"mihoyobbs_Stuid": "",
"mihoyobbs_Stoken": "",
"mihoyobbs_Cookies": "",
"mihoyobbs": {
"bbs_Gobal": true,
"bbs_Singin": true,
"bbs_Singin_multi": true,
"bbs_Singin_multi_list": [2, 5],
"bbs_Read_posts": true,
"bbs_Like_posts": true,
"bbs_Unlike": true,
"bbs_Share": true
},
"genshin_AutoSingin": false
}

86
config.py Normal file
View File

@ -0,0 +1,86 @@
import os
import json
from tools import log
#这里的内容会自动获取
mihoyobbs_Login_ticket = ""
mihoyobbs_Stuid = ""
mihoyobbs_Stoken = ""
#这里填入你的米游社Cookie
mihoyobbs_Cookies = ""
#这个dist里面的内容和米游社有关
mihoyobbs = {
#全局开关,关闭之后下面的都不执行
"bbs_Gobal": True,
#讨论区签到
"bbs_Singin": True,
#多个讨论区签到
"bbs_Singin_multi": True,
#指定签到讨论区
"bbs_Singin_multi_list": [2,5],
#浏览3个帖子
"bbs_Read_posts": True,
#完成5次点赞
"bbs_Like_posts": True,
#完成后取消点赞
"bbs_Unlike": True,
#分享帖子
"bbs_Share": True,
}
#原神自动签到
genshin_AutoSingin = True
path = os.path.dirname(os.path.realpath(__file__))
def Load_config():
with open(f"{path}/config.json", "r") as f:
data = json.load(f)
global mihoyobbs_Login_ticket
global mihoyobbs_Stuid
global mihoyobbs_Stoken
global mihoyobbs_Cookies
global mihoyobbs
mihoyobbs_Login_ticket = data["mihoyobbs_Login_ticket"]
mihoyobbs_Stuid = data["mihoyobbs_Stuid"]
mihoyobbs_Stoken = data["mihoyobbs_Stoken"]
mihoyobbs_Cookies = data["mihoyobbs_Cookies"]
mihoyobbs["bbs_Gobal"] = data["mihoyobbs"]["bbs_Gobal"]
mihoyobbs["bbs_Singin"] = data["mihoyobbs"]["bbs_Singin"]
mihoyobbs["bbs_Singin_multi"] = data["mihoyobbs"]["bbs_Singin_multi"]
mihoyobbs["bbs_Singin_multi_list"] = data["mihoyobbs"]["bbs_Singin_multi_list"]
mihoyobbs["bbs_Read_posts"] = data["mihoyobbs"]["bbs_Read_posts"]
mihoyobbs["bbs_Like_posts"] = data["mihoyobbs"]["bbs_Like_posts"]
mihoyobbs["bbs_Unlike"] = data["mihoyobbs"]["bbs_Unlike"]
mihoyobbs["bbs_Share"] = data["mihoyobbs"]["bbs_Share"]
genshin_AutoSingin = data["genshin_AutoSingin"]
f.close()
log.info("Config加载完毕")
def Save_config():
with open(f"{path}/config.json","r+") as f:
data = json.load(f)
data["mihoyobbs_Login_ticket"] = mihoyobbs_Login_ticket
data["mihoyobbs_Stuid"] = mihoyobbs_Stuid
data["mihoyobbs_Stoken"] = mihoyobbs_Stoken
f.seek(0)
f.truncate()
temp_Text = json.dumps(data, sort_keys=False, indent=4, separators=(', ', ': '))
f.write(temp_Text)
f.flush()
f.close()
log.info("Config保存完毕")
def Clear_cookies():
with open(f"{path}/config.json","r+") as f:
data = json.load(f)
data["mihoyobbs_Login_ticket"] = ""
data["mihoyobbs_Stuid"] = ""
data["mihoyobbs_Stoken"] = ""
data["mihoyobbs_Cookies"] = ""
f.seek(0)
f.truncate()
temp_Text = json.dumps(data, sort_keys=False, indent=4, separators=(', ', ': '))
f.write(temp_Text)
f.flush()
f.close()
log.info("Cookie删除完毕")

34
genshin.py Normal file
View File

@ -0,0 +1,34 @@
import time
import httpx
import tools
import config
import random
import setting
class genshin:
def __init__(self) -> None:
self.headers = {
'Accept': 'application/json, text/plain, */*',
'DS': tools.Get_ds(web=True, web_old=True),
'Origin': 'https://webstatic.mihoyo.com',
'x-rpc-app_version': setting.mihoyobbs_Version_old,
'User-Agent': 'Mozilla/5.0 (Linux; Android 9; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 miHoYoBBS/2.2.0',
'x-rpc-client_type': setting.mihoyobbs_Client_type_web,
'Referer': 'https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?bbs_auth_required=true&act_id=e202009291139501&utm_source=bbs&utm_medium=mys&utm_campaign=icon',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,en-US;q=0.8',
'X-Requested-With': 'com.mihoyo.hyperion',
"Cookie": config.mihoyobbs_Cookies
}
self.acc_List = self.Getacc_list()
#获取绑定的账号列表
def Getacc_list(self) -> list:
temp_List = []
req = httpx.get(setting.accinfo_Url, headers=self.headers)
data = req.json()
if (data["rercode"] != 0):
tools.log.warn("获取账号列表失败!")
exit()
for i in data["data"]["list"]:
temp_List.append([i["nickname"], i["game_uid"], i["region"]])
return (temp_List)

30
login.py Normal file
View File

@ -0,0 +1,30 @@
from tools import log
import config
import request
import setting
def login():
if (config.mihoyobbs_Cookies == ''):
log.error("请填入Cookies!")
exit()
temp_Cookies = {}
if ("login_ticket" in config.mihoyobbs_Cookies):
temp_Cookies = config.mihoyobbs_Cookies.split(";")
for i in temp_Cookies:
if (i.split("=")[0] == " login_ticket"):
config.mihoyobbs_Login_ticket = i.split("=")[1]
break
data = request.get(url=setting.cookieUrl.format(config.mihoyobbs_Login_ticket))
if ("成功" in data["data"]["msg"]):
config.mihoyobbs_Stuid = str(data["data"]["cookie_info"]["account_id"])
data = request.get(url=setting.cookieUrl2.format(config.mihoyobbs_Login_ticket, config.mihoyobbs_Stuid))
config.mihoyobbs_Stoken = data["data"]["list"][0]["token"]
log.info("登录成功!")
log.info("正在保存Config")
config.Save_config()
else:
log.error("cookie已失效,请重新登录米游社抓取cookie")
exit()
else:
log.error("cookie中没有'login_ticket'字段,请重新登录米游社重新抓取cookie!")
exit()

82
mihoyobbs.py Normal file
View File

@ -0,0 +1,82 @@
import time
import httpx
import tools
import config
import random
import setting
class mihoyobbs:
def __init__(self):
self.headers = {
"DS": tools.Get_ds(web=False, web_old=False),
"cookie": f"stuid={config.mihoyobbs_Stuid};stoken={config.mihoyobbs_Stoken}",
"x-rpc-client_type": setting.mihoyobbs_Client_type,
"x-rpc-app_version": setting.mihoyobbs_Version,
"x-rpc-sys_version": "6.0.1",
"x-rpc-channel": "mihoyo",
"x-rpc-device_id": tools.Random_text(20) + tools.Random_text(12),
"x-rpc-device_name": tools.Random_text(random.randint(1, 10)),
"x-rpc-device_model": "Mi 10",
"Referer": "https://app.mihoyo.com",
"Host": "bbs-api.mihoyo.com",
"User-Agent": "okhttp/4.8.0"
}
self.postsList = self.Getlist()
#进行签到操作
def Singin(self):
tools.log.info("正在签到......")
for i in setting.mihoyobbs_List_Use:
req = httpx.post(url=setting.signUrl.format(i["id"]), data="" ,headers=self.headers)
data = req.json()
if ("err" not in data["message"]):
tools.log.info(str(i["name"]+ data["message"]))
time.sleep(2)
else:
tools.log.info("签到失败你的cookie可能已过期请重新设置cookie。")
config.Clear_cookies()
exit()
#获取要帖子列表
def Getlist(self) -> list:
temp_List = []
tools.log.info("正在获取帖子列表......")
for i in setting.mihoyobbs_List_Use:
req = httpx.get(url=setting.listUrl.format(i["forumId"]), headers=self.headers)
data = req.json()
for n in range(10):
temp_List.append([data["data"]["list"][n]["post"]["post_id"], data["data"]["list"][n]["post"]["subject"]])
tools.log.info("已获取{}个帖子".format(len(temp_List)))
time.sleep(2)
return (temp_List)
#看帖子
def Readposts(self):
tools.log.info("正在看帖......")
for i in range(3):
req = httpx.get(url=setting.detailUrl.format(self.postsList[i][0]), headers=self.headers)
data = req.json()
if data["message"] == "OK":
tools.log.info("看帖:{} 成功".format(self.postsList[i][1]))
time.sleep(2)
#点赞
def Likeposts(self):
tools.log.info("正在点赞......")
for i in range(5):
req = httpx.post(url=setting.likeUrl, headers=self.headers,
json={"post_id": self.postsList[i][0], "is_cancel": False})
data = req.json()
if (data["message"] == "OK"):
tools.log.info("点赞:{} 成功".format(self.postsList[i][1]))
#判断取消点赞是否打开
if (config.mihoyobbs["bbs_Unlike"] == True):
req = httpx.post(url=setting.likeUrl, headers=self.headers,
json={"post_id": self.postsList[i][0], "is_cancel": True})
data = req.json()
if (data["message"] == "OK"):
tools.log.info("取消点赞:{} 成功".format(self.postsList[i][1]))
time.sleep(2)
def Share(self):
tools.log.info("正在分享......")
req = httpx.get(url=setting.shareUrl.format(self.postsList[0][0]), cookies=self.Cookie, headers=self.headers)
data = req.json()
if data["message"] == "OK":
tools.log.info("分享:{} 成功".format(self.postsList[0][1]))

26
request.py Normal file
View File

@ -0,0 +1,26 @@
import httpx
#这里实际上应该加个"-> dict"但是考虑到请求可能失败的关系,所以直接不声明返回变量
def get(url:str, **headers:dict):
try:
req = httpx.get(url, headers=headers)
return (req.json())
except:
print("请求失败,网络错误!")
return ("")
def post(url:str, data:dict, **headers:dict):
try:
req = httpx.post(url, data=data, headers=headers)
return (req.json())
except:
print("请求失败,网络错误!")
return ("")
def post_json(url:str, json, **headers:dict):
try:
req = httpx.post(url, json=json, headers=headers)
return (req.json())
except:
print("请求失败,网络错误!")
return ("")

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
httpx == 0.18.1

33
run.py Normal file
View File

@ -0,0 +1,33 @@
import login
import config
import setting
import mihoyobbs
#初始化,加载配置
config.Load_config()
#检测参数是否齐全,如果缺少就进行登入操作
if (config.mihoyobbs_Login_ticket == "" or config.mihoyobbs_Stuid == "" or config.mihoyobbs_Stoken == ""):
#登入
login.login()
#获取要使用的BBS列表
#判断是否开启bbs_Singin_multi
if (config.mihoyobbs["bbs_Singin_multi"] == True):
for i in setting.mihoyobbs_List:
if (int(i["id"]) in config.mihoyobbs["bbs_Singin_multi_list"]):
setting.mihoyobbs_List_Use.append(i)
else:
#关闭bbs_Singin_multi后只签到大别墅
for i in setting.mihoyobbs_List:
if (int(i["id"]) == 5):
setting.mihoyobbs_List_Use.append(i)
#米游社签到
if(config.mihoyobbs["bbs_Gobal"] == True):
bbs = mihoyobbs.mihoyobbs()
if (config.mihoyobbs["bbs_Singin"] == True):
bbs.Singin()
if (config.mihoyobbs["bbs_Read_posts"] == True):
bbs.Readposts()
if (config.mihoyobbs["bbs_Like_posts"] == True):
bbs.Likeposts()
if (config.mihoyobbs["bbs_Share"] == True):
bbs.Share()

53
setting.py Normal file
View File

@ -0,0 +1,53 @@
#米游社的Salt
mihoyobbs_Salt = "fd3ykrh7o1j54g581upo1tvpam0dsgtf"
mihoyobbs_Salt_web = "14bmu1mz0yuljprsfgpvjh3ju2ni468r"
mihoyobbs_Salt_web_old = "h8w582wxwgqvahcdkpvdhbh2w9casgfl"
#米游社的版本
mihoyobbs_Version = "2.7.0" #Slat和Version相互对应
mihoyobbs_Version_old = "2.3.0"
#米游社的客户端类型
mihoyobbs_Client_type = "2" #1为ios 2为安卓
mihoyobbs_Client_type_web = "5" #4为pc web 5为mobile web
#米游社的分区列表
mihoyobbs_List = [{
"id": "1",
"forumId": "1",
"name": "崩坏3",
"url": "https://bbs.mihoyo.com/bh3/"
},{
"id": "2",
"forumId": "26",
"name": "原神",
"url": "https://bbs.mihoyo.com/ys/"
},{
"id": "3",
"forumId": "30",
"name": "崩坏2",
"url": "https://bbs.mihoyo.com/bh2/"
},{
"id": "4",
"forumId": "37",
"name": "未定事件簿",
"url": "https://bbs.mihoyo.com/wd/"
},{
"id": "5",
"forumId": "34",
"name": "大别野",
"url": "https://bbs.mihoyo.com/dby/"
}]
#Config Load之后run里面进行列表的选择
mihoyobbs_List_Use= []
#米游社的API列表
cookieUrl = "https://webapi.account.mihoyo.com/Api/cookie_accountinfo_by_loginticket?login_ticket={}"
cookieUrl2 = "https://api-takumi.mihoyo.com/auth/api/getMultiTokenByLoginTicket?login_ticket={}&token_types=3&uid={}"
signUrl = "https://bbs-api.mihoyo.com/apihub/sapi/signIn?gids={}" # post
listUrl = "https://bbs-api.mihoyo.com/post/api/getForumPostList?forum_id={}&is_good=false&is_hot=false&page_size=20&sort_type=1"
detailUrl = "https://bbs-api.mihoyo.com/post/api/getPostFull?post_id={}"
shareUrl = "https://bbs-api.mihoyo.com/apihub/api/getShareConf?entity_id={}&entity_type=1"
likeUrl = "https://bbs-api.mihoyo.com/apihub/sapi/upvotePost" # post json
#原神自动签到相关的设置
act_ID = "e202009291139501"
accinfo_Url = "https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie?game_biz=hk4e_cn"

48
tools.py Normal file
View File

@ -0,0 +1,48 @@
import logging
import time
import random
import string
import hashlib
import setting
#Log输出
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y-%m-%dT%H:%M:%S')
log = logger = logging
#md5计算
def MD5(text:str) -> str:
md5 = hashlib.md5()
md5.update(text.encode())
return (md5.hexdigest())
#随机文本
def Random_text(num:int) -> str:
return(''.join(random.sample(string.ascii_lowercase + string.digits, num)))
#时间戳
def Timestamp() -> int:
return(int(time.time()))
#获取请求Header里的DS 当web为true则生成网页端的DS
def Get_ds(web:bool, web_old:bool) -> str:
if(web == True):
if(web_old == True):
n = setting.mihoyobbs_Salt_web_old
else:
n = setting.mihoyobbs_Salt_web
else:
n = setting.mihoyobbs_Salt
i = str(Timestamp())
r = Random_text(6)
c = MD5("salt=" + n + "&t=" + i + "&r=" + r)
return (i + "," + r + "," + c)
#获取明天早晨0点的时间戳
def Nextday() -> int:
now_time = int(time.time())
nextday_time = now_time - now_time % 86400 + time.timezone + 86400
return (nextday_time)