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

View File

@ -13,40 +13,65 @@
## 部署 ## 部署
### 1. Fork 仓库 ### 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 ### 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 ### 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 ### 4. 启用 Action
> Actions 默认处于关闭状态,首次需要手动执行一次,验证是否可以正常工作。 > Actions 默认处于关闭状态,首次需要手动执行一次,验证是否可以正常工作。
点击 **Actions**,再点击左侧的**Genshin Impact Helper**,再点击**Run workflow** 返回项目主页面,点击上方的`Actions`,再点击左侧的`Genshin Impact Helper`,再点击`Run workflow`
![run](https://i.loli.net/2020/10/28/5ylvgdYf9BDMqAH.png) ![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` 2. 登录失效时,尝试重新更换 `Cookie`
3. 支持多账号,不同 `Cookie` 之间用 `#` 分开即可 3. 支持多账号,不同 `Cookie` 之间用 `#` 分开即可

179
genshin.py Normal file → Executable file
View File

@ -1,52 +1,159 @@
#!/usr/bin/env python3
import requests import requests
import json import json
import uuid import uuid
import logging
from time import sleep from time import sleep
from random import randint 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(): class ConfMeta(type):
url1 = f'https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie?game_biz=hk4e_cn' @property
url2 = f'https://api-takumi.mihoyo.com/event/bbs_sign_reward/sign' def index_url(cls):
device_id = str(uuid.uuid3(uuid.NAMESPACE_URL,cookie)).replace('-','').upper() return 'https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html'
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', @property
'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', 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', 'Accept-Encoding': 'gzip, deflate, br',
'Cookie': cookie 'Cookie': self._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', def get_uid(self):
'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', # 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', 'Accept-Encoding': 'gzip, deflate, br',
'cookie': cookie, 'Cookie': self._cookie,
'x-rpc-device_id': device_id 'x-rpc-device_id': str(uuid.uuid3(
} uuid.NAMESPACE_URL, self._cookie)).replace('-','').upper()
r1 = s.get(url1, headers = headers1) }
d1 = json.loads(r1.text)
uid = d1['data']['list'][0]['game_uid'] def run(self):
logging.info('UID is %s' %(self._uid))
data = { data = {
'act_id': 'e202009291139501', 'act_id': 'e202009291139501',
'region': 'cn_gf01', 'region': 'cn_gf01',
'uid': uid 'uid': self._uid
} }
r2 = s.post(url2, headers = headers2, data = json.dumps(data))
d2 = json.loads(r2.text) try:
if d2['retcode'] == 0: jdict = json.loads(requests.Session().post(
print("======\n签到成功!\n======") self._url, headers = self.get_header(),
else : data = json.dumps(data)).text)
if d2['retcode'] == -5003: except Exception as e:
print("======\n" + d2['message'] + "\n======") raise
else :
print("======\n签到失败!\n详细信息:" + d2['message'] + "\n======") return jdict
exit(100)
def makeResult(result:str, data = None):
return json.dumps(
{
'result': result,
'message': data
},
sort_keys=False, indent=2
)
if __name__ == "__main__": if __name__ == "__main__":
sleep(randint(10,300)) seconds = randint(10, 300)
main() 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'))