Add a way for the application to dump inventory data into a file

This commit is contained in:
DevilXD
2024-06-30 12:01:03 +02:00
parent 6d258efe41
commit f5d5fc3a05
7 changed files with 55 additions and 24 deletions

1
.gitignore vendored
View File

@@ -13,6 +13,7 @@ __pycache__
/cache
/*.jar
log.txt
/dump.dat
/lock.file
settings.json
/lang/English.json

27
.vscode/launch.json vendored
View File

@@ -11,24 +11,6 @@
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "Run App (INFO)",
"type": "python",
"request": "launch",
"program": "main.py",
"args": ["-vv"],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Run App (INFO+Tray)",
"type": "python",
"request": "launch",
"program": "main.py",
"args": ["-vv", "--tray"],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Run App (CALL)",
"type": "python",
@@ -38,6 +20,15 @@
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Run App (DUMP)",
"type": "python",
"request": "launch",
"program": "main.py",
"args": ["--dump"],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Run App (DEBUG+WS)",
"type": "python",

View File

@@ -23,7 +23,7 @@ if TYPE_CHECKING:
IS_APPIMAGE = "APPIMAGE" in os.environ and os.path.exists(os.environ["APPIMAGE"])
IS_PACKAGED = hasattr(sys, "_MEIPASS") or IS_APPIMAGE
# logging special levels
CALL = logging.INFO - 1
CALL: int = logging.INFO - 1
logging.addLevelName(CALL, "CALL")
# site-packages venv path changes depending on the system platform
if sys.platform == "win32":
@@ -94,8 +94,9 @@ SITE_PACKAGES_PATH = Path(VENV_PATH, SYS_SITE_PACKAGES)
LANG_PATH = _resource_path("lang")
# Other Paths
LOG_PATH = Path(WORKING_DIR, "log.txt")
CACHE_PATH = Path(WORKING_DIR, "cache")
DUMP_PATH = Path(WORKING_DIR, "dump.dat")
LOCK_PATH = Path(WORKING_DIR, "lock.file")
CACHE_PATH = Path(WORKING_DIR, "cache")
CACHE_DB = Path(CACHE_PATH, "mapping.json")
COOKIES_PATH = Path(WORKING_DIR, "cookies.jar")
SETTINGS_PATH = Path(WORKING_DIR, "settings.json")

View File

@@ -53,7 +53,7 @@ if __name__ == "__main__":
_debug_gql: bool
log: bool
tray: bool
no_run_check: bool
dump: bool
# TODO: replace int with union of literal values once typeshed updates
@property
@@ -103,6 +103,7 @@ if __name__ == "__main__":
parser.add_argument("-v", dest="_verbose", action="count", default=0)
parser.add_argument("--tray", action="store_true")
parser.add_argument("--log", action="store_true")
parser.add_argument("--dump", action="store_true")
# undocumented debug args
parser.add_argument(
"--debug-ws", dest="_debug_ws", action="store_true", help=argparse.SUPPRESS

View File

@@ -5,15 +5,20 @@
Available command line arguments:
• --tray
Start application as minimised into tray.
Start the application as minimised into tray.
• -v
Increase verbosity level. Can be stacked up several times (-vv, -vvv, etc.) to show
increasingly more information during application runtime.
• --log
Enables logging of runtime information into a 'log.txt' file. Verbosity level of this logging
matches the level set by `-v`.
• --dump
Start the application in a data-dump mode, where a 'dump.dat' file is created.
The file contains anonymous raw Twitch API data, studying of which can help troubleshoot
issues with the application. The application automatically closes shortly after launching,
once dumping is finished.
• --version
Show application version information
Show application version information.
Note: Additional settings are available within the application GUI.

View File

@@ -40,7 +40,7 @@ class Settings:
# from args
log: bool
tray: bool
no_run_check: bool
dump: bool
# args properties
debug_ws: int
debug_gql: int

View File

@@ -4,6 +4,7 @@ import json
import asyncio
import logging
from time import time
from copy import deepcopy
from itertools import chain
from functools import partial
from collections import abc, deque, OrderedDict
@@ -39,6 +40,7 @@ from utils import (
)
from constants import (
CALL,
DUMP_PATH,
COOKIES_PATH,
GQL_OPERATIONS,
MAX_CHANNELS,
@@ -559,6 +561,10 @@ class Twitch:
return -1
async def run(self):
if self.settings.dump:
with open(DUMP_PATH, 'w', encoding="utf8"):
# replace the existing file with an empty one
pass
while True:
try:
await self._run()
@@ -599,6 +605,9 @@ class Twitch:
self.change_state(State.INVENTORY_FETCH)
while True:
if self._state is State.IDLE:
if self.settings.dump:
self.gui.close()
continue
self.gui.status.update(_("gui", "status", "idle"))
self.stop_watching()
# clear the flag and wait until it's set again
@@ -787,6 +796,9 @@ class Twitch:
watching_channel,
)
elif self._state is State.CHANNEL_SWITCH:
if self.settings.dump:
self.gui.close()
continue
self.gui.status.update(_("gui", "status", "switching"))
# Change into the selected channel, stay in the watching channel,
# or select a new channel that meets the required conditions
@@ -1412,6 +1424,26 @@ class Twitch:
chunk_campaigns_data = await chunk_coro
# merge the inventory and campaigns datas together
inventory_data = self._merge_data(inventory_data, chunk_campaigns_data)
if self.settings.dump:
# dump the campaigns data to the dump file
with open(DUMP_PATH, 'a', encoding="utf8") as file:
# pre-process a little, so the dump file isn't overly bloated
dump_data: JsonType = deepcopy(inventory_data)
for campaign_data in dump_data.values():
if (
campaign_data["allow"]
and campaign_data["allow"].get("isEnabled", True)
and campaign_data["allow"]["channels"]
):
# simply count the channels included in the ACL
campaign_data["allow"]["channels"] = (
f"{len(campaign_data['allow']['channels'])} channels"
)
json.dump(dump_data, file, indent=4, sort_keys=True)
file.write("\n\n") # add a new line spacer
json.dump(claimed_benefits, file, indent=4, sort_keys=True, default=str)
# use the merged data to create campaign objects
campaigns: list[DropsCampaign] = [
DropsCampaign(self, campaign_data, claimed_benefits)