mirror of
https://github.com/frozenpandaman/s3s.git
synced 2026-08-28 05:14:27 -05:00
add --getseed flag (#74)
This commit is contained in:
@@ -11,7 +11,8 @@ Looking to track your _Splatoon 2_ gameplay? See **[splatnet2statink](https://gi
|
||||
- [x] Full automation of SplatNet token generation via user log-in
|
||||
- [x] Ability to parse & upload complete battle/job stats to stat.ink ([example profile](https://stat.ink/@frozenpandaman/spl3))
|
||||
- [x] Monitoring for new results in real-time & checking for missing/unuploaded results
|
||||
- [x] Flag to black out other players' names from results
|
||||
- [x] Flag to remove other players' names from results
|
||||
- [x] File exporting function for use with Lean's [gear & Shell-Out Machine seed checker](https://leanny.github.io/splat3seedchecker/)
|
||||
- [x] Support for all available game languages
|
||||
- [x] Modular design to support [IkaLog3](https://github.com/hasegaw/IkaLog3) and other tools
|
||||
|
||||
@@ -23,7 +24,7 @@ Looking to track your _Splatoon 2_ gameplay? See **[splatnet2statink](https://gi
|
||||
|
||||
## Usage 🐙
|
||||
```
|
||||
$ python s3s.py [-M [N]] [-r] [-nsr | -osr] [--blackout]
|
||||
$ python s3s.py [-M [N]] [-r] [-nsr | -osr] [--blackout] [--getseed]
|
||||
```
|
||||
|
||||
The `-M` flag runs the script in monitoring mode, uploading new battles/jobs as you play, checking for new results every `N` seconds; if no `N` is provided, it defaults to 300 (5 minutes).
|
||||
@@ -34,7 +35,9 @@ The `-nsr` flag makes Salmon Run jobs **not** be monitored/uploaded. Use this if
|
||||
|
||||
The `-osr` flag, conversely, makes **only** Salmon Run jobs be monitored/uploaded. Use this if you're playing at Grizzco only.
|
||||
|
||||
The `--blackout` flag blacks out other players' names in uploaded scoreboard data.
|
||||
The `--blackout` flag removes other players' names from uploaded scoreboard data.
|
||||
|
||||
The `--getseed` flag exports a file which can be uploaded to Lean's [gear & Shell-Out Machine seed checker](https://leanny.github.io/splat3seedchecker/).
|
||||
|
||||
Arguments for advanced usage (e.g. locally exporting data to JSON files) can be viewed using `--help`.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
beautifulsoup4
|
||||
mmh3
|
||||
msgpack_python
|
||||
packaging
|
||||
requests
|
||||
|
||||
84
s3s.py
84
s3s.py
@@ -5,11 +5,11 @@
|
||||
# License: GPLv3
|
||||
|
||||
import argparse, base64, datetime, json, os, shutil, re, requests, sys, time, uuid
|
||||
import msgpack
|
||||
import mmh3, msgpack
|
||||
from packaging import version
|
||||
import iksm, utils
|
||||
|
||||
A_VERSION = "0.1.16"
|
||||
A_VERSION = "0.1.17"
|
||||
|
||||
DEBUG = False
|
||||
|
||||
@@ -1225,6 +1225,67 @@ class SquidProgress:
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def export_seed_json(skipprefetch=False):
|
||||
'''Export a JSON file for use with Lean's seed checker at https://leanny.github.io/splat3seedchecker/.'''
|
||||
|
||||
if not skipprefetch:
|
||||
prefetch_checks(printout=True)
|
||||
|
||||
sha = utils.translate_rid["MyOutfitCommonDataEquipmentsQuery"]
|
||||
outfit_post = requests.post(utils.GRAPHQL_URL, data=utils.gen_graphql_body(sha),
|
||||
headers=headbutt(), cookies=dict(_gtoken=GTOKEN))
|
||||
|
||||
sha = utils.translate_rid["LatestBattleHistoriesQuery"]
|
||||
history_post = requests.post(utils.GRAPHQL_URL, data=utils.gen_graphql_body(sha),
|
||||
headers=headbutt(), cookies=dict(_gtoken=GTOKEN))
|
||||
|
||||
if outfit_post.status_code != 200 or history_post.status_code != 200:
|
||||
print("Could not reach SplatNet 3. Exiting.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
outfit = json.loads(outfit_post.text)
|
||||
history = json.loads(history_post.text)
|
||||
except:
|
||||
print("Ill-formatted JSON file received. Exiting.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
pid = history["data"]["latestBattleHistories"]["historyGroupsOnlyFirst"]["nodes"][0]["historyDetails"]["nodes"][0]["player"]["id"]
|
||||
# VsPlayer-u-<20 char long player id>:RECENT:<YYYYMMDD>T<HHMMSS>_<UUID>:u-<same player id as earlier>
|
||||
s = utils.b64d(pid)
|
||||
r = s.split(":")[-1]
|
||||
except KeyError: # no recent battles (mr. grizz is pleased)
|
||||
try:
|
||||
sha = utils.translate_rid["CoopHistoryQuery"]
|
||||
history_post = requests.post(utils.GRAPHQL_URL, data=utils.gen_graphql_body(sha),
|
||||
headers=headbutt(), cookies=dict(_gtoken=GTOKEN))
|
||||
|
||||
if history_post.status_code != 200:
|
||||
print("Could not reach SplatNet 3. Exiting.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
history = json.loads(history_post.text)
|
||||
except:
|
||||
print("Ill-formatted JSON file received. Exiting.")
|
||||
sys.exit(1)
|
||||
|
||||
pid = history["data"]["coopResult"]["historyGroupsOnlyFirst"]["nodes"][0]["historyDetails"]["nodes"][0]["id"]
|
||||
# CoopHistoryDetail-u-<20 char long player id>:<YYYYMMDD>T<HHMMSS>_<UUID>
|
||||
s = utils.b64d(pid)
|
||||
r = s.split(":")[0].replace("CoopHistoryDetail-", "")
|
||||
except KeyError:
|
||||
r = ""
|
||||
|
||||
h = mmh3.hash(r)&0xFFFFFFFF # make positive
|
||||
key = base64.b64encode(bytes([k^(h&0xFF) for k in bytes(r, "utf-8")]))
|
||||
t = int(time.time())
|
||||
|
||||
with open(os.path.join(os.getcwd(), f"gear_{t}.json"), "x") as fout:
|
||||
json.dump({"key": key.decode("utf-8"), "h": h, "timestamp": t, "gear": outfit}, fout)
|
||||
|
||||
print(f"gear_{t}.json has been exported.")
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
'''Setup for command-line options.'''
|
||||
|
||||
@@ -1235,17 +1296,19 @@ def parse_arguments():
|
||||
parser.add_argument("-r", required=False, action="store_true",
|
||||
help="retroactively post unuploaded battles/jobs")
|
||||
srgroup.add_argument("-nsr", required=False, action="store_true",
|
||||
help="do not check for Salmon Run jobs")
|
||||
help="do not check for Salmon Run jobs")
|
||||
srgroup.add_argument("-osr", required=False, action="store_true",
|
||||
help="only check for Salmon Run jobs")
|
||||
help="only check for Salmon Run jobs")
|
||||
parser.add_argument("--blackout", required=False, action="store_true",
|
||||
help="black out names in uploaded scoreboard data")
|
||||
help="remove player names from uploaded scoreboard data")
|
||||
parser.add_argument("-o", required=False, action="store_true",
|
||||
help="export all possible results to local files")
|
||||
parser.add_argument("-i", dest="file", nargs=2, required=False,
|
||||
help="upload local results; use `-i results.json overview.json`")
|
||||
parser.add_argument("-t", required=False, action="store_true",
|
||||
help="dry run for testing (won't post to stat.ink)")
|
||||
parser.add_argument("--getseed", required=False, action="store_true",
|
||||
help="export JSON for gear & Shell-Out Machine seed checker")
|
||||
parser.add_argument("--skipprefetch", required=False, action="store_true", help=argparse.SUPPRESS)
|
||||
return parser.parse_args()
|
||||
|
||||
@@ -1271,6 +1334,7 @@ def main():
|
||||
only_ink = parser_result.nsr # ink battles ONLY
|
||||
only_salmon = parser_result.osr # salmon run ONLY
|
||||
blackout = parser_result.blackout
|
||||
getseed = parser_result.getseed
|
||||
|
||||
# testing/dev stuff
|
||||
test_run = parser_result.t # send to stat.ink as dry run
|
||||
@@ -1280,7 +1344,15 @@ def main():
|
||||
|
||||
# i/o checks
|
||||
############
|
||||
if only_ink and only_salmon:
|
||||
if getseed and len(sys.argv) > 2 and "--skipprefetch" not in sys.argv:
|
||||
print("Cannot use --getseed with other arguments. Exiting.")
|
||||
sys.exit(0)
|
||||
|
||||
elif getseed:
|
||||
export_seed_json(skipprefetch)
|
||||
sys.exit(0)
|
||||
|
||||
elif only_ink and only_salmon:
|
||||
print("That doesn't make any sense! :) Exiting.")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
19
utils.py
19
utils.py
@@ -20,14 +20,15 @@ SUPPORTED_KEYS = [
|
||||
# SHA256 hash database for SplatNet 3 GraphQL queries
|
||||
# full list: https://github.com/samuelthomas2774/nxapi/discussions/11#discussioncomment-3614603
|
||||
translate_rid = {
|
||||
'HomeQuery': 'dba47124d5ec3090c97ba17db5d2f4b3', # blank vars
|
||||
'LatestBattleHistoriesQuery': '7d8b560e31617e981cf7c8aa1ca13a00', # INK / blank vars - query1
|
||||
'RegularBattleHistoriesQuery': 'f6e7e0277e03ff14edfef3b41f70cd33', # INK / blank vars - query1
|
||||
'BankaraBattleHistoriesQuery': 'c1553ac75de0a3ea497cdbafaa93e95b', # INK / blank vars - query1
|
||||
'PrivateBattleHistoriesQuery': '38e0529de8bc77189504d26c7a14e0b8', # INK / blank vars - query1
|
||||
'VsHistoryDetailQuery': '2b085984f729cd51938fc069ceef784a', # INK / req "vsResultId" - query2
|
||||
'CoopHistoryQuery': '817618ce39bcf5570f52a97d73301b30', # SR / blank vars - query1
|
||||
'CoopHistoryDetailQuery': 'f3799a033f0a7ad4b1b396f9a3bafb1e' # SR / req "coopHistoryDetailId" - query2
|
||||
'HomeQuery': 'dba47124d5ec3090c97ba17db5d2f4b3', # blank vars
|
||||
'LatestBattleHistoriesQuery': '7d8b560e31617e981cf7c8aa1ca13a00', # INK / blank vars - query1
|
||||
'RegularBattleHistoriesQuery': 'f6e7e0277e03ff14edfef3b41f70cd33', # INK / blank vars - query1
|
||||
'BankaraBattleHistoriesQuery': 'c1553ac75de0a3ea497cdbafaa93e95b', # INK / blank vars - query1
|
||||
'PrivateBattleHistoriesQuery': '38e0529de8bc77189504d26c7a14e0b8', # INK / blank vars - query1
|
||||
'VsHistoryDetailQuery': '2b085984f729cd51938fc069ceef784a', # INK / req "vsResultId" - query2
|
||||
'CoopHistoryQuery': '817618ce39bcf5570f52a97d73301b30', # SR / blank vars - query1
|
||||
'CoopHistoryDetailQuery': 'f3799a033f0a7ad4b1b396f9a3bafb1e', # SR / req "coopHistoryDetailId" - query2
|
||||
'MyOutfitCommonDataEquipmentsQuery': 'd29cd0c2b5e6bac90dd5b817914832f8' # for Lean's seed checker
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +95,7 @@ def b64d(string):
|
||||
if len(thing_id) == 5 and thing_id[:1] == "2" and thing_id[-3:] == "900": # grizzco weapon ID from a hacker
|
||||
return ""
|
||||
|
||||
if thing_id[:15] == "VsHistoryDetail" or thing_id[:17] == "CoopHistoryDetail":
|
||||
if thing_id[:15] == "VsHistoryDetail" or thing_id[:17] == "CoopHistoryDetail" or thing_id[:8] == "VsPlayer":
|
||||
return thing_id # string
|
||||
else:
|
||||
return int(thing_id) # integer
|
||||
|
||||
Reference in New Issue
Block a user