cs2tracker 2.1.17__py3-none-any.whl → 2.1.19__py3-none-any.whl
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.
Potentially problematic release.
This version of cs2tracker might be problematic. Click here for more details.
- cs2tracker/_version.py +2 -2
- cs2tracker/app/editor_frame.py +68 -27
- cs2tracker/config.py +41 -28
- cs2tracker/constants.py +4 -3
- cs2tracker/data/config.ini +24 -44
- cs2tracker/data/convert_inventory.js +66 -20
- cs2tracker/data/get_inventory.js +58 -24
- {cs2tracker-2.1.17.dist-info → cs2tracker-2.1.19.dist-info}/METADATA +12 -11
- {cs2tracker-2.1.17.dist-info → cs2tracker-2.1.19.dist-info}/RECORD +13 -13
- {cs2tracker-2.1.17.dist-info → cs2tracker-2.1.19.dist-info}/WHEEL +0 -0
- {cs2tracker-2.1.17.dist-info → cs2tracker-2.1.19.dist-info}/entry_points.txt +0 -0
- {cs2tracker-2.1.17.dist-info → cs2tracker-2.1.19.dist-info}/licenses/LICENSE +0 -0
- {cs2tracker-2.1.17.dist-info → cs2tracker-2.1.19.dist-info}/top_level.txt +0 -0
cs2tracker/_version.py
CHANGED
cs2tracker/app/editor_frame.py
CHANGED
|
@@ -8,7 +8,7 @@ from tkinter import messagebox, ttk
|
|
|
8
8
|
from nodejs import node
|
|
9
9
|
from ttk_text import ThemedText
|
|
10
10
|
|
|
11
|
-
from cs2tracker.config import get_config
|
|
11
|
+
from cs2tracker.config import CUSTOM_SECTIONS, get_config
|
|
12
12
|
from cs2tracker.constants import (
|
|
13
13
|
CONFIG_FILE,
|
|
14
14
|
CONFIG_FILE_BACKUP,
|
|
@@ -18,7 +18,7 @@ from cs2tracker.constants import (
|
|
|
18
18
|
)
|
|
19
19
|
from cs2tracker.util.tkinter import centered, size_info
|
|
20
20
|
|
|
21
|
-
ADD_CUSTOM_ITEM_TITLE = "Add
|
|
21
|
+
ADD_CUSTOM_ITEM_TITLE = "Add Item"
|
|
22
22
|
ADD_CUSTOM_ITEM_SIZE = "500x230"
|
|
23
23
|
|
|
24
24
|
IMPORT_INVENTORY_TITLE = "Import Steam Inventory"
|
|
@@ -131,7 +131,7 @@ class ConfigEditorFrame(ttk.Frame):
|
|
|
131
131
|
if selected:
|
|
132
132
|
item = selected[0]
|
|
133
133
|
section_name = self.tree.parent(item)
|
|
134
|
-
if section_name in
|
|
134
|
+
if section_name in CUSTOM_SECTIONS:
|
|
135
135
|
next_option = self.tree.next(item)
|
|
136
136
|
self.tree.delete(item)
|
|
137
137
|
self.save_config()
|
|
@@ -169,31 +169,24 @@ class ConfigEditorFrame(ttk.Frame):
|
|
|
169
169
|
continue
|
|
170
170
|
|
|
171
171
|
section_level = self.tree.insert("", "end", iid=section, text=section)
|
|
172
|
-
|
|
173
|
-
# Items in the Stickers, Cases, and Skins sections should be displayed alphabetically sorted
|
|
174
172
|
section_items = config.items(section)
|
|
175
|
-
|
|
173
|
+
|
|
174
|
+
# Major Sticker Capsules should remain sorted by year
|
|
175
|
+
if section != "Major Sticker Capsules":
|
|
176
176
|
section_items = sorted(section_items)
|
|
177
177
|
|
|
178
178
|
for config_option, value in section_items:
|
|
179
179
|
if section not in ("User Settings", "App Settings"):
|
|
180
180
|
option_name = config.option_to_name(config_option, href=True)
|
|
181
|
-
self.tree.insert(
|
|
182
|
-
section_level,
|
|
183
|
-
"end",
|
|
184
|
-
iid=f"{section}-{option_name}",
|
|
185
|
-
text=option_name,
|
|
186
|
-
values=[value],
|
|
187
|
-
)
|
|
188
181
|
else:
|
|
189
182
|
option_name = config.option_to_name(config_option)
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
183
|
+
self.tree.insert(
|
|
184
|
+
section_level,
|
|
185
|
+
"end",
|
|
186
|
+
iid=f"{section}-{option_name}",
|
|
187
|
+
text=option_name,
|
|
188
|
+
values=[value],
|
|
189
|
+
)
|
|
197
190
|
|
|
198
191
|
self.tree.focus("User Settings")
|
|
199
192
|
self.tree.selection_set("User Settings")
|
|
@@ -267,6 +260,25 @@ class ConfigEditorButtonFrame(ttk.Frame):
|
|
|
267
260
|
custom_item_button = ttk.Button(self, text="Add Item", command=self._add_custom_item)
|
|
268
261
|
custom_item_button.pack(side="left", expand=True, padx=5)
|
|
269
262
|
|
|
263
|
+
def open_custom_enter(_):
|
|
264
|
+
selected = self.editor_frame.tree.selection()
|
|
265
|
+
if selected and not self.editor_frame.tree.parent(selected[0]):
|
|
266
|
+
selected_section = self.editor_frame.tree.item(selected[0], "text")
|
|
267
|
+
if selected_section in CUSTOM_SECTIONS and not self.editor_frame.tree.get_children(
|
|
268
|
+
selected_section
|
|
269
|
+
):
|
|
270
|
+
custom_item_button.invoke()
|
|
271
|
+
|
|
272
|
+
def open_custom_click(event):
|
|
273
|
+
selected_section = self.editor_frame.tree.identify_row(event.y)
|
|
274
|
+
if selected_section in CUSTOM_SECTIONS and not self.editor_frame.tree.get_children(
|
|
275
|
+
selected_section
|
|
276
|
+
):
|
|
277
|
+
custom_item_button.invoke()
|
|
278
|
+
|
|
279
|
+
self.editor_frame.tree.bind("<Return>", open_custom_enter, add="+")
|
|
280
|
+
self.editor_frame.tree.bind("<Double-1>", open_custom_click, add="+")
|
|
281
|
+
|
|
270
282
|
import_inventory_button = ttk.Button(
|
|
271
283
|
self, text="Import Steam Inventory", command=self._import_steam_inventory
|
|
272
284
|
)
|
|
@@ -397,6 +409,36 @@ class CustomItemFrame(ttk.Frame):
|
|
|
397
409
|
break
|
|
398
410
|
return insert_index
|
|
399
411
|
|
|
412
|
+
def _identify_custom_section(self, item_name):
|
|
413
|
+
# pylint: disable=too-many-return-statements,too-many-branches
|
|
414
|
+
"""Given an item name, identify the custom section it belongs to."""
|
|
415
|
+
if "Patch Pack" in item_name or "Patch Collection" in item_name:
|
|
416
|
+
return "Patch Packs"
|
|
417
|
+
elif "Patch |" in item_name:
|
|
418
|
+
return "Patches"
|
|
419
|
+
elif "Sticker |" in item_name:
|
|
420
|
+
return "Stickers"
|
|
421
|
+
elif "Charm |" in item_name:
|
|
422
|
+
return "Charms"
|
|
423
|
+
elif "Music Kit |" in item_name:
|
|
424
|
+
return "Music Kits"
|
|
425
|
+
elif "Souvenir" in item_name and "|" not in item_name:
|
|
426
|
+
return "Souvenirs"
|
|
427
|
+
elif "★ " in item_name:
|
|
428
|
+
return "Special Items"
|
|
429
|
+
elif " | " in item_name and "(" in item_name and ")" in item_name:
|
|
430
|
+
return "Skins"
|
|
431
|
+
elif "Pins Capsule" in item_name:
|
|
432
|
+
return "Pins Capsules"
|
|
433
|
+
elif "Capsule" in item_name:
|
|
434
|
+
return "Sticker Capsules"
|
|
435
|
+
elif "Pin" in item_name:
|
|
436
|
+
return "Collectible Pins"
|
|
437
|
+
elif " | " in item_name:
|
|
438
|
+
return "Agents"
|
|
439
|
+
else:
|
|
440
|
+
return "Others"
|
|
441
|
+
|
|
400
442
|
def _add_custom_item(self, item_href, item_owned):
|
|
401
443
|
"""Add a custom item to the configuration."""
|
|
402
444
|
if not item_href or not item_owned:
|
|
@@ -404,7 +446,7 @@ class CustomItemFrame(ttk.Frame):
|
|
|
404
446
|
"Input Error", "All fields must be filled out.", parent=self.window
|
|
405
447
|
)
|
|
406
448
|
return
|
|
407
|
-
if config.option_exists(item_href, exclude_sections=
|
|
449
|
+
if config.option_exists(item_href, exclude_sections=CUSTOM_SECTIONS):
|
|
408
450
|
messagebox.showerror(
|
|
409
451
|
"Item Exists", "This item already exists in another section.", parent=self.window
|
|
410
452
|
)
|
|
@@ -416,12 +458,11 @@ class CustomItemFrame(ttk.Frame):
|
|
|
416
458
|
messagebox.showerror("Invalid URL", str(error), parent=self.window)
|
|
417
459
|
return
|
|
418
460
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return
|
|
461
|
+
for section in CUSTOM_SECTIONS:
|
|
462
|
+
if self._update_existing(section, item_name, item_owned):
|
|
463
|
+
return
|
|
423
464
|
|
|
424
|
-
section =
|
|
465
|
+
section = self._identify_custom_section(item_name)
|
|
425
466
|
insert_index = self._get_insert_index(item_name, section)
|
|
426
467
|
self.editor_frame.tree.insert(
|
|
427
468
|
section,
|
|
@@ -500,7 +541,7 @@ class InventoryImportFrame(ttk.Frame):
|
|
|
500
541
|
self.import_sticker_capsules_value = tk.BooleanVar(value=True)
|
|
501
542
|
self.import_sticker_capsules_checkbox = ttk.Checkbutton(
|
|
502
543
|
self.checkbox_frame,
|
|
503
|
-
text="Import Sticker Capsules",
|
|
544
|
+
text="Import Major Sticker Capsules",
|
|
504
545
|
variable=self.import_sticker_capsules_value,
|
|
505
546
|
style="Switch.TCheckbutton",
|
|
506
547
|
)
|
cs2tracker/config.py
CHANGED
|
@@ -3,12 +3,33 @@ import re
|
|
|
3
3
|
from configparser import ConfigParser, ParsingError
|
|
4
4
|
from urllib.parse import quote, unquote
|
|
5
5
|
|
|
6
|
-
from cs2tracker.constants import
|
|
6
|
+
from cs2tracker.constants import (
|
|
7
|
+
CONFIG_FILE,
|
|
8
|
+
INVENTORY_IMPORT_FILE,
|
|
9
|
+
)
|
|
7
10
|
from cs2tracker.util.padded_console import get_console
|
|
8
11
|
|
|
9
12
|
STEAM_MARKET_LISTING_BASEURL_CS2 = "https://steamcommunity.com/market/listings/730/"
|
|
10
13
|
STEAM_MARKET_LISTING_REGEX = r"^https://steamcommunity.com/market/listings/\d+/.+$"
|
|
11
14
|
|
|
15
|
+
CUSTOM_SECTIONS = [
|
|
16
|
+
"Skins",
|
|
17
|
+
"Special Items",
|
|
18
|
+
"Agents",
|
|
19
|
+
"Charms",
|
|
20
|
+
"Patches",
|
|
21
|
+
"Patch Packs",
|
|
22
|
+
"Stickers",
|
|
23
|
+
"Souvenirs",
|
|
24
|
+
"Sticker Capsules",
|
|
25
|
+
"Others",
|
|
26
|
+
"Collectible Pins",
|
|
27
|
+
"Pins Capsules",
|
|
28
|
+
"Music Kits",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
PRECONFIGURED_SECTIONS = ["Cases", "Major Sticker Capsules", "App Settings", "User Settings"]
|
|
32
|
+
|
|
12
33
|
console = get_console()
|
|
13
34
|
|
|
14
35
|
|
|
@@ -46,19 +67,12 @@ class ValidatedConfig(ConfigParser):
|
|
|
46
67
|
|
|
47
68
|
def _validate_config_sections(self):
|
|
48
69
|
"""Validate that the configuration file has all required sections."""
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if not self.has_section("Cases"):
|
|
56
|
-
raise ValueError("Missing 'Cases' section in the configuration file.")
|
|
57
|
-
if not self.has_section("Skins"):
|
|
58
|
-
raise ValueError("Missing 'Skins' section in the configuration file.")
|
|
59
|
-
for capsule_section in CAPSULE_PAGES:
|
|
60
|
-
if not self.has_section(capsule_section):
|
|
61
|
-
raise ValueError(f"Missing '{capsule_section}' section in the configuration file.")
|
|
70
|
+
for section in CUSTOM_SECTIONS:
|
|
71
|
+
if not self.has_section(section):
|
|
72
|
+
raise ValueError(f"Missing '{section}' section in the configuration file.")
|
|
73
|
+
for section in PRECONFIGURED_SECTIONS:
|
|
74
|
+
if not self.has_section(section):
|
|
75
|
+
raise ValueError(f"Missing '{section}' section in the configuration file.")
|
|
62
76
|
|
|
63
77
|
def _validate_config_values(self):
|
|
64
78
|
# pylint: disable=too-many-branches
|
|
@@ -136,23 +150,22 @@ class ValidatedConfig(ConfigParser):
|
|
|
136
150
|
try:
|
|
137
151
|
with open(INVENTORY_IMPORT_FILE, "r", encoding="utf-8") as inventory_file:
|
|
138
152
|
inventory_data = json.load(inventory_file)
|
|
139
|
-
sorted_inventory_data = dict(sorted(inventory_data.items()))
|
|
140
153
|
|
|
141
154
|
added_to_config = set()
|
|
142
|
-
for
|
|
143
|
-
|
|
144
|
-
for section in self.sections():
|
|
145
|
-
if option in self.options(section):
|
|
146
|
-
self.set(section, option, str(item_owned))
|
|
147
|
-
added_to_config.add(item_name)
|
|
148
|
-
|
|
149
|
-
for item_name, item_owned in sorted_inventory_data.items():
|
|
150
|
-
if item_name not in added_to_config:
|
|
155
|
+
for _, item_infos in inventory_data.items():
|
|
156
|
+
for item_name, item_owned in item_infos.items():
|
|
151
157
|
option = self.name_to_option(item_name, href=True)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
158
|
+
for section in self.sections():
|
|
159
|
+
if option in self.options(section):
|
|
160
|
+
self.set(section, option, str(item_owned))
|
|
161
|
+
added_to_config.add(item_name)
|
|
162
|
+
|
|
163
|
+
for section, item_infos in inventory_data.items():
|
|
164
|
+
sorted_item_infos = dict(sorted(item_infos.items()))
|
|
165
|
+
for item_name, item_owned in sorted_item_infos.items():
|
|
166
|
+
if item_name not in added_to_config:
|
|
167
|
+
option = self.name_to_option(item_name, href=True)
|
|
168
|
+
self.set(section, option, str(item_owned))
|
|
156
169
|
|
|
157
170
|
self.write_to_file()
|
|
158
171
|
except (FileNotFoundError, json.JSONDecodeError) as error:
|
cs2tracker/constants.py
CHANGED
|
@@ -41,9 +41,9 @@ PYTHON_EXECUTABLE = sys.executable
|
|
|
41
41
|
RUNNING_IN_EXE = getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")
|
|
42
42
|
|
|
43
43
|
if RUNNING_IN_EXE:
|
|
44
|
-
|
|
45
|
-
MODULE_DIR =
|
|
46
|
-
PROJECT_DIR =
|
|
44
|
+
EXECUTABLE_DIR = sys._MEIPASS # type: ignore pylint: disable=protected-access
|
|
45
|
+
MODULE_DIR = EXECUTABLE_DIR
|
|
46
|
+
PROJECT_DIR = EXECUTABLE_DIR
|
|
47
47
|
|
|
48
48
|
if OS == OSType.WINDOWS:
|
|
49
49
|
APP_DATA_DIR = os.path.join(os.path.expanduser("~"), "AppData", "Local")
|
|
@@ -187,6 +187,7 @@ AUTHOR_STRING = (
|
|
|
187
187
|
f"Version: {VERSION} - {datetime.today().strftime('%Y/%m/%d')} - Jannik Novak @ashiven\n"
|
|
188
188
|
)
|
|
189
189
|
|
|
190
|
+
|
|
190
191
|
CAPSULE_PAGES = {
|
|
191
192
|
"Katowice 2014 Sticker Capsule": "https://steamcommunity.com/market/search?q=katowice+2014+legends+challengers",
|
|
192
193
|
"Cologne 2014 Sticker Capsule": "https://steamcommunity.com/market/search?q=cologne+2014+legends+challengers",
|
cs2tracker/data/config.ini
CHANGED
|
@@ -4,13 +4,33 @@ discord_notifications ~ False
|
|
|
4
4
|
conversion_currency ~ EUR
|
|
5
5
|
|
|
6
6
|
[User Settings]
|
|
7
|
-
proxy_api_key ~
|
|
8
7
|
discord_webhook_url ~
|
|
8
|
+
proxy_api_key ~
|
|
9
9
|
|
|
10
10
|
[Skins]
|
|
11
11
|
|
|
12
|
+
[Special Items]
|
|
13
|
+
|
|
14
|
+
[Agents]
|
|
15
|
+
|
|
16
|
+
[Charms]
|
|
17
|
+
|
|
18
|
+
[Patches]
|
|
19
|
+
|
|
20
|
+
[Patch Packs]
|
|
21
|
+
|
|
12
22
|
[Stickers]
|
|
13
23
|
|
|
24
|
+
[Souvenirs]
|
|
25
|
+
|
|
26
|
+
[Sticker Capsules]
|
|
27
|
+
|
|
28
|
+
[Collectible Pins]
|
|
29
|
+
|
|
30
|
+
[Pins Capsules]
|
|
31
|
+
|
|
32
|
+
[Music Kits]
|
|
33
|
+
|
|
14
34
|
[Cases]
|
|
15
35
|
https://steamcommunity.com/market/listings/730/CS%3AGO%20Weapon%20Case ~ 0
|
|
16
36
|
https://steamcommunity.com/market/listings/730/CS%3AGO%20Weapon%20Case%202 ~ 0
|
|
@@ -55,56 +75,36 @@ https://steamcommunity.com/market/listings/730/eSports%202013%20Case ~ 0
|
|
|
55
75
|
https://steamcommunity.com/market/listings/730/eSports%202013%20Winter%20Case ~ 0
|
|
56
76
|
https://steamcommunity.com/market/listings/730/eSports%202014%20Summer%20Case ~ 0
|
|
57
77
|
|
|
58
|
-
[
|
|
78
|
+
[Major Sticker Capsules]
|
|
59
79
|
https://steamcommunity.com/market/listings/730/EMS%20Katowice%202014%20Legends ~ 0
|
|
60
80
|
https://steamcommunity.com/market/listings/730/EMS%20Katowice%202014%20Challengers ~ 0
|
|
61
|
-
|
|
62
|
-
[Cologne 2014 Sticker Capsule]
|
|
63
81
|
https://steamcommunity.com/market/listings/730/ESL%20One%20Cologne%202014%20Legends ~ 0
|
|
64
82
|
https://steamcommunity.com/market/listings/730/ESL%20One%20Cologne%202014%20Challengers ~ 0
|
|
65
|
-
|
|
66
|
-
[DreamHack 2014 Sticker Capsule]
|
|
67
83
|
https://steamcommunity.com/market/listings/730/DreamHack%202014%20Legends%20%28Holo-Foil%29 ~ 0
|
|
68
|
-
|
|
69
|
-
[Katowice 2015 Sticker Capsule]
|
|
70
84
|
https://steamcommunity.com/market/listings/730/ESL%20One%20Katowice%202015%20Legends%20%28Holo-Foil%29 ~ 0
|
|
71
85
|
https://steamcommunity.com/market/listings/730/ESL%20One%20Katowice%202015%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
72
|
-
|
|
73
|
-
[Cologne 2015 Sticker Capsule]
|
|
74
86
|
https://steamcommunity.com/market/listings/730/ESL%20One%20Cologne%202015%20Legends%20%28Foil%29 ~ 0
|
|
75
87
|
https://steamcommunity.com/market/listings/730/ESL%20One%20Cologne%202015%20Challengers%20%28Foil%29 ~ 0
|
|
76
|
-
|
|
77
|
-
[Cluj-Napoca 2015 Sticker Capsule]
|
|
78
88
|
https://steamcommunity.com/market/listings/730/DreamHack%20Cluj-Napoca%202015%20Legends%20%28Foil%29 ~ 0
|
|
79
89
|
https://steamcommunity.com/market/listings/730/DreamHack%20Cluj-Napoca%202015%20Challengers%20%28Foil%29 ~ 0
|
|
80
90
|
https://steamcommunity.com/market/listings/730/Autograph%20Capsule%20%7C%20Legends%20%28Foil%29%20%7C%20Cluj-Napoca%202015 ~ 0
|
|
81
91
|
https://steamcommunity.com/market/listings/730/Autograph%20Capsule%20%7C%20Challengers%20%28Foil%29%20%7C%20Cluj-Napoca%202015 ~ 0
|
|
82
|
-
|
|
83
|
-
[Columbus 2016 Sticker Capsule]
|
|
84
92
|
https://steamcommunity.com/market/listings/730/MLG%20Columbus%202016%20Legends%20%28Holo-Foil%29 ~ 0
|
|
85
93
|
https://steamcommunity.com/market/listings/730/MLG%20Columbus%202016%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
86
94
|
https://steamcommunity.com/market/listings/730/Autograph%20Capsule%20%7C%20Legends%20%28Foil%29%20%7C%20MLG%20Columbus%202016 ~ 0
|
|
87
95
|
https://steamcommunity.com/market/listings/730/Autograph%20Capsule%20%7C%20Challengers%20%28Foil%29%20%7C%20MLG%20Columbus%202016 ~ 0
|
|
88
|
-
|
|
89
|
-
[Cologne 2016 Sticker Capsule]
|
|
90
96
|
https://steamcommunity.com/market/listings/730/Cologne%202016%20Legends%20%28Holo-Foil%29 ~ 0
|
|
91
97
|
https://steamcommunity.com/market/listings/730/Cologne%202016%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
92
98
|
https://steamcommunity.com/market/listings/730/Autograph%20Capsule%20%7C%20Legends%20%28Foil%29%20%7C%20Cologne%202016 ~ 0
|
|
93
99
|
https://steamcommunity.com/market/listings/730/Autograph%20Capsule%20%7C%20Challengers%20%28Foil%29%20%7C%20Cologne%202016 ~ 0
|
|
94
|
-
|
|
95
|
-
[Atlanta 2017 Sticker Capsule]
|
|
96
100
|
https://steamcommunity.com/market/listings/730/Atlanta%202017%20Legends%20%28Holo-Foil%29 ~ 0
|
|
97
101
|
https://steamcommunity.com/market/listings/730/Atlanta%202017%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
98
102
|
https://steamcommunity.com/market/listings/730/Autograph%20Capsule%20%7C%20Legends%20%28Foil%29%20%7C%20Atlanta%202017 ~ 0
|
|
99
103
|
https://steamcommunity.com/market/listings/730/Autograph%20Capsule%20%7C%20Challengers%20%28Foil%29%20%7C%20Atlanta%202017 ~ 0
|
|
100
|
-
|
|
101
|
-
[Krakow 2017 Sticker Capsule]
|
|
102
104
|
https://steamcommunity.com/market/listings/730/Krakow%202017%20Legends%20%28Holo-Foil%29 ~ 0
|
|
103
105
|
https://steamcommunity.com/market/listings/730/Krakow%202017%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
104
106
|
https://steamcommunity.com/market/listings/730/Krakow%202017%20Legends%20Autograph%20Capsule ~ 0
|
|
105
107
|
https://steamcommunity.com/market/listings/730/Krakow%202017%20Challengers%20Autograph%20Capsule ~ 0
|
|
106
|
-
|
|
107
|
-
[Boston 2018 Sticker Capsule]
|
|
108
108
|
https://steamcommunity.com/market/listings/730/Boston%202018%20Legends%20%28Holo-Foil%29 ~ 0
|
|
109
109
|
https://steamcommunity.com/market/listings/730/Boston%202018%20Minor%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
110
110
|
https://steamcommunity.com/market/listings/730/Boston%202018%20Returning%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
@@ -115,44 +115,32 @@ https://steamcommunity.com/market/listings/730/Boston%202018%20Minor%20Challenge
|
|
|
115
115
|
https://steamcommunity.com/market/listings/730/Boston%202018%20Returning%20Challengers%20Autograph%20Capsule ~ 0
|
|
116
116
|
https://steamcommunity.com/market/listings/730/Boston%202018%20Attending%20Legends%20Autograph%20Capsule ~ 0
|
|
117
117
|
https://steamcommunity.com/market/listings/730/Boston%202018%20Minor%20Challengers%20with%20Flash%20Gaming%20Autograph%20Capsule ~ 0
|
|
118
|
-
|
|
119
|
-
[London 2018 Sticker Capsule]
|
|
120
118
|
https://steamcommunity.com/market/listings/730/London%202018%20Legends%20%28Holo-Foil%29 ~ 0
|
|
121
119
|
https://steamcommunity.com/market/listings/730/London%202018%20Minor%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
122
120
|
https://steamcommunity.com/market/listings/730/London%202018%20Returning%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
123
121
|
https://steamcommunity.com/market/listings/730/London%202018%20Legends%20Autograph%20Capsule ~ 0
|
|
124
122
|
https://steamcommunity.com/market/listings/730/London%202018%20Minor%20Challengers%20Autograph%20Capsule ~ 0
|
|
125
123
|
https://steamcommunity.com/market/listings/730/London%202018%20Returning%20Challengers%20Autograph%20Capsule ~ 0
|
|
126
|
-
|
|
127
|
-
[Katowice 2019 Sticker Capsule]
|
|
128
124
|
https://steamcommunity.com/market/listings/730/Katowice%202019%20Legends%20%28Holo-Foil%29 ~ 0
|
|
129
125
|
https://steamcommunity.com/market/listings/730/Katowice%202019%20Minor%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
130
126
|
https://steamcommunity.com/market/listings/730/Katowice%202019%20Returning%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
131
127
|
https://steamcommunity.com/market/listings/730/Katowice%202019%20Legends%20Autograph%20Capsule ~ 0
|
|
132
128
|
https://steamcommunity.com/market/listings/730/Katowice%202019%20Minor%20Challengers%20Autograph%20Capsule ~ 0
|
|
133
129
|
https://steamcommunity.com/market/listings/730/Katowice%202019%20Returning%20Challengers%20Autograph%20Capsule ~ 0
|
|
134
|
-
|
|
135
|
-
[Berlin 2019 Sticker Capsule]
|
|
136
130
|
https://steamcommunity.com/market/listings/730/Berlin%202019%20Legends%20%28Holo-Foil%29 ~ 0
|
|
137
131
|
https://steamcommunity.com/market/listings/730/Berlin%202019%20Minor%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
138
132
|
https://steamcommunity.com/market/listings/730/Berlin%202019%20Returning%20Challengers%20%28Holo-Foil%29 ~ 0
|
|
139
133
|
https://steamcommunity.com/market/listings/730/Berlin%202019%20Legends%20Autograph%20Capsule ~ 0
|
|
140
134
|
https://steamcommunity.com/market/listings/730/Berlin%202019%20Minor%20Challengers%20Autograph%20Capsule ~ 0
|
|
141
135
|
https://steamcommunity.com/market/listings/730/Berlin%202019%20Returning%20Challengers%20Autograph%20Capsule ~ 0
|
|
142
|
-
|
|
143
|
-
[2020 RMR Sticker Capsule]
|
|
144
136
|
https://steamcommunity.com/market/listings/730/2020%20RMR%20Legends ~ 0
|
|
145
137
|
https://steamcommunity.com/market/listings/730/2020%20RMR%20Challengers ~ 0
|
|
146
138
|
https://steamcommunity.com/market/listings/730/2020%20RMR%20Contenders ~ 0
|
|
147
|
-
|
|
148
|
-
[Stockholm 2021 Sticker Capsule]
|
|
149
139
|
https://steamcommunity.com/market/listings/730/Stockholm%202021%20Legends%20Sticker%20Capsule ~ 0
|
|
150
140
|
https://steamcommunity.com/market/listings/730/Stockholm%202021%20Challengers%20Sticker%20Capsule ~ 0
|
|
151
141
|
https://steamcommunity.com/market/listings/730/Stockholm%202021%20Contenders%20Sticker%20Capsule ~ 0
|
|
152
142
|
https://steamcommunity.com/market/listings/730/Stockholm%202021%20Champions%20Autograph%20Capsule ~ 0
|
|
153
143
|
https://steamcommunity.com/market/listings/730/Stockholm%202021%20Finalists%20Autograph%20Capsule ~ 0
|
|
154
|
-
|
|
155
|
-
[Antwerp 2022 Sticker Capsule]
|
|
156
144
|
https://steamcommunity.com/market/listings/730/Antwerp%202022%20Legends%20Sticker%20Capsule ~ 0
|
|
157
145
|
https://steamcommunity.com/market/listings/730/Antwerp%202022%20Challengers%20Sticker%20Capsule ~ 0
|
|
158
146
|
https://steamcommunity.com/market/listings/730/Antwerp%202022%20Contenders%20Sticker%20Capsule ~ 0
|
|
@@ -160,8 +148,6 @@ https://steamcommunity.com/market/listings/730/Antwerp%202022%20Champions%20Auto
|
|
|
160
148
|
https://steamcommunity.com/market/listings/730/Antwerp%202022%20Challengers%20Autograph%20Capsule ~ 0
|
|
161
149
|
https://steamcommunity.com/market/listings/730/Antwerp%202022%20Legends%20Autograph%20Capsule ~ 0
|
|
162
150
|
https://steamcommunity.com/market/listings/730/Antwerp%202022%20Contenders%20Autograph%20Capsule ~ 0
|
|
163
|
-
|
|
164
|
-
[Rio 2022 Sticker Capsule]
|
|
165
151
|
https://steamcommunity.com/market/listings/730/Rio%202022%20Legends%20Sticker%20Capsule ~ 0
|
|
166
152
|
https://steamcommunity.com/market/listings/730/Rio%202022%20Challengers%20Sticker%20Capsule ~ 0
|
|
167
153
|
https://steamcommunity.com/market/listings/730/Rio%202022%20Contenders%20Sticker%20Capsule ~ 0
|
|
@@ -169,8 +155,6 @@ https://steamcommunity.com/market/listings/730/Rio%202022%20Champions%20Autograp
|
|
|
169
155
|
https://steamcommunity.com/market/listings/730/Rio%202022%20Challengers%20Autograph%20Capsule ~ 0
|
|
170
156
|
https://steamcommunity.com/market/listings/730/Rio%202022%20Legends%20Autograph%20Capsule ~ 0
|
|
171
157
|
https://steamcommunity.com/market/listings/730/Rio%202022%20Contenders%20Autograph%20Capsule ~ 0
|
|
172
|
-
|
|
173
|
-
[Paris 2023 Sticker Capsule]
|
|
174
158
|
https://steamcommunity.com/market/listings/730/Paris%202023%20Legends%20Sticker%20Capsule ~ 0
|
|
175
159
|
https://steamcommunity.com/market/listings/730/Paris%202023%20Challengers%20Sticker%20Capsule ~ 0
|
|
176
160
|
https://steamcommunity.com/market/listings/730/Paris%202023%20Contenders%20Sticker%20Capsule ~ 0
|
|
@@ -178,8 +162,6 @@ https://steamcommunity.com/market/listings/730/Paris%202023%20Champions%20Autogr
|
|
|
178
162
|
https://steamcommunity.com/market/listings/730/Paris%202023%20Challengers%20Autograph%20Capsule ~ 0
|
|
179
163
|
https://steamcommunity.com/market/listings/730/Paris%202023%20Legends%20Autograph%20Capsule ~ 0
|
|
180
164
|
https://steamcommunity.com/market/listings/730/Paris%202023%20Contenders%20Autograph%20Capsule ~ 0
|
|
181
|
-
|
|
182
|
-
[Copenhagen 2024 Sticker Capsule]
|
|
183
165
|
https://steamcommunity.com/market/listings/730/Copenhagen%202024%20Legends%20Sticker%20Capsule ~ 0
|
|
184
166
|
https://steamcommunity.com/market/listings/730/Copenhagen%202024%20Challengers%20Sticker%20Capsule ~ 0
|
|
185
167
|
https://steamcommunity.com/market/listings/730/Copenhagen%202024%20Contenders%20Sticker%20Capsule ~ 0
|
|
@@ -187,8 +169,6 @@ https://steamcommunity.com/market/listings/730/Copenhagen%202024%20Champions%20A
|
|
|
187
169
|
https://steamcommunity.com/market/listings/730/Copenhagen%202024%20Challengers%20Autograph%20Capsule ~ 0
|
|
188
170
|
https://steamcommunity.com/market/listings/730/Copenhagen%202024%20Legends%20Autograph%20Capsule ~ 0
|
|
189
171
|
https://steamcommunity.com/market/listings/730/Copenhagen%202024%20Contenders%20Autograph%20Capsule ~ 0
|
|
190
|
-
|
|
191
|
-
[Shanghai 2024 Sticker Capsule]
|
|
192
172
|
https://steamcommunity.com/market/listings/730/Shanghai%202024%20Legends%20Sticker%20Capsule ~ 0
|
|
193
173
|
https://steamcommunity.com/market/listings/730/Shanghai%202024%20Challengers%20Sticker%20Capsule ~ 0
|
|
194
174
|
https://steamcommunity.com/market/listings/730/Shanghai%202024%20Contenders%20Sticker%20Capsule ~ 0
|
|
@@ -196,8 +176,6 @@ https://steamcommunity.com/market/listings/730/Shanghai%202024%20Champions%20Aut
|
|
|
196
176
|
https://steamcommunity.com/market/listings/730/Shanghai%202024%20Challengers%20Autograph%20Capsule ~ 0
|
|
197
177
|
https://steamcommunity.com/market/listings/730/Shanghai%202024%20Legends%20Autograph%20Capsule ~ 0
|
|
198
178
|
https://steamcommunity.com/market/listings/730/Shanghai%202024%20Contenders%20Autograph%20Capsule ~ 0
|
|
199
|
-
|
|
200
|
-
[Austin 2025 Sticker Capsule]
|
|
201
179
|
https://steamcommunity.com/market/listings/730/Austin%202025%20Legends%20Sticker%20Capsule ~ 0
|
|
202
180
|
https://steamcommunity.com/market/listings/730/Austin%202025%20Challengers%20Sticker%20Capsule ~ 0
|
|
203
181
|
https://steamcommunity.com/market/listings/730/Austin%202025%20Contenders%20Sticker%20Capsule ~ 0
|
|
@@ -205,3 +183,5 @@ https://steamcommunity.com/market/listings/730/Austin%202025%20Champions%20Autog
|
|
|
205
183
|
https://steamcommunity.com/market/listings/730/Austin%202025%20Challengers%20Autograph%20Capsule ~ 0
|
|
206
184
|
https://steamcommunity.com/market/listings/730/Austin%202025%20Legends%20Autograph%20Capsule ~ 0
|
|
207
185
|
https://steamcommunity.com/market/listings/730/Austin%202025%20Contenders%20Autograph%20Capsule ~ 0
|
|
186
|
+
|
|
187
|
+
[Others]
|
|
@@ -11,6 +11,9 @@ const itemsGameLink =
|
|
|
11
11
|
const translationsCacheFile = path.join(__dirname, "translations.json");
|
|
12
12
|
const itemsCacheFile = path.join(__dirname, "items.json");
|
|
13
13
|
|
|
14
|
+
const translationRegex = /"(.+?)"\s+"(.+?)"/;
|
|
15
|
+
const souvenirRegex = /^csgo_crate_[a-z0-9]+_promo.*/;
|
|
16
|
+
|
|
14
17
|
class ItemNameConverter {
|
|
15
18
|
constructor() {
|
|
16
19
|
this.translations = {};
|
|
@@ -38,7 +41,7 @@ class ItemNameConverter {
|
|
|
38
41
|
const res = await axios.get(translationsLink);
|
|
39
42
|
const lines = res.data.split(/\n/);
|
|
40
43
|
for (const line of lines) {
|
|
41
|
-
const match = line.match(
|
|
44
|
+
const match = line.match(translationRegex);
|
|
42
45
|
if (match) {
|
|
43
46
|
this.translations[match[1].toLowerCase()] = match[2];
|
|
44
47
|
}
|
|
@@ -174,26 +177,72 @@ class ItemNameConverter {
|
|
|
174
177
|
|
|
175
178
|
getItemType(item) {
|
|
176
179
|
const def = this.items[item.def_index];
|
|
177
|
-
if (def === undefined) return "
|
|
180
|
+
if (def === undefined) return "Unknown";
|
|
178
181
|
|
|
179
182
|
if (def.item_name !== undefined) {
|
|
180
183
|
let translatedName =
|
|
181
184
|
def.item_name.replace("#", "").toLowerCase() || def.item_name;
|
|
182
185
|
if (
|
|
183
|
-
translatedName.startsWith("csgo_crate_sticker_pack")
|
|
186
|
+
(translatedName.startsWith("csgo_crate_sticker_pack") &&
|
|
187
|
+
(translatedName.includes("2014") ||
|
|
188
|
+
translatedName.includes("2015") ||
|
|
189
|
+
translatedName.includes("contenders") ||
|
|
190
|
+
translatedName.includes("challengers") ||
|
|
191
|
+
translatedName.includes("legends"))) ||
|
|
184
192
|
translatedName.startsWith("csgo_crate_signature_pack")
|
|
185
193
|
) {
|
|
186
|
-
return "
|
|
187
|
-
} else if (translatedName.startsWith("
|
|
188
|
-
return "
|
|
194
|
+
return "Major Sticker Capsules";
|
|
195
|
+
} else if (translatedName.startsWith("csgo_crate_sticker_pack")) {
|
|
196
|
+
return "Sticker Capsules";
|
|
197
|
+
} else if (translatedName.startsWith("csgo_crate_patch_pack")) {
|
|
198
|
+
return "Patch Packs";
|
|
199
|
+
} else if (translatedName.match(souvenirRegex)) {
|
|
200
|
+
return "Souvenirs";
|
|
201
|
+
} else if (
|
|
202
|
+
translatedName.startsWith("csgo_crate_community") ||
|
|
203
|
+
translatedName.startsWith("csgo_crate_gamma") ||
|
|
204
|
+
translatedName.startsWith("csgo_crate_valve") ||
|
|
205
|
+
translatedName.startsWith("csgo_crate_esports") ||
|
|
206
|
+
translatedName.startsWith("csgo_crate_operation")
|
|
207
|
+
) {
|
|
208
|
+
return "Cases";
|
|
189
209
|
} else if (translatedName.startsWith("csgo_tool_spray")) {
|
|
190
|
-
return "
|
|
210
|
+
return "Graffitis";
|
|
191
211
|
} else if (translatedName.startsWith("csgo_tool_sticker")) {
|
|
192
|
-
return "
|
|
212
|
+
return "Stickers";
|
|
213
|
+
} else if (translatedName.startsWith("csgo_tool_patch")) {
|
|
214
|
+
return "Patches";
|
|
215
|
+
} else if (translatedName.startsWith("csgo_tool_keychain")) {
|
|
216
|
+
return "Charms";
|
|
217
|
+
} else if (translatedName.startsWith("csgo_customplayer")) {
|
|
218
|
+
return "Agents";
|
|
219
|
+
} else if (translatedName.startsWith("csgo_collectible_pin")) {
|
|
220
|
+
return "Collectible Pins";
|
|
221
|
+
} else if (translatedName.startsWith("coupon_pins")) {
|
|
222
|
+
return "Pins Capsules";
|
|
193
223
|
}
|
|
194
224
|
}
|
|
195
225
|
|
|
196
|
-
|
|
226
|
+
if (item.quality === 3) {
|
|
227
|
+
return "Special Items";
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (def.prefab !== undefined) {
|
|
231
|
+
let prefab = this.prefabs[def.prefab];
|
|
232
|
+
if (
|
|
233
|
+
prefab !== undefined &&
|
|
234
|
+
prefab.image_inventory !== undefined &&
|
|
235
|
+
prefab.image_inventory.startsWith("econ/weapons/base_weapons")
|
|
236
|
+
) {
|
|
237
|
+
return "Skins";
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (this.getItemName(item).startsWith("Music Kit |")) {
|
|
242
|
+
return "Music Kits";
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return "Others";
|
|
197
246
|
}
|
|
198
247
|
|
|
199
248
|
getItemTradable(item) {
|
|
@@ -204,11 +253,13 @@ class ItemNameConverter {
|
|
|
204
253
|
let translatedName =
|
|
205
254
|
def.item_name.replace("#", "").toLowerCase() || def.item_name;
|
|
206
255
|
if (
|
|
207
|
-
translatedName.startsWith("csgo_collectible")
|
|
256
|
+
(translatedName.startsWith("csgo_collectible") &&
|
|
257
|
+
!translatedName.startsWith("csgo_collectible_pin")) ||
|
|
208
258
|
translatedName.startsWith("csgo_tournamentpass") ||
|
|
209
259
|
translatedName.startsWith("csgo_tournamentjournal") ||
|
|
210
260
|
translatedName.startsWith("csgo_ticket") ||
|
|
211
|
-
translatedName.startsWith("csgo_tool_casket_tag")
|
|
261
|
+
translatedName.startsWith("csgo_tool_casket_tag") ||
|
|
262
|
+
translatedName.startsWith("sfui_wpnhud_c4")
|
|
212
263
|
) {
|
|
213
264
|
return false;
|
|
214
265
|
}
|
|
@@ -221,14 +272,6 @@ class ItemNameConverter {
|
|
|
221
272
|
return false;
|
|
222
273
|
}
|
|
223
274
|
|
|
224
|
-
// Base weapons with stickers/name tags
|
|
225
|
-
if (
|
|
226
|
-
def.image_inventory !== undefined &&
|
|
227
|
-
def.image_inventory.startsWith("econ/weapons/base_weapons")
|
|
228
|
-
) {
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
275
|
// Base weapons with stickers/name tags
|
|
233
276
|
if (
|
|
234
277
|
item.paint_index === undefined &&
|
|
@@ -239,7 +282,10 @@ class ItemNameConverter {
|
|
|
239
282
|
if (
|
|
240
283
|
prefab !== undefined &&
|
|
241
284
|
prefab.image_inventory !== undefined &&
|
|
242
|
-
prefab.image_inventory.startsWith("econ/weapons/base_weapons")
|
|
285
|
+
prefab.image_inventory.startsWith("econ/weapons/base_weapons") &&
|
|
286
|
+
!prefab.image_inventory.startsWith(
|
|
287
|
+
"econ/weapons/base_weapons/weapon_knife",
|
|
288
|
+
)
|
|
243
289
|
) {
|
|
244
290
|
return false;
|
|
245
291
|
}
|
cs2tracker/data/get_inventory.js
CHANGED
|
@@ -91,16 +91,12 @@ console.error = (...args) => {
|
|
|
91
91
|
|
|
92
92
|
if (importInventory) {
|
|
93
93
|
const inventoryItemCounts = await processInventory();
|
|
94
|
-
|
|
95
|
-
finalItemCounts[itemName] = (finalItemCounts[itemName] || 0) + count;
|
|
96
|
-
}
|
|
94
|
+
mergeItemCounts(finalItemCounts, inventoryItemCounts);
|
|
97
95
|
}
|
|
98
96
|
|
|
99
97
|
if (importStorageUnits) {
|
|
100
98
|
const storageUnitItemCounts = await processStorageUnits();
|
|
101
|
-
|
|
102
|
-
finalItemCounts[itemName] = (finalItemCounts[itemName] || 0) + count;
|
|
103
|
-
}
|
|
99
|
+
mergeItemCounts(finalItemCounts, storageUnitItemCounts);
|
|
104
100
|
}
|
|
105
101
|
|
|
106
102
|
paddedLog("Saving config...");
|
|
@@ -127,7 +123,7 @@ console.error = (...args) => {
|
|
|
127
123
|
const convertedItems =
|
|
128
124
|
nameConverter.convertInventory(prefilteredInventory);
|
|
129
125
|
const filteredItems = filterItems(convertedItems);
|
|
130
|
-
const itemCounts =
|
|
126
|
+
const itemCounts = groupAndCountItems(filteredItems);
|
|
131
127
|
paddedLog(`${filteredItems.length} items found in inventory`);
|
|
132
128
|
console.log(itemCounts);
|
|
133
129
|
return itemCounts;
|
|
@@ -145,10 +141,8 @@ console.error = (...args) => {
|
|
|
145
141
|
const items = await getCasketContentsAsync(cs2, unitId);
|
|
146
142
|
const convertedItems = nameConverter.convertInventory(items);
|
|
147
143
|
const filteredItems = filterItems(convertedItems);
|
|
148
|
-
const itemCounts =
|
|
149
|
-
|
|
150
|
-
finalItemCounts[itemName] = (finalItemCounts[itemName] || 0) + count;
|
|
151
|
-
}
|
|
144
|
+
const itemCounts = groupAndCountItems(filteredItems);
|
|
145
|
+
mergeItemCounts(finalItemCounts, itemCounts);
|
|
152
146
|
paddedLog(
|
|
153
147
|
`${filteredItems.length} items found in storage unit: ${unitIndex + 1}/${storageUnitIds.length}`,
|
|
154
148
|
);
|
|
@@ -181,16 +175,32 @@ console.error = (...args) => {
|
|
|
181
175
|
}
|
|
182
176
|
|
|
183
177
|
function filterItems(items) {
|
|
178
|
+
const otherItemTypes = [
|
|
179
|
+
"Skins",
|
|
180
|
+
"Special Items",
|
|
181
|
+
"Agents",
|
|
182
|
+
"Charms",
|
|
183
|
+
"Patches",
|
|
184
|
+
"Patch Packs",
|
|
185
|
+
"Souvenirs",
|
|
186
|
+
"Others",
|
|
187
|
+
"Sticker Capsules",
|
|
188
|
+
"Collectible Pins",
|
|
189
|
+
"Pins Capsules",
|
|
190
|
+
"Music Kits",
|
|
191
|
+
];
|
|
184
192
|
let filteredItems = [];
|
|
193
|
+
|
|
185
194
|
items.forEach((item) => {
|
|
186
195
|
if (!item.item_tradable) {
|
|
187
196
|
return;
|
|
188
197
|
}
|
|
189
198
|
if (
|
|
190
|
-
(item.item_type === "
|
|
191
|
-
(item.item_type === "
|
|
192
|
-
|
|
193
|
-
(item.item_type === "
|
|
199
|
+
(item.item_type === "Cases" && importCases) ||
|
|
200
|
+
(item.item_type === "Major Sticker Capsules" &&
|
|
201
|
+
importStickerCapsules) ||
|
|
202
|
+
(item.item_type === "Stickers" && importStickers) ||
|
|
203
|
+
(otherItemTypes.includes(item.item_type) && importOthers)
|
|
194
204
|
) {
|
|
195
205
|
filteredItems.push(item);
|
|
196
206
|
}
|
|
@@ -198,15 +208,39 @@ console.error = (...args) => {
|
|
|
198
208
|
return filteredItems;
|
|
199
209
|
}
|
|
200
210
|
|
|
201
|
-
function
|
|
202
|
-
let
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
itemCounts[item.item_name] = 1;
|
|
211
|
+
function groupAndCountItems(items) {
|
|
212
|
+
let groupedItems = items.reduce((acc, item) => {
|
|
213
|
+
const { item_name, item_type } = item;
|
|
214
|
+
|
|
215
|
+
if (!acc[item_type]) {
|
|
216
|
+
acc[item_type] = {};
|
|
208
217
|
}
|
|
209
|
-
|
|
210
|
-
|
|
218
|
+
|
|
219
|
+
if (!acc[item_type][item_name]) {
|
|
220
|
+
acc[item_type][item_name] = 0;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
acc[item_type][item_name]++;
|
|
224
|
+
return acc;
|
|
225
|
+
}, {});
|
|
226
|
+
|
|
227
|
+
return groupedItems;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function mergeItemCounts(finalItemCounts, currentItemCounts) {
|
|
231
|
+
for (const item_type in currentItemCounts) {
|
|
232
|
+
if (!finalItemCounts[item_type]) {
|
|
233
|
+
finalItemCounts[item_type] = {};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
for (const item_name in currentItemCounts[item_type]) {
|
|
237
|
+
if (!finalItemCounts[item_type][item_name]) {
|
|
238
|
+
finalItemCounts[item_type][item_name] = 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
finalItemCounts[item_type][item_name] +=
|
|
242
|
+
currentItemCounts[item_type][item_name];
|
|
243
|
+
}
|
|
244
|
+
}
|
|
211
245
|
}
|
|
212
246
|
})();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cs2tracker
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.19
|
|
4
4
|
Summary: Tracking the steam market prices of CS2 items
|
|
5
5
|
Home-page: https://github.com/ashiven/cs2tracker
|
|
6
6
|
Author: Jannik Novak
|
|
@@ -76,7 +76,7 @@ Dynamic: license-file
|
|
|
76
76
|
|
|
77
77
|
Simply download the program and run it:
|
|
78
78
|
|
|
79
|
-
- [Windows](https://github.com/ashiven/cs2tracker/releases/latest/download/cs2tracker-
|
|
79
|
+
- [Windows](https://github.com/ashiven/cs2tracker/releases/latest/download/cs2tracker-setup.exe)
|
|
80
80
|
- [Linux](https://github.com/ashiven/cs2tracker/releases/latest/download/cs2tracker-linux.zip)
|
|
81
81
|
|
|
82
82
|
#### Method 2: Install via Pip
|
|
@@ -120,29 +120,30 @@ This will open the config editor where you can change any setting by double clic
|
|
|
120
120
|
|
|
121
121
|
- Enable **Daily Background Calculations** to automatically run a daily calculation of your investment in the background.
|
|
122
122
|
- Use **Receive Discord Notifications** to receive a notification on your Discord server whenever the program has finished calculating your investment.
|
|
123
|
-
- You need to set up a [webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) in your Discord server and enter the webhook
|
|
123
|
+
- You need to set up a [webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) in your Discord server and enter the webhook URL into the `discord_webhook_url` field in the config `User Settings`.
|
|
124
124
|
- Enable **Proxy Requests** to prevent your requests from being rate limited by the steamcommunity server.
|
|
125
125
|
- You need to register for a free API key on [Crawlbase](crawlbase.com) and enter it into the `proxy_api_key` field in the config `User Settings`.
|
|
126
126
|
|
|
127
127
|
## FAQ
|
|
128
128
|
|
|
129
|
-
**Q: Is it safe to login with my Steam account?**
|
|
129
|
+
- **Q: Is it safe to login with my Steam account?**
|
|
130
|
+
- **A:** Yes, the program uses the [SteamUser](https://github.com/DoctorMcKay/node-steam-user?tab=readme-ov-file#methods-) and [Globaloffensive](https://github.com/DoctorMcKay/node-globaloffensive) libraries to sign in and import your Storage Units (the same method is used by [casemove](https://github.com/nombersDev/casemove)) and all of the login-related code is transparently available in [this file](cs2tracker/data/get_inventory.js).
|
|
130
131
|
|
|
131
|
-
**A:** Yes, the program uses the [SteamUser](https://github.com/DoctorMcKay/node-steam-user?tab=readme-ov-file#methods-) and [Globaloffensive](https://github.com/DoctorMcKay/node-globaloffensive) libraries to sign in and import your Storage Units (the same method is used by [casemove](https://github.com/nombersDev/casemove)) and all of the login-related code is transparently available in [this file](cs2tracker/data/get_inventory.js).
|
|
132
132
|
|
|
133
|
+
- **Q: Do I have to login with my Steam account?**
|
|
134
|
+
- **A:** No, you can also manually specify the number of items you own in the config editor.
|
|
133
135
|
|
|
134
|
-
**Q: Do I have to login with my Steam account?**
|
|
135
136
|
|
|
136
|
-
**
|
|
137
|
+
- **Q: Can I get VAC-banned for using this program?**
|
|
138
|
+
- **A:** No, this program does not interact with the game in any way and only reads your Storage Units.
|
|
137
139
|
|
|
138
140
|
|
|
139
|
-
**Q:
|
|
140
|
-
|
|
141
|
-
**A:** No, this program does not interact with the game in any way and only reads your Storage Units.
|
|
141
|
+
- **Q: Why does Windows Defender flag this program as potentially harmful?**
|
|
142
|
+
- **A:** This is because the program is not signed with a [Code Signing Certificate](https://www.globalsign.com/en/code-signing-certificate/what-is-code-signing-certificate), which Windows uses to verify the identity of publishers. These certificates are very expensive and not something I am willing to invest in for a free and open source project like this.
|
|
142
143
|
|
|
143
144
|
## Contributing
|
|
144
145
|
|
|
145
|
-
Please feel free to submit a pull request
|
|
146
|
+
Please feel free to submit a [pull request](https://github.com/ashiven/cs2tracker/pulls) or open an [issue](https://github.com/ashiven/cs2tracker/issues).
|
|
146
147
|
|
|
147
148
|
1. Fork the repository
|
|
148
149
|
2. Create a new branch: `git checkout -b feature-name`.
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
cs2tracker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
cs2tracker/__main__.py,sha256=Ub--oSMv48YzfWF1CZqYlkn1-HvZ7Bhxoc7urn1oY6o,249
|
|
3
|
-
cs2tracker/_version.py,sha256=
|
|
4
|
-
cs2tracker/config.py,sha256=
|
|
5
|
-
cs2tracker/constants.py,sha256=
|
|
3
|
+
cs2tracker/_version.py,sha256=H0zgjQHhg7kQrNE7IoxjBFCFnEnqqBnOnQe-ScWOyb4,513
|
|
4
|
+
cs2tracker/config.py,sha256=X-oPB4f_loD1KZAySdVWSQS6rwbah6OJTqI5nN1QYQs,10840
|
|
5
|
+
cs2tracker/constants.py,sha256=bdtX1pkaO2z8LZkNPqjMJDWIAxAIiw8UIUlxSt7ySgg,9478
|
|
6
6
|
cs2tracker/logs.py,sha256=K6uLoGjhHTlb6HLKIj6C5mz6R6bnZgltA6xwNVJ7Z8Y,6004
|
|
7
7
|
cs2tracker/main.py,sha256=9Jjn8-Hv9AzQLYjCjA6pwAmThE4HH1u3akF_c7atyl4,1046
|
|
8
8
|
cs2tracker/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
cs2tracker/app/app.py,sha256=yKe7CUgvDfiicE-4w-omMEwHvxqCQerQSFa_FtRtYWM,12012
|
|
10
|
-
cs2tracker/app/editor_frame.py,sha256=
|
|
10
|
+
cs2tracker/app/editor_frame.py,sha256=w-P6TEMLy5Kef1fr9u583TN0B9ad2iWRYwaBImUV-vo,28837
|
|
11
11
|
cs2tracker/app/history_frame.py,sha256=_QJdomghK10k0q0q4hyNm_RtzrbWa5jw3Rbq72smGT0,2001
|
|
12
12
|
cs2tracker/app/scraper_frame.py,sha256=GDRytrNe1gUMXA_ZcbTEcOVx2N81pQJGGYI-Fv-ww6o,4233
|
|
13
|
-
cs2tracker/data/config.ini,sha256=
|
|
14
|
-
cs2tracker/data/convert_inventory.js,sha256=
|
|
15
|
-
cs2tracker/data/get_inventory.js,sha256=
|
|
13
|
+
cs2tracker/data/config.ini,sha256=KWpFngdNqXNGYCjbjvAxr7rDvAJTpUu8aUZNfgSoIqs,14551
|
|
14
|
+
cs2tracker/data/convert_inventory.js,sha256=jouylRzNWUBwoezIUEy7D38c-ATzrx8VJqt_VbVjcHA,9634
|
|
15
|
+
cs2tracker/data/get_inventory.js,sha256=zMOkwxYpgnFt8IBTiZEa3WBAYk1ZGSjwNzbfktDO6io,6947
|
|
16
16
|
cs2tracker/data/output.csv,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
cs2tracker/scraper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
18
|
cs2tracker/scraper/background_task.py,sha256=4m1mr9veS3PUErTJhJVQNuBvmK1B8G9rPyVF_d8Cb9Q,6443
|
|
@@ -23,9 +23,9 @@ cs2tracker/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
23
23
|
cs2tracker/util/currency_conversion.py,sha256=h_VdipCFPzcgybWZ2VYknOd1VjHiqsFbEVed95FOe7U,2199
|
|
24
24
|
cs2tracker/util/padded_console.py,sha256=ZEbU5MxDA7Xbd-_SXIyezwGvb349OgAtjNPjFT_wrZw,1774
|
|
25
25
|
cs2tracker/util/tkinter.py,sha256=yR6rog4P7t_rDgH6ctssfQeJYFbqFXboiRv1V9c1vk4,1518
|
|
26
|
-
cs2tracker-2.1.
|
|
27
|
-
cs2tracker-2.1.
|
|
28
|
-
cs2tracker-2.1.
|
|
29
|
-
cs2tracker-2.1.
|
|
30
|
-
cs2tracker-2.1.
|
|
31
|
-
cs2tracker-2.1.
|
|
26
|
+
cs2tracker-2.1.19.dist-info/licenses/LICENSE,sha256=doPNswWMPXbkhplb9cnZLwJoqqS72pJPhkSib8kIF08,19122
|
|
27
|
+
cs2tracker-2.1.19.dist-info/METADATA,sha256=MpXvoZVeGZdjL7PlV_5VuCvZ98nHiC4Ck7gDCcK8Z1w,6914
|
|
28
|
+
cs2tracker-2.1.19.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
29
|
+
cs2tracker-2.1.19.dist-info/entry_points.txt,sha256=K8IwDIkg8QztSB9g9c89B9jR_2pG4QyJGrNs4z5RcZw,63
|
|
30
|
+
cs2tracker-2.1.19.dist-info/top_level.txt,sha256=2HB4xDDOxaU5BDc_yvdi9UlYLgL768n8aR-hRhFM6VQ,11
|
|
31
|
+
cs2tracker-2.1.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|