Splatlogger 1.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright © 2025 Shadow Doggo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6
+ and associated documentation files (the “Software”), to deal in the Software without
7
+ restriction, including without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or
12
+ substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
15
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,67 @@
1
+ Metadata-Version: 2.4
2
+ Name: Splatlogger
3
+ Version: 1.5
4
+ Summary: A PID/PNID grabber and match logger for Splatoon using TCPGecko.
5
+ Author-email: Shadow Doggo <shadowdoggo@protonmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Source Code, https://github.com/spoongaming61/Splatlogger
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: userpaths
14
+ Requires-Dist: requests
15
+ Dynamic: license-file
16
+
17
+ # Splatlogger
18
+ A PID/PNID grabber and match logger for Splatoon using TCPGecko, written in Python.
19
+
20
+ ## Prerequisites
21
+ You'll need a modded Wii U running either Tiramisu or Aroma, as well as Python 3.11 or newer installed on your system (on Android devices you can use [Termux](https://termux.com/)).
22
+
23
+ On Tiramisu, use [TCPGecko](https://github.com/BullyWiiPlaza/tcpgecko) (Geckiine or SDGeckiine will work as well).
24
+
25
+ On Aroma, install the [TCPGecko Aroma plugin](https://github.com/spoongaming61/TCPGeckoAroma).
26
+
27
+ ## Installation and Usage
28
+ Install the package from PyPI:
29
+
30
+ `python -m pip install Splatlogger`
31
+
32
+ Or download and install the latest release from GitHub:
33
+
34
+ `python -m pip install /path/to/Splatlogger-1.x.zip`
35
+
36
+ Run Splatlogger with `splatlogger -ip IP [options]` (or `python -m splatlogger -ip IP [options]`) where `IP` is your Wii U's LAN IP address.
37
+
38
+ Alternatively, you can run the script directly from the source code:
39
+
40
+ `cd /path/to/Splatlogger/src && python -m splatlogger -ip IP [options]`
41
+
42
+ Options:
43
+ - `-log-level [option]` - Set how much data should be logged.
44
+ - `none` - Don't create a log file (default).
45
+ - `basic` - Log only basic player information (name, PID, PNID, region).
46
+ - `full` - Log all player information (basic + team, level, rank, appearance, gear, weapons).
47
+ - `stats` - Log all player information and player stats (points, kills, deaths). Requires the match to end to finish logging.
48
+
49
+ - `-auto [option]` - Enable auto logging. When enabled will automatically log every match you play (log level must be at least `basic`).
50
+ - `all` - Save a log of all matches you play (default).
51
+ - `latest` - Save a log of only the latest match
52
+
53
+ - `-aroma` - Enable Aroma mode.
54
+
55
+ - `-silent` - Disable printing logs to the console.
56
+
57
+ Logs are saved in `/[User]/Documents/Splatlogger/logs/[Date]`.
58
+
59
+ To always run with the same IP and options, create an `args.txt` file in `/[User]/Documents/Splatlogger` and put all the arguments in there.
60
+ Afterward run Splatlogger without any arguments.
61
+
62
+ Only one program can be connected to TCPGecko at a time. If you have something else connected, disconnect it beforehand.
63
+
64
+ ## Credits
65
+ [pyGecko](https://github.com/wiiudev/pyGecko) authors - tcpgecko.py
66
+
67
+ Everyone who contributed to [PNIDGrab](https://github.com/JerrySM64/PNIDGrab) and other similar PID grabbers as this is partly based on those.
@@ -0,0 +1,51 @@
1
+ # Splatlogger
2
+ A PID/PNID grabber and match logger for Splatoon using TCPGecko, written in Python.
3
+
4
+ ## Prerequisites
5
+ You'll need a modded Wii U running either Tiramisu or Aroma, as well as Python 3.11 or newer installed on your system (on Android devices you can use [Termux](https://termux.com/)).
6
+
7
+ On Tiramisu, use [TCPGecko](https://github.com/BullyWiiPlaza/tcpgecko) (Geckiine or SDGeckiine will work as well).
8
+
9
+ On Aroma, install the [TCPGecko Aroma plugin](https://github.com/spoongaming61/TCPGeckoAroma).
10
+
11
+ ## Installation and Usage
12
+ Install the package from PyPI:
13
+
14
+ `python -m pip install Splatlogger`
15
+
16
+ Or download and install the latest release from GitHub:
17
+
18
+ `python -m pip install /path/to/Splatlogger-1.x.zip`
19
+
20
+ Run Splatlogger with `splatlogger -ip IP [options]` (or `python -m splatlogger -ip IP [options]`) where `IP` is your Wii U's LAN IP address.
21
+
22
+ Alternatively, you can run the script directly from the source code:
23
+
24
+ `cd /path/to/Splatlogger/src && python -m splatlogger -ip IP [options]`
25
+
26
+ Options:
27
+ - `-log-level [option]` - Set how much data should be logged.
28
+ - `none` - Don't create a log file (default).
29
+ - `basic` - Log only basic player information (name, PID, PNID, region).
30
+ - `full` - Log all player information (basic + team, level, rank, appearance, gear, weapons).
31
+ - `stats` - Log all player information and player stats (points, kills, deaths). Requires the match to end to finish logging.
32
+
33
+ - `-auto [option]` - Enable auto logging. When enabled will automatically log every match you play (log level must be at least `basic`).
34
+ - `all` - Save a log of all matches you play (default).
35
+ - `latest` - Save a log of only the latest match
36
+
37
+ - `-aroma` - Enable Aroma mode.
38
+
39
+ - `-silent` - Disable printing logs to the console.
40
+
41
+ Logs are saved in `/[User]/Documents/Splatlogger/logs/[Date]`.
42
+
43
+ To always run with the same IP and options, create an `args.txt` file in `/[User]/Documents/Splatlogger` and put all the arguments in there.
44
+ Afterward run Splatlogger without any arguments.
45
+
46
+ Only one program can be connected to TCPGecko at a time. If you have something else connected, disconnect it beforehand.
47
+
48
+ ## Credits
49
+ [pyGecko](https://github.com/wiiudev/pyGecko) authors - tcpgecko.py
50
+
51
+ Everyone who contributed to [PNIDGrab](https://github.com/JerrySM64/PNIDGrab) and other similar PID grabbers as this is partly based on those.
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "Splatlogger"
7
+ version = "1.5"
8
+ authors = [
9
+ { name="Shadow Doggo", email="shadowdoggo@protonmail.com" }
10
+ ]
11
+ description = "A PID/PNID grabber and match logger for Splatoon using TCPGecko."
12
+ readme = "README.md"
13
+ requires-python = ">=3.11"
14
+ dependencies = [
15
+ "userpaths",
16
+ "requests"
17
+ ]
18
+ classifiers = [
19
+ "Programming Language :: Python :: 3",
20
+ "Operating System :: OS Independent",
21
+ ]
22
+ license = "MIT"
23
+ license-files = ["LICENSE"]
24
+
25
+ [project.urls]
26
+ "Source Code" = "https://github.com/spoongaming61/Splatlogger"
27
+
28
+ [project.scripts]
29
+ splatlogger = "splatlogger.__main__:main"
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
33
+ include = ["splatlogger*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,67 @@
1
+ Metadata-Version: 2.4
2
+ Name: Splatlogger
3
+ Version: 1.5
4
+ Summary: A PID/PNID grabber and match logger for Splatoon using TCPGecko.
5
+ Author-email: Shadow Doggo <shadowdoggo@protonmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Source Code, https://github.com/spoongaming61/Splatlogger
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: userpaths
14
+ Requires-Dist: requests
15
+ Dynamic: license-file
16
+
17
+ # Splatlogger
18
+ A PID/PNID grabber and match logger for Splatoon using TCPGecko, written in Python.
19
+
20
+ ## Prerequisites
21
+ You'll need a modded Wii U running either Tiramisu or Aroma, as well as Python 3.11 or newer installed on your system (on Android devices you can use [Termux](https://termux.com/)).
22
+
23
+ On Tiramisu, use [TCPGecko](https://github.com/BullyWiiPlaza/tcpgecko) (Geckiine or SDGeckiine will work as well).
24
+
25
+ On Aroma, install the [TCPGecko Aroma plugin](https://github.com/spoongaming61/TCPGeckoAroma).
26
+
27
+ ## Installation and Usage
28
+ Install the package from PyPI:
29
+
30
+ `python -m pip install Splatlogger`
31
+
32
+ Or download and install the latest release from GitHub:
33
+
34
+ `python -m pip install /path/to/Splatlogger-1.x.zip`
35
+
36
+ Run Splatlogger with `splatlogger -ip IP [options]` (or `python -m splatlogger -ip IP [options]`) where `IP` is your Wii U's LAN IP address.
37
+
38
+ Alternatively, you can run the script directly from the source code:
39
+
40
+ `cd /path/to/Splatlogger/src && python -m splatlogger -ip IP [options]`
41
+
42
+ Options:
43
+ - `-log-level [option]` - Set how much data should be logged.
44
+ - `none` - Don't create a log file (default).
45
+ - `basic` - Log only basic player information (name, PID, PNID, region).
46
+ - `full` - Log all player information (basic + team, level, rank, appearance, gear, weapons).
47
+ - `stats` - Log all player information and player stats (points, kills, deaths). Requires the match to end to finish logging.
48
+
49
+ - `-auto [option]` - Enable auto logging. When enabled will automatically log every match you play (log level must be at least `basic`).
50
+ - `all` - Save a log of all matches you play (default).
51
+ - `latest` - Save a log of only the latest match
52
+
53
+ - `-aroma` - Enable Aroma mode.
54
+
55
+ - `-silent` - Disable printing logs to the console.
56
+
57
+ Logs are saved in `/[User]/Documents/Splatlogger/logs/[Date]`.
58
+
59
+ To always run with the same IP and options, create an `args.txt` file in `/[User]/Documents/Splatlogger` and put all the arguments in there.
60
+ Afterward run Splatlogger without any arguments.
61
+
62
+ Only one program can be connected to TCPGecko at a time. If you have something else connected, disconnect it beforehand.
63
+
64
+ ## Credits
65
+ [pyGecko](https://github.com/wiiudev/pyGecko) authors - tcpgecko.py
66
+
67
+ Everyone who contributed to [PNIDGrab](https://github.com/JerrySM64/PNIDGrab) and other similar PID grabbers as this is partly based on those.
@@ -0,0 +1,15 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/Splatlogger.egg-info/PKG-INFO
5
+ src/Splatlogger.egg-info/SOURCES.txt
6
+ src/Splatlogger.egg-info/dependency_links.txt
7
+ src/Splatlogger.egg-info/entry_points.txt
8
+ src/Splatlogger.egg-info/requires.txt
9
+ src/Splatlogger.egg-info/top_level.txt
10
+ src/splatlogger/__init__.py
11
+ src/splatlogger/__main__.py
12
+ src/splatlogger/data.py
13
+ src/splatlogger/match_logger.py
14
+ src/splatlogger/tcpgecko.py
15
+ src/splatlogger/tcpgecko_aroma.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ splatlogger = splatlogger.__main__:main
@@ -0,0 +1,2 @@
1
+ userpaths
2
+ requests
@@ -0,0 +1 @@
1
+ splatlogger
File without changes
@@ -0,0 +1,286 @@
1
+ # Splatlogger (c) 2025 Shadow Doggo.
2
+
3
+ import os
4
+ import sys
5
+ import time
6
+ import argparse
7
+ import requests
8
+ import ipaddress
9
+ import userpaths # type: ignore[import-untyped]
10
+ import xml.etree.ElementTree as ElementTree
11
+ from datetime import datetime
12
+
13
+ from .data import Pointers, Offsets, PlayerInfo
14
+ from .match_logger import MatchLogger
15
+ from .tcpgecko import TCPGecko, TCPGeckoException
16
+ from .tcpgecko_aroma import TCPGeckoAroma
17
+
18
+ _VERSION: str = "1.5"
19
+
20
+
21
+ def main() -> None:
22
+ def splatlog(match_count: int) -> None:
23
+ request_fail: bool = False
24
+ request_errors: list[str] = []
25
+ session_id: int = 0
26
+ player_count: int = 8
27
+ player_info_list: list[PlayerInfo] = []
28
+
29
+ if session_adr != 0:
30
+ session_id_idx: int = int.from_bytes(gecko.peek_raw(session_adr + Offsets.SESSION_ID_IDX, length=0x1),
31
+ byteorder="big")
32
+ session_id = gecko.peek32(session_adr + session_id_idx * 4 + Offsets.SESSION_ID)
33
+
34
+ main_mgr_base_adr: int = gecko.peek32(Pointers.MAIN_MGR_BASE)
35
+ if main_mgr_base_adr != 0:
36
+ player_mgr_adr: int = gecko.peek32(main_mgr_base_adr + Offsets.PLAYER_MGR)
37
+ if player_mgr_adr != 0:
38
+ player_count = gecko.peek8(player_mgr_adr + Offsets.PLAYER_COUNT)
39
+ else:
40
+ print("You are currently not in a match. Logging previous match data "
41
+ "(Player 1 data will be your own, Session ID will be the current one).\n")
42
+
43
+ player_idx: int
44
+ for player_idx in range(player_count):
45
+ player_info_adr: int = gecko.peek32(player_info_ary_adr + player_idx * 0x4)
46
+ player_info_raw: bytes = gecko.peek_raw(player_info_adr, length=0xD4)
47
+
48
+ player_pid: int = int.from_bytes(player_info_raw[0xD0:0xD4], byteorder="big")
49
+ if player_pid != 0:
50
+ player_name: str = (player_info_raw[0x6:0x26]
51
+ .decode("utf-16-be")
52
+ .split("\u0000")[0]
53
+ .replace("\n", "")
54
+ .replace("\r", ""))
55
+
56
+ player_pnid: str = ""
57
+ player_mii_name: str = ""
58
+ request_error: str = ""
59
+ request_retry_count: int = 0
60
+ while request_retry_count < 3:
61
+ try:
62
+ response: requests.Response = requests.get(
63
+ f"https://account.pretendo.cc/v1/api/miis?pids={player_pid}",
64
+ headers={"X-Nintendo-Client-ID": "a2efa818a34fa16b8afbc8a74eba3eda",
65
+ "X-Nintendo-Client-Secret": "c91cdb5658bd4954ade78533a339cf9a"},
66
+ timeout=10
67
+ )
68
+
69
+ root: ElementTree.Element[str] = ElementTree.fromstring(response.text)
70
+ assert (isinstance(root[0].find("user_id"), ElementTree.Element) and
71
+ isinstance(root[0].find("name"), ElementTree.Element))
72
+ player_pnid = root[0].find("user_id").text # type: ignore
73
+ player_mii_name = (root[0].find("name") # type: ignore
74
+ .text
75
+ .replace("\n", "")
76
+ .replace("\r", ""))
77
+ request_fail = False
78
+ break
79
+ except (requests.HTTPError, AssertionError) as ex:
80
+ request_fail = True
81
+ request_error = str(ex)
82
+ request_retry_count += 1
83
+ time.sleep(1)
84
+
85
+ if request_fail and request_error not in request_errors:
86
+ request_errors.append(request_error)
87
+
88
+ if log_level != "none":
89
+ player_info: PlayerInfo = PlayerInfo(
90
+ index=player_idx,
91
+ pid=player_pid,
92
+ pnid=player_pnid,
93
+ name=player_name,
94
+ mii_name=player_mii_name,
95
+ region=int.from_bytes(player_info_raw[0x2C:0x30], byteorder="big"),
96
+ team=int.from_bytes(player_info_raw[0x33:0x34], byteorder="big"),
97
+ gender=int.from_bytes(player_info_raw[0x37:0x38], byteorder="big"),
98
+ skin_tone=int.from_bytes(player_info_raw[0x3B:0x3C], byteorder="big"),
99
+ eye_color=int.from_bytes(player_info_raw[0x3F:0x40], byteorder="big"),
100
+ weapon=int.from_bytes(player_info_raw[0x46:0x48], byteorder="big"),
101
+ sub_weapon=int.from_bytes(player_info_raw[0x4A:0x4C], byteorder="big"),
102
+ special_weapon=int.from_bytes(player_info_raw[0x4D:0x50], byteorder="big"),
103
+ shoes=int.from_bytes(player_info_raw[0x54:0x58], byteorder="big"),
104
+ clothes=int.from_bytes(player_info_raw[0x70:0x74], byteorder="big"),
105
+ headgear=int.from_bytes(player_info_raw[0x8C:0x90], byteorder="big"),
106
+ level=int.from_bytes(player_info_raw[0xAF:0xB0], byteorder="big", signed=True) + 1,
107
+ rank=int.from_bytes(player_info_raw[0xB3:0xB4], byteorder="big", signed=True)
108
+ )
109
+ player_info_list.append(player_info)
110
+
111
+ if not silent_logging:
112
+ print(f"Player {player_idx + 1} | "
113
+ f"PID: {player_pid:X} ({player_pid}) {' ' * 16 if player_pid == 0 else ''}| "
114
+ f"PNID: {player_pnid} {' ' * (16 - len(player_pnid))}| "
115
+ f"Name: {player_name}"
116
+ f"{' (Mii name: ' + player_mii_name + ')' if player_name != player_mii_name else ''}")
117
+
118
+ if not silent_logging:
119
+ print()
120
+ if request_fail:
121
+ print("Failed to get account data for one or more players: "
122
+ f"{'; '.join(request_errors)}\n")
123
+
124
+ if session_id != 0:
125
+ print(f"Session ID: {session_id:X} ({session_id})")
126
+ else:
127
+ print("Session ID: None")
128
+
129
+ print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
130
+
131
+ if log_level != "none":
132
+ match_logger.log_match(session_id, match_count, player_info_list)
133
+
134
+ # Main driver code.
135
+ epic_fail: bool = False
136
+ retry_count: int = 0
137
+
138
+ print(f"Splatlogger v{_VERSION} by Shadow Doggo\n")
139
+
140
+ parser: argparse.ArgumentParser = argparse.ArgumentParser(
141
+ description="A PID/PNID grabber and match logger for Splatoon using TCPGecko."
142
+ )
143
+ parser.add_argument("-ip", help="Your Wii U's LAN IP address.", required=True)
144
+ parser.add_argument("-log-level", help="Set how much data should be logged (see README).",
145
+ choices=["none", "basic", "full", "stats"], nargs="?", const="none", default="none")
146
+ parser.add_argument("-auto",
147
+ help="Enable auto logging (all to log every match, latest to only log the latest match).",
148
+ choices=["all", "latest"], nargs="?", const="all")
149
+ parser.add_argument("-aroma", help="Enable Aroma mode.", action="store_true")
150
+ parser.add_argument("-silent", help="Disable printing logs to the console.", action="store_true")
151
+
152
+ args: argparse.Namespace
153
+ if os.path.isfile(f"{userpaths.get_my_documents()}/Splatlogger/args.txt"):
154
+ with open(f"{userpaths.get_my_documents()}/Splatlogger/args.txt") as f:
155
+ args = parser.parse_args(f.read().split())
156
+ else:
157
+ args = parser.parse_args()
158
+
159
+ log_level: str = args.log_level
160
+ silent_logging: bool = args.silent
161
+ auto_logging: bool = True if args.auto in ("all", "latest") else False
162
+ log_latest: bool = True if args.auto == "latest" else False
163
+ aroma: bool = True if args.aroma else False
164
+
165
+ gecko: TCPGecko
166
+ try:
167
+ ipaddress.ip_address(args.ip)
168
+ print(f"Connecting to: {args.ip}")
169
+ gecko = TCPGeckoAroma(args.ip) if aroma else TCPGecko(args.ip)
170
+ except ValueError:
171
+ print("Please provide a valid IP address.\nExiting.")
172
+ sys.exit()
173
+ except OSError as e:
174
+ print(f"Failed to connect: {e}\nExiting.")
175
+ sys.exit()
176
+
177
+ static_mem_adr: int = 0
178
+ session_adr: int = 0
179
+ player_info_ary_adr: int = 0
180
+ while retry_count < 3:
181
+ try:
182
+ static_mem_adr = gecko.peek32(Pointers.STATIC_MEM)
183
+ session_adr = gecko.peek32(Pointers.SESSION)
184
+ player_info_ary_adr = gecko.peek32(static_mem_adr + Offsets.PLAYER_INFO_ARY)
185
+
186
+ epic_fail = False
187
+ break
188
+ except (OSError, TimeoutError, TCPGeckoException) as e:
189
+ print(f"\nAn error has occurred: {e}\nRetrying in 10 seconds...")
190
+ epic_fail = True
191
+ time.sleep(10)
192
+
193
+ if epic_fail:
194
+ print("\nFailed after 3 retries. Exiting.")
195
+ sys.exit()
196
+
197
+ print("Connected.\n")
198
+ retry_count = 0
199
+
200
+ match_logger: MatchLogger
201
+ if log_level != "none" and not auto_logging:
202
+ match_logger = MatchLogger(gecko, log_level, auto_logging, aroma, static_mem_adr)
203
+ try:
204
+ match_logger.create_new_log()
205
+ except OSError as e:
206
+ print(f"Failed to create log file: {e}\nExiting.")
207
+ sys.exit()
208
+
209
+ if log_level != "none" and auto_logging:
210
+ print("Auto logging enabled.")
211
+
212
+ match_logger = MatchLogger(gecko, log_level, auto_logging, aroma, static_mem_adr)
213
+ try:
214
+ match_logger.create_new_log()
215
+ except OSError as e:
216
+ print(f"Failed to create log file: {e}\nExiting.")
217
+ sys.exit()
218
+
219
+ match_in_progress: bool = False
220
+ count: int = 0
221
+ while True:
222
+ try:
223
+ main_mgr_vs_game_adr: int = gecko.peek32(Pointers.MAIN_MGR_VS_GAME)
224
+ if main_mgr_vs_game_adr == 0:
225
+ match_in_progress = False
226
+
227
+ if not match_in_progress and main_mgr_vs_game_adr != 0: # Trigger logging when a VS match is loaded.
228
+ match_in_progress = True
229
+ session_adr = gecko.peek32(Pointers.SESSION)
230
+ count += 1
231
+
232
+ if log_latest:
233
+ match_logger.create_new_log()
234
+
235
+ if not silent_logging:
236
+ print(f"\nMatch {count}\n")
237
+
238
+ time.sleep(1)
239
+ while retry_count < 3:
240
+ try:
241
+ splatlog(count)
242
+ epic_fail = False
243
+ break
244
+ except (OSError, TimeoutError, TCPGeckoException) as e:
245
+ print(f"\nAn error has occurred: {e}\nRetrying in 10 seconds...")
246
+ epic_fail = True
247
+ retry_count += 1
248
+ time.sleep(10)
249
+
250
+ if epic_fail:
251
+ print("\nFailed after 3 retries. Exiting.")
252
+ sys.exit()
253
+
254
+ retry_count = 0
255
+ time.sleep(10)
256
+ except KeyboardInterrupt:
257
+ print("\nExiting.")
258
+ break
259
+ except (OSError, TimeoutError, TCPGeckoException) as e:
260
+ if retry_count < 3:
261
+ print(f"\nAn error has occurred: {e}\nRetrying in 10 seconds...")
262
+ retry_count += 1
263
+ time.sleep(10)
264
+ else:
265
+ print("\nFailed after 3 retries. Exiting.")
266
+ break
267
+
268
+ if not auto_logging:
269
+ while retry_count < 3:
270
+ try:
271
+ splatlog(match_count=1)
272
+ epic_fail = False
273
+ break
274
+ except (OSError, TimeoutError, TCPGeckoException) as e:
275
+ print(f"\nAn error has occurred: {e}\nRetrying in 10 seconds...")
276
+ epic_fail = True
277
+ retry_count += 1
278
+ time.sleep(10)
279
+
280
+ if epic_fail:
281
+ print("\nFailed after 3 retries. Exiting.")
282
+ sys.exit()
283
+
284
+
285
+ if __name__ == "__main__":
286
+ main()