commit
2e4039952f
@ -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
|
|
||||||
51
README.md
51
README.md
@ -13,40 +13,65 @@
|
|||||||
## 部署
|
## 部署
|
||||||
|
|
||||||
### 1. Fork 仓库
|
### 1. Fork 仓库
|
||||||
* 项目地址:[github/genshin-impact-helper](https://github.com/y1ndan/genshin-impact-helper)
|
|
||||||
* 点击右上角**Fork**到自己的账号下
|
|
||||||
|
|
||||||

|
* 项目地址:[github/genshin-impact-helper](https://github.com/y1ndan/genshin-impact-helper)
|
||||||
|
* 点击右上角`Fork`到自己的账号下
|
||||||
|
|
||||||
|
> 
|
||||||
|
|
||||||
### 2. 获取 Cookie
|
### 2. 获取 Cookie
|
||||||
* 浏览器打开 https://bbs.mihoyo.com/ys/ 并登录账号
|
|
||||||
* 按**F12**,打开**开发者工具**,找到**Network**并点击
|
|
||||||
* 按**F5**刷新页面,按下图复制**Cookie**
|
|
||||||
|
|
||||||

|
* 浏览器打开 https://bbs.mihoyo.com/ys/ 并登录账号
|
||||||
|
* 按`F12`,打开`开发者工具`,找到`Network`并点击
|
||||||
|
* 按`F5`刷新页面,按下图复制`Cookie`
|
||||||
|
|
||||||
|
> 
|
||||||
|
|
||||||
### 3. 添加 Cookie 至 Secrets
|
### 3. 添加 Cookie 至 Secrets
|
||||||
* 回到项目页面,依次点击 Settings --> Secrets --> New secret
|
|
||||||
|
|
||||||

|
* 回到项目页面,依次点击`Settings`-->`Secrets`-->`New secret`
|
||||||
|
|
||||||
* 建立名为`COOKIE`的 secret,值为**步骤2**中复制的**Cookie**内容,最后点击**Add secret**
|
> 
|
||||||
|
|
||||||

|
* 建立名为`COOKIE`的 secret,值为`步骤2`中复制的`Cookie`内容,最后点击`Add secret`
|
||||||
|
|
||||||
|
> 
|
||||||
|
|
||||||
### 4. 启用 Action
|
### 4. 启用 Action
|
||||||
|
|
||||||
> Actions 默认处于关闭状态,首次需要手动执行一次,验证是否可以正常工作。
|
> Actions 默认处于关闭状态,首次需要手动执行一次,验证是否可以正常工作。
|
||||||
|
|
||||||
点击 **Actions**,再点击左侧的**Genshin Impact Helper**,再点击**Run workflow**
|
返回项目主页面,点击上方的`Actions`,再点击左侧的`Genshin Impact Helper`,再点击`Run workflow`
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
至此,部署完毕。
|
至此,部署完毕。
|
||||||
|
|
||||||
|
首先会运行一遍,如果成功,会输出类似以下结果`"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` 之间用 `#` 分开即可
|
||||||
|
|
||||||
|
|||||||
173
genshin.py
Normal file → Executable file
173
genshin.py
Normal file → Executable 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)
|
def run(self):
|
||||||
uid = d1['data']['list'][0]['game_uid']
|
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'))
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user