Merge pull request #5 from Arondight/master

Better sign
This commit is contained in:
y1ndan 2020-10-30 13:37:28 +08:00 committed by GitHub
commit 2e4039952f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 194 additions and 65 deletions

View File

@ -8,19 +8,16 @@ on:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.7
- run: |
python-version: 3.8
- name: run sign
run: |
pip install -r requirements.txt
string="${{ secrets.COOKIE }}"
IFS="#"
array=($string)
for var in ${array[@]}
do
python3 genshin.py <<EOF
$var
EOF
done
echo "${{ secrets.COOKIE }}" | tr '#' "\n" | xargs -I {} sh -c 'echo "{}" | python3 ./genshin.py'

View File

@ -13,40 +13,65 @@
## 部署
### 1. Fork 仓库
* 项目地址:[github/genshin-impact-helper](https://github.com/y1ndan/genshin-impact-helper)
* 点击右上角**Fork**到自己的账号下
![fork](https://i.loli.net/2020/10/28/qpXowZmIWeEUyrJ.png)
* 项目地址:[github/genshin-impact-helper](https://github.com/y1ndan/genshin-impact-helper)
* 点击右上角`Fork`到自己的账号下
> ![fork](https://i.loli.net/2020/10/28/qpXowZmIWeEUyrJ.png)
### 2. 获取 Cookie
* 浏览器打开 https://bbs.mihoyo.com/ys/ 并登录账号
* 按**F12**,打开**开发者工具**,找到**Network**并点击
* 按**F5**刷新页面,按下图复制**Cookie**
![cookie](https://i.loli.net/2020/10/28/TMKC6lsnk4w5A8i.png)
* 浏览器打开 https://bbs.mihoyo.com/ys/ 并登录账号
* 按`F12`,打开`开发者工具`,找到`Network`并点击
* 按`F5`刷新页面,按下图复制`Cookie`
> ![cookie](https://i.loli.net/2020/10/28/TMKC6lsnk4w5A8i.png)
### 3. 添加 Cookie 至 Secrets
* 回到项目页面,依次点击 Settings --> Secrets --> New secret
![new-secret.png](https://i.loli.net/2020/10/28/sxTuBFtRvzSgUaA.png)
* 回到项目页面,依次点击`Settings`-->`Secrets`-->`New secret`
* 建立名为`COOKIE`的 secret值为**步骤2**中复制的**Cookie**内容,最后点击**Add secret**
> ![new-secret.png](https://i.loli.net/2020/10/28/sxTuBFtRvzSgUaA.png)
![add-secret](https://i.loli.net/2020/10/28/sETkVdmrNcCUpgq.png)
* 建立名为`COOKIE`的 secret值为`步骤2`中复制的`Cookie`内容,最后点击`Add secret`
> ![add-secret](https://i.loli.net/2020/10/28/sETkVdmrNcCUpgq.png)
### 4. 启用 Action
> Actions 默认处于关闭状态,首次需要手动执行一次,验证是否可以正常工作。
点击 **Actions**,再点击左侧的**Genshin Impact Helper**,再点击**Run workflow**
返回项目主页面,点击上方的`Actions`,再点击左侧的`Genshin Impact Helper`,再点击`Run workflow`
![run](https://i.loli.net/2020/10/28/5ylvgdYf9BDMqAH.png)
至此,部署完毕。
首先会运行一遍,如果成功,会输出类似以下结果`"result": "Success"`。
```
2020-10-30T11:30:08 INFO sleep for 214 seconds ...
2020-10-30T11:30:08 INFO UID is 102445054
2020-10-30T11:30:09 INFO {
"result": "Success",
"message": "{'data': None, 'message': '旅行者,你已经签到过了', 'retcode': -5003}"
}
```
如果失败,会输出类似以下结果`"result": "Failed"`。
```
2020-10-30T11:14:26 INFO sleep for 207 seconds ...
2020-10-30T11:14:26 ERROR get uid failed, request is "{'data': None, 'message': '登录失效,请重新登录', 'retcode': -100}"
2020-10-30T11:14:26 INFO {
"result": "Failed",
"message": ""{'data': None, 'message': '登录失效,请重新登录', 'retcode': -100}""
}
```
## 说明
1. 程序会在每天早上 6 点自动执行签到,也可以通过上述**步骤4**手动触发执行
1. 程序会在每天早上 6 点自动执行签到(可能会延迟五分钟),也可以通过上述**步骤4**手动触发执行
2. 登录失效时,尝试重新更换 `Cookie`
3. 支持多账号,不同 `Cookie` 之间用 `#` 分开即可

189
genshin.py Normal file → Executable file
View File

@ -1,52 +1,159 @@
#!/usr/bin/env python3
import requests
import json
import uuid
import logging
from time import sleep
from random import randint
from requests.exceptions import *
s = requests.Session()
logging.basicConfig(
level = logging.INFO,
format = '%(asctime)s %(levelname)s %(message)s',
datefmt = '%Y-%m-%dT%H:%M:%S')
cookie = ""
if (cookie == ""):
cookie = input().strip()
def main():
url1 = f'https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie?game_biz=hk4e_cn'
url2 = f'https://api-takumi.mihoyo.com/event/bbs_sign_reward/sign'
device_id = str(uuid.uuid3(uuid.NAMESPACE_URL,cookie)).replace('-','').upper()
headers1 = {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.1.0',
'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, br',
'Cookie': cookie
}
headers2 = {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.1.0',
'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, br',
'cookie': cookie,
'x-rpc-device_id': device_id
}
r1 = s.get(url1, headers = headers1)
d1 = json.loads(r1.text)
uid = d1['data']['list'][0]['game_uid']
data = {
'act_id': 'e202009291139501',
'region': 'cn_gf01',
'uid': uid
}
r2 = s.post(url2, headers = headers2, data = json.dumps(data))
d2 = json.loads(r2.text)
if d2['retcode'] == 0:
print("======\n签到成功!\n======")
else :
if d2['retcode'] == -5003:
print("======\n" + d2['message'] + "\n======")
else :
print("======\n签到失败!\n详细信息:" + d2['message'] + "\n======")
exit(100)
class ConfMeta(type):
@property
def index_url(cls):
return 'https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html'
@property
def ua(cls):
return 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) ' \
'AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.1.0'
class Conf(metaclass = ConfMeta):
pass
class UID(object):
def __init__(self, cookie:str = None):
if type(cookie) is not str:
raise TypeError("%s want a %s but got %s" %(
self.__class__, type(__name__), type(cookie)))
self._cookie = cookie
self._url = "https://api-takumi.mihoyo.com/binding/api/" \
"getUserGameRolesByCookie?game_biz=%s" %('hk4e_cn')
def get_header(self):
actid = 'e202009291139501'
ref = "%s?bbs_auth_required=%s&act_id=%s&utm_source=%s" \
"&utm_medium=%s&utm_campaign=%s" %(
Conf.index_url, 'true', actid, 'bbs', 'mys', 'icon')
return {
'User-Agent': Conf.ua,
'Referer': ref,
'Accept-Encoding': 'gzip, deflate, br',
'Cookie': self._cookie
}
def get_uid(self):
# XXX Loop this code for try N times ?
try:
jdict = json.loads(
requests.Session().get(
self._url, headers = self.get_header()).text)
except Exception as e:
logging.error(e)
raise HTTPError
try:
return jdict['data']['list'][0]['game_uid']
except:
raise KeyError(str(jdict))
class Sign(object):
def __init__(self, cookie:str = None):
if type(cookie) is not str:
raise TypeError("%s want a %s but got %s" %(
self.__class__, type(__name__), type(cookie)))
self._url = 'https://api-takumi.mihoyo.com/event/bbs_sign_reward/sign'
try:
self._uid = UID(cookie).get_uid()
except KeyError as e:
logging.error("get uid failed, request is %s" %(e))
raise
except Exception as e:
logging.error("Unknown error %s" %(e))
raise
self._cookie = cookie
def get_header(self):
actid = 'e202009291139501'
ref = "%s?bbs_auth_required=%s&act_id=%s&utm_source=%s" \
"&utm_medium=%s&utm_campaign=%s" %(
Conf.index_url, 'true', actid, 'bbs', 'mys', 'icon')
return {
'User-Agent': Conf.ua,
'Referer': ref,
'Accept-Encoding': 'gzip, deflate, br',
'Cookie': self._cookie,
'x-rpc-device_id': str(uuid.uuid3(
uuid.NAMESPACE_URL, self._cookie)).replace('-','').upper()
}
def run(self):
logging.info('UID is %s' %(self._uid))
data = {
'act_id': 'e202009291139501',
'region': 'cn_gf01',
'uid': self._uid
}
try:
jdict = json.loads(requests.Session().post(
self._url, headers = self.get_header(),
data = json.dumps(data)).text)
except Exception as e:
raise
return jdict
def makeResult(result:str, data = None):
return json.dumps(
{
'result': result,
'message': data
},
sort_keys=False, indent=2
)
if __name__ == "__main__":
sleep(randint(10,300))
main()
seconds = randint(10, 300)
logging.info('sleep for %s seconds ...' %(seconds))
sleep(seconds)
try:
jdict = Sign(input().strip()).run()
jstr = str(jdict)
code = jdict['retcode']
except Exception as e:
jstr = str(e)
result = makeResult('Failed', jstr)
try:
code
except NameError:
code = -1
# 0: success
# -5003: already signed in
if code in [0, -5003]:
result = makeResult('Success', jstr)
logging.info(result.encode('utf-8').decode('unicode_escape'))