cs2tracker 2.1.12__py3-none-any.whl → 2.1.14__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.

@@ -1,25 +1,45 @@
1
+ import json
1
2
  import re
2
- from configparser import ConfigParser
3
-
4
- from cs2tracker.constants import CAPSULE_INFO, CONFIG_FILE
5
- from cs2tracker.util.padded_console import PaddedConsole
6
-
7
- console = PaddedConsole()
3
+ from configparser import ConfigParser, ParsingError
4
+ from urllib.parse import quote, unquote
8
5
 
6
+ from cs2tracker.constants import CAPSULE_PAGES, CONFIG_FILE, INVENTORY_IMPORT_FILE
7
+ from cs2tracker.util.padded_console import get_console
9
8
 
9
+ STEAM_MARKET_LISTING_BASEURL_CS2 = "https://steamcommunity.com/market/listings/730/"
10
10
  STEAM_MARKET_LISTING_REGEX = r"^https://steamcommunity.com/market/listings/\d+/.+$"
11
11
 
12
+ console = get_console()
13
+
12
14
 
13
15
  class ValidatedConfig(ConfigParser):
14
16
  def __init__(self):
15
17
  """Initialize the ValidatedConfig class."""
16
18
  super().__init__(delimiters=("~"), interpolation=None)
17
19
  self.optionxform = str # type: ignore
18
- super().read(CONFIG_FILE)
19
20
 
20
21
  self.valid = False
21
22
  self.last_error = None
22
- self._validate_config()
23
+ try:
24
+ self.load_from_file()
25
+ except (FileNotFoundError, ParsingError) as error:
26
+ console.error(f"Config error: {error}")
27
+ self.last_error = error
28
+
29
+ def delete_display_sections(self):
30
+ """
31
+ Delete all sections that are displayed to the user from the config.
32
+
33
+ (This excludes the internal App Settings section)
34
+ """
35
+ use_proxy = self.getboolean("App Settings", "use_proxy", fallback=False)
36
+ discord_notifications = self.getboolean(
37
+ "App Settings", "discord_notifications", fallback=False
38
+ )
39
+ self.clear()
40
+ self.add_section("App Settings")
41
+ self.set("App Settings", "use_proxy", str(use_proxy))
42
+ self.set("App Settings", "discord_notifications", str(discord_notifications))
23
43
 
24
44
  def _validate_config_sections(self):
25
45
  """Validate that the configuration file has all required sections."""
@@ -31,7 +51,7 @@ class ValidatedConfig(ConfigParser):
31
51
  raise ValueError("Missing 'Custom Items' section in the configuration file.")
32
52
  if not self.has_section("Cases"):
33
53
  raise ValueError("Missing 'Cases' section in the configuration file.")
34
- for capsule_section in CAPSULE_INFO:
54
+ for capsule_section in CAPSULE_PAGES:
35
55
  if not self.has_section(capsule_section):
36
56
  raise ValueError(f"Missing '{capsule_section}' section in the configuration file.")
37
57
 
@@ -48,16 +68,21 @@ class ValidatedConfig(ConfigParser):
48
68
  raise ValueError(
49
69
  f"Invalid value in 'Custom Items' section: {custom_item_href} = {custom_item_owned}"
50
70
  )
51
- for case_name, case_owned in self.items("Cases"):
71
+ for case_href, case_owned in self.items("Cases"):
72
+ if not re.match(STEAM_MARKET_LISTING_REGEX, case_href):
73
+ raise ValueError(
74
+ f"Invalid Steam market listing URL in 'Cases' section: {case_href}"
75
+ )
76
+
52
77
  if int(case_owned) < 0:
53
78
  raise ValueError(
54
- f"Invalid value in 'Cases' section: {case_name} = {case_owned}"
79
+ f"Invalid value in 'Cases' section: {case_href} = {case_owned}"
55
80
  )
56
- for capsule_section in CAPSULE_INFO:
57
- for capsule_name, capsule_owned in self.items(capsule_section):
81
+ for capsule_section in CAPSULE_PAGES:
82
+ for capsule_href, capsule_owned in self.items(capsule_section):
58
83
  if int(capsule_owned) < 0:
59
84
  raise ValueError(
60
- f"Invalid value in '{capsule_section}' section: {capsule_name} = {capsule_owned}"
85
+ f"Invalid value in '{capsule_section}' section: {capsule_href} = {capsule_owned}"
61
86
  )
62
87
  except ValueError as error:
63
88
  if "Invalid " in str(error):
@@ -77,18 +102,86 @@ class ValidatedConfig(ConfigParser):
77
102
  self._validate_config_values()
78
103
  self.valid = True
79
104
  except ValueError as error:
80
- console.print(f"[bold red][!] Config error: {error}")
105
+ console.error(f"Config error: {error}")
81
106
  self.valid = False
82
107
  self.last_error = error
83
108
 
109
+ def load_from_file(self):
110
+ """Load the configuration file and validate it."""
111
+ self.clear()
112
+ self.read(CONFIG_FILE)
113
+ self._validate_config()
114
+
84
115
  def write_to_file(self):
85
- """Write the current configuration to the configuration file."""
116
+ """Validate the current configuration and write it to the configuration file if
117
+ it is valid.
118
+ """
86
119
  self._validate_config()
87
120
 
88
121
  if self.valid:
89
122
  with open(CONFIG_FILE, "w", encoding="utf-8") as config_file:
90
123
  self.write(config_file)
91
124
 
125
+ def read_from_inventory_file(self):
126
+ """
127
+ Read an inventory file into the configuration.
128
+
129
+ This file is generated after a user automatically imports their inventory.
130
+ """
131
+ try:
132
+ with open(INVENTORY_IMPORT_FILE, "r", encoding="utf-8") as inventory_file:
133
+ inventory_data = json.load(inventory_file)
134
+ added_to_config = set()
135
+
136
+ for item_name, item_owned in inventory_data.items():
137
+ option_name_href = self.name_to_option(item_name, href=True)
138
+ for section in self.sections():
139
+ if option_name_href in self.options(section):
140
+ self.set(section, option_name_href, str(item_owned))
141
+ added_to_config.add(item_name)
142
+
143
+ for item_name, item_owned in inventory_data.items():
144
+ if item_name not in added_to_config:
145
+ url_encoded_item_name = quote(item_name)
146
+ listing_url = f"{STEAM_MARKET_LISTING_BASEURL_CS2}{url_encoded_item_name}"
147
+ self.set("Custom Items", listing_url, str(item_owned))
148
+
149
+ self.write_to_file()
150
+ except (FileNotFoundError, json.JSONDecodeError) as error:
151
+ console.error(f"Error reading inventory file: {error}")
152
+ self.last_error = error
153
+ self.valid = False
154
+
155
+ def option_to_name(self, option, href=False):
156
+ """
157
+ Convert an internal option representation to a reader-friendly name.
158
+
159
+ :param option: The internal option representation to convert.
160
+ :param custom: If True, the option is for a custom item.
161
+ :return: The reader-friendly name.
162
+ """
163
+ if href:
164
+ converted_option = unquote(option.split("/")[-1])
165
+ else:
166
+ converted_option = option.replace("_", " ").title()
167
+
168
+ return converted_option
169
+
170
+ def name_to_option(self, name, href=False):
171
+ """
172
+ Convert a reader-friendly name to an internal option representation.
173
+
174
+ :param name: The reader-friendly name to convert.
175
+ :param custom: If True, the name is for a custom item.
176
+ :return: The internal option representation.
177
+ """
178
+ if href:
179
+ converted_name = STEAM_MARKET_LISTING_BASEURL_CS2 + quote(name)
180
+ else:
181
+ converted_name = name.replace(" ", "_").lower()
182
+
183
+ return converted_name
184
+
92
185
  def toggle_use_proxy(self, enabled: bool):
93
186
  """
94
187
  Toggle the use of proxies for requests. This will update the configuration file.
@@ -115,3 +208,11 @@ class ValidatedConfig(ConfigParser):
115
208
  console.print(
116
209
  f"[bold green]{'[+] Enabled' if enabled else '[-] Disabled'} Discord webhook notifications."
117
210
  )
211
+
212
+
213
+ config = ValidatedConfig()
214
+
215
+
216
+ def get_config():
217
+ """Accessor function to retrieve the current configuration."""
218
+ return config
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: cs2tracker
3
+ Version: 2.1.14
4
+ Summary: Tracking the steam market prices of CS2 items
5
+ Home-page: https://github.com/ashiven/cs2tracker
6
+ Author: Jannik Novak
7
+ Author-email: nevisha@pm.me
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Requires-Python: >=3.11
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: numpy==1.26.4
15
+ Requires-Dist: beautifulsoup4==4.11.1
16
+ Requires-Dist: CurrencyConverter==0.17.9
17
+ Requires-Dist: matplotlib==3.7.0
18
+ Requires-Dist: Requests==2.31.0
19
+ Requires-Dist: rich==13.6.0
20
+ Requires-Dist: tenacity==8.2.2
21
+ Requires-Dist: urllib3==2.1.0
22
+ Requires-Dist: sv_ttk==2.6.1
23
+ Requires-Dist: tksheet==7.5.12
24
+ Requires-Dist: nodejs-bin==18.4.0a4
25
+ Requires-Dist: ttk-text==0.2.0
26
+ Requires-Dist: requests-cache==1.2.1
27
+ Dynamic: license-file
28
+
29
+ <p align="center">
30
+ <h2 align="center">CS2Tracker</h2>
31
+ </p>
32
+
33
+ <p align="center">
34
+ A simple, elegant GUI tool to track CS2 item investments
35
+ </p>
36
+
37
+ <div align="center">
38
+
39
+ [![CC BY-NC-ND 4.0][cc-by-nc-nd-shield]][cc-by-nc-nd]
40
+ [![GitHub Release](https://img.shields.io/github/v/release/ashiven/cs2tracker)](https://github.com/ashiven/cs2tracker/releases)
41
+ [![PyPI version](https://badge.fury.io/py/cs2tracker.svg)](https://badge.fury.io/py/cs2tracker)
42
+ [![GitHub Issues or Pull Requests](https://img.shields.io/github/issues/ashiven/cs2tracker)](https://github.com/ashiven/cs2tracker/issues)
43
+ [![GitHub Issues or Pull Requests](https://img.shields.io/github/issues-pr/ashiven/cs2tracker)](https://github.com/ashiven/cs2tracker/pulls)
44
+ ![GitHub Repo stars](https://img.shields.io/github/stars/ashiven/cs2tracker)
45
+
46
+ <img src="https://github.com/user-attachments/assets/9585afb2-bf1a-473c-be5d-cccbb3349b9a"/>
47
+ </div>
48
+
49
+ ## Table of Contents
50
+
51
+ - [Features](#features)
52
+ - [Getting Started](#getting-started)
53
+ - [Prerequisites](#prerequisites)
54
+ - [Installation](#installation)
55
+ - [Usage](#usage)
56
+ - [Configuration](#configuration)
57
+ - [Advanced Features](#advanced-features)
58
+ - [Contributing](#contributing)
59
+ - [License](#license)
60
+
61
+ ## Features
62
+
63
+ - ⚡ Rapidly import your Storage Units
64
+ - 🔍 Track CS2 Steam Market prices
65
+ - 📈 View investment price history
66
+ - 🧾 Export/Import price data
67
+ - 📤 Discord notifications on updates
68
+ - 📅 Daily background calculations
69
+ - 🛡️ Proxy support to avoid rate limits
70
+
71
+ ## Getting Started
72
+
73
+ ### Prerequisites
74
+
75
+ - Download and install the latest versions of [Python](https://www.python.org/downloads/) and [Pip](https://pypi.org/project/pip/). (Required on Linux)
76
+ - Register for the [Crawlbase Smart Proxy API](https://crawlbase.com/) and retrieve your API key. (Optional)
77
+ - Create a [Discord Webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) to be notified about recent price updates. (Optional)
78
+
79
+ ### Installation
80
+
81
+ #### Option 1: Windows Executable
82
+
83
+ - Simply [download the latest executable](https://github.com/ashiven/cs2tracker/releases/latest/download/cs2tracker-windows.zip) and run it.
84
+
85
+ #### Option 2: Install via Pip
86
+
87
+ 1. Install the program:
88
+
89
+ ```bash
90
+ pip install cs2tracker
91
+ ```
92
+
93
+ 2. Run it:
94
+
95
+ ```bash
96
+ cs2tracker
97
+ ```
98
+
99
+ ## Usage
100
+
101
+ - Click **Run!** to gather the current market prices of your items and calculate the total amount in USD and EUR.
102
+ - The generated Excel sheet can be saved by right-clicking and then selecting **Save Sheet**.
103
+ - Use **Edit Config** to specify the numbers of items owned in the configuration.
104
+ - Click **Show History** to see a price chart consisting of past calculations.
105
+ - Use **Export / Import History** to export or import the price history to or from a CSV file.
106
+
107
+ ## Configuration
108
+
109
+ You can configure the app settings via the **Edit Config** option.
110
+ This will open the config editor where you can change any setting by double clicking on it or navigating to it with the arrow keys and hitting enter. On top of that, the config editor allows you to:
111
+
112
+ - Automatically import items from your Storage Units
113
+ - Manually Specify the number of items you own
114
+ - Add custom items that are not listed in the config
115
+ - Enter Discord webhook and Crawlbase proxy API keys
116
+
117
+ ## Advanced Features
118
+
119
+ - Enable **Daily Background Calculations** to automatically run a daily calculation of your investment in the background.
120
+ - Use **Receive Discord Notifications** to receive a notification on your Discord server whenever the program has finished calculating your investment.
121
+ - 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`.
122
+ - Enable **Proxy Requests** to prevent your requests from being rate limited by the steamcommunity server.
123
+ - 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`.
124
+
125
+ ## Contributing
126
+
127
+ Please feel free to submit a pull request or open an issue. See [issues](https://github.com/ashiven/cs2tracker/issues) and [pull requests](https://github.com/ashiven/cs2tracker/pulls) for current work.
128
+
129
+ 1. Fork the repository
130
+ 2. Create a new branch
131
+ 3. Make your changes
132
+ 4. Submit a PR
133
+
134
+ ## License
135
+
136
+ This project is licensed under the
137
+ [Creative Commons Attribution-NonCommercial-NoDerivs 4.0 International License][cc-by-nc-nd].
138
+
139
+ [![CC BY-NC-ND 4.0][cc-by-nc-nd-image]][cc-by-nc-nd]
140
+
141
+ [cc-by-nc-nd]: http://creativecommons.org/licenses/by-nc-nd/4.0/
142
+ [cc-by-nc-nd-image]: https://licensebuttons.net/l/by-nc-nd/4.0/88x31.png
143
+ [cc-by-nc-nd-shield]: https://img.shields.io/badge/License-CC%20BY--NC--ND%204.0-lightgrey.svg
144
+
145
+ ---
146
+
147
+ > GitHub [@ashiven](https://github.com/Ashiven) &nbsp;&middot;&nbsp;
148
+ > Twitter [ashiven\_](https://twitter.com/ashiven_)
@@ -0,0 +1,28 @@
1
+ cs2tracker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ cs2tracker/__main__.py,sha256=Ub--oSMv48YzfWF1CZqYlkn1-HvZ7Bhxoc7urn1oY6o,249
3
+ cs2tracker/_version.py,sha256=80wtCyj9QUrrEVvuEW7o-ILwCKz10sXaQFnSq4DOKBE,513
4
+ cs2tracker/constants.py,sha256=9E1CPVEohDmV_F2PLLrPRmtYAHHVDimbUFfohhjci1c,6742
5
+ cs2tracker/main.py,sha256=_Y8be0bVDaoO4SE-TZjJ0wpXjvXDYF3VPKC4f32nZc0,1019
6
+ cs2tracker/app/__init__.py,sha256=uqAxdDzoR2-2IrDc1riIU3Pi9vLEDwr68eg93-0RFmM,105
7
+ cs2tracker/app/application.py,sha256=wjUFt5RzRZ8gRqprtPaCTtHW_cEWS3DzmcdRz48vmFg,9135
8
+ cs2tracker/app/editor_frame.py,sha256=zbNaZOBhFCWjJrl-kCgdbBPafeRgEcYG31tDgMaZ3_s,21313
9
+ cs2tracker/app/scraper_frame.py,sha256=9m5tQFhPGCqWWtkgSG_XuH9ELj-km83lU93tSBqndNA,4007
10
+ cs2tracker/data/config.ini,sha256=oLm6Ggfqjr8coDZE4NAMVomZZDJqMia0VxNO3wCzHsQ,15059
11
+ cs2tracker/data/convert_inventory.js,sha256=5bEDfe9Rf2wYC4dIlmvjhbslfnuKuBBNjuTk67jEV9Q,5370
12
+ cs2tracker/data/get_inventory.js,sha256=YL0RJV1j2K0J20mRZVXSakwU8fpRtjyMLrAYFl0-rsM,5793
13
+ cs2tracker/data/output.csv,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ cs2tracker/scraper/__init__.py,sha256=kfUB9yfshSche92ZvTqQQYBkVqujRez46djPoa9u0YU,335
15
+ cs2tracker/scraper/background_task.py,sha256=1_lKnFWn9wuABpru58JdQbfDHjL0Up-7h6Nlcc4TsZ4,3671
16
+ cs2tracker/scraper/discord_notifier.py,sha256=-PdTRAtzMHTjDH17zguI0LKB7INITEohx0da0fWRdKI,2962
17
+ cs2tracker/scraper/parsers.py,sha256=BcCRU39RXtkpXOZouh2LLTDlCOJAFAJmyaQVVwK1i4A,6897
18
+ cs2tracker/scraper/scraper.py,sha256=sotDjZMrMxkM_bCOhPm9S-Pq82-pJp-8RPNcxtY9cPs,10462
19
+ cs2tracker/util/__init__.py,sha256=Pgltyrkotd5ijU-srmY5vaFP7gzz9itSAl2LfS-D7-E,322
20
+ cs2tracker/util/padded_console.py,sha256=u8SNbjvR_YyePhpiqREt4Kh4NiDI5NAPCPL5toqh8dg,1622
21
+ cs2tracker/util/price_logs.py,sha256=JuZ2ptDtxA-NzKjpG_4q0eeOr1IaUvVah-Qth6GrDDU,4165
22
+ cs2tracker/util/validated_config.py,sha256=ZsUTaahs08HBEoCM2XUzAHqjKeaeU3XzBNhGxr1kEfg,8740
23
+ cs2tracker-2.1.14.dist-info/licenses/LICENSE,sha256=doPNswWMPXbkhplb9cnZLwJoqqS72pJPhkSib8kIF08,19122
24
+ cs2tracker-2.1.14.dist-info/METADATA,sha256=hehgmIANx4SmR2lJOlurlsV54ERx9TVg3fi80No46kM,5782
25
+ cs2tracker-2.1.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
+ cs2tracker-2.1.14.dist-info/entry_points.txt,sha256=K8IwDIkg8QztSB9g9c89B9jR_2pG4QyJGrNs4z5RcZw,63
27
+ cs2tracker-2.1.14.dist-info/top_level.txt,sha256=2HB4xDDOxaU5BDc_yvdi9UlYLgL768n8aR-hRhFM6VQ,11
28
+ cs2tracker-2.1.14.dist-info/RECORD,,