cs2tracker 2.1.9__py3-none-any.whl → 2.1.11__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/application.py DELETED
@@ -1,270 +0,0 @@
1
- import ctypes
2
- import tkinter as tk
3
- from shutil import copy
4
- from subprocess import Popen
5
- from threading import Thread
6
- from tkinter import messagebox
7
- from typing import cast
8
-
9
- import matplotlib.pyplot as plt
10
- from matplotlib.axes import Axes
11
- from matplotlib.dates import DateFormatter
12
-
13
- from cs2tracker.constants import (
14
- CONFIG_FILE,
15
- CONFIG_FILE_BACKUP,
16
- ICON_FILE,
17
- OS,
18
- OUTPUT_FILE,
19
- POWERSHELL_COLORIZE_OUTPUT,
20
- PYTHON_EXECUTABLE,
21
- RUNNING_IN_EXE,
22
- TEXT_EDITOR,
23
- OSType,
24
- )
25
- from cs2tracker.scraper import Scraper
26
-
27
- APPLICATION_NAME = "CS2Tracker"
28
-
29
- WINDOW_SIZE = "550x500"
30
- BACKGROUND_COLOR = "#1e1e1e"
31
- BUTTON_COLOR = "#3c3f41"
32
- BUTTON_HOVER_COLOR = "#505354"
33
- BUTTON_ACTIVE_COLOR = "#5c5f61"
34
- FONT_STYLE = "Segoe UI"
35
- FONT_COLOR = "white"
36
-
37
- SCRAPER_WINDOW_HEIGHT = 40
38
- SCRAPER_WINDOW_WIDTH = 120
39
- SCRAPER_WINDOW_BACKGROUND_COLOR = "Black"
40
-
41
-
42
- class Application:
43
- def __init__(self):
44
- self.scraper = Scraper()
45
-
46
- def run(self):
47
- """Run the main application window with buttons for scraping prices, editing the
48
- configuration, showing history in a chart, and editing the log file.
49
- """
50
- application_window = self._configure_window()
51
- application_window.mainloop()
52
-
53
- def _add_button(self, frame, text, command):
54
- """Create and style a button for the main application window."""
55
- button_style = {
56
- "font": (FONT_STYLE, 12),
57
- "fg": FONT_COLOR,
58
- "bg": BUTTON_COLOR,
59
- "activebackground": BUTTON_ACTIVE_COLOR,
60
- }
61
- button = tk.Button(frame, text=text, command=command, **button_style)
62
- button.pack(pady=5, fill="x")
63
- button.bind("<Enter>", lambda _: button.config(bg=BUTTON_HOVER_COLOR))
64
- button.bind("<Leave>", lambda _: button.config(bg=BUTTON_COLOR))
65
- return button
66
-
67
- def _add_checkbox(self, frame, text, variable, command):
68
- checkbox = tk.Checkbutton(
69
- frame,
70
- text=text,
71
- variable=variable,
72
- command=command,
73
- bg=BACKGROUND_COLOR,
74
- fg=FONT_COLOR,
75
- selectcolor=BUTTON_COLOR,
76
- activebackground=BACKGROUND_COLOR,
77
- font=(FONT_STYLE, 10),
78
- anchor="w",
79
- padx=20,
80
- )
81
- checkbox.pack(fill="x", anchor="w", pady=2)
82
-
83
- def _configure_window(self):
84
- """Configure the main application window UI and add buttons for the main
85
- functionalities.
86
- """
87
- window = tk.Tk()
88
- window.title(APPLICATION_NAME)
89
- window.geometry(WINDOW_SIZE)
90
- window.configure(bg=BACKGROUND_COLOR)
91
- if OS == OSType.WINDOWS:
92
- app_id = "cs2tracker.unique.id"
93
- ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(app_id)
94
- icon = tk.PhotoImage(file=ICON_FILE)
95
- window.wm_iconphoto(False, icon)
96
-
97
- frame = tk.Frame(window, bg=BACKGROUND_COLOR, padx=30, pady=30)
98
- frame.pack(expand=True, fill="both")
99
-
100
- label = tk.Label(
101
- frame,
102
- text=f"Welcome to {APPLICATION_NAME}!",
103
- font=(FONT_STYLE, 16, "bold"),
104
- fg=FONT_COLOR,
105
- bg=BACKGROUND_COLOR,
106
- )
107
- label.pack(pady=(0, 30))
108
-
109
- self._add_button(frame, "Run!", self.scrape_prices)
110
- self._add_button(frame, "Edit Config", self._edit_config)
111
- self._add_button(frame, "Reset Config", self._confirm_reset_config)
112
- self._add_button(frame, "Show History (Chart)", self._draw_plot)
113
- self._add_button(frame, "Show History (File)", self._edit_log_file)
114
-
115
- checkbox_frame = tk.Frame(frame, bg=BACKGROUND_COLOR)
116
- checkbox_frame.pack(pady=(20, 0), fill="x")
117
-
118
- background_checkbox_value = tk.BooleanVar(value=self.scraper.identify_background_task())
119
- self._add_checkbox(
120
- checkbox_frame,
121
- "Daily Background Calculations",
122
- background_checkbox_value,
123
- lambda: self._toggle_background_task(background_checkbox_value.get()),
124
- )
125
-
126
- discord_webhook_checkbox_value = tk.BooleanVar(
127
- value=self.scraper.config.getboolean(
128
- "App Settings", "discord_notifications", fallback=False
129
- )
130
- )
131
- self._add_checkbox(
132
- checkbox_frame,
133
- "Receive Discord Notifications",
134
- discord_webhook_checkbox_value,
135
- lambda: self._toggle_discord_webhook(discord_webhook_checkbox_value.get()),
136
- )
137
-
138
- use_proxy_checkbox_value = tk.BooleanVar(
139
- value=self.scraper.config.getboolean("App Settings", "use_proxy", fallback=False)
140
- )
141
- self._add_checkbox(
142
- checkbox_frame,
143
- "Proxy Requests",
144
- use_proxy_checkbox_value,
145
- lambda: self._toggle_use_proxy(use_proxy_checkbox_value.get()),
146
- )
147
-
148
- return window
149
-
150
- def _construct_scraper_command_windows(self):
151
- """Construct the command to run the scraper in a new window for Windows."""
152
- get_size = "$size = $Host.UI.RawUI.WindowSize;"
153
- set_size = "$Host.UI.RawUI.WindowSize = $size;"
154
- set_window_title = f"$Host.UI.RawUI.WindowTitle = '{APPLICATION_NAME}';"
155
- set_window_width = (
156
- f"$size.Width = [Math]::Min({SCRAPER_WINDOW_WIDTH}, $Host.UI.RawUI.BufferSize.Width);"
157
- )
158
- set_window_height = f"$size.Height = {SCRAPER_WINDOW_HEIGHT};"
159
- set_background_color = (
160
- f"$Host.UI.RawUI.BackgroundColor = '{SCRAPER_WINDOW_BACKGROUND_COLOR}';"
161
- )
162
- clear = "Clear-Host;"
163
-
164
- if RUNNING_IN_EXE:
165
- # The python executable is set as the executable itself in PyInstaller
166
- scraper_cmd = f"{PYTHON_EXECUTABLE} --only-scrape | {POWERSHELL_COLORIZE_OUTPUT}"
167
- else:
168
- scraper_cmd = f"{PYTHON_EXECUTABLE} -m cs2tracker --only-scrape"
169
-
170
- cmd = (
171
- 'start powershell -NoExit -Command "& {'
172
- + set_window_title
173
- + get_size
174
- + set_window_width
175
- + set_window_height
176
- + set_size
177
- + set_background_color
178
- + clear
179
- + scraper_cmd
180
- + '}"'
181
- )
182
- return cmd
183
-
184
- def _construct_scraper_command(self):
185
- """Construct the command to run the scraper in a new window."""
186
- if OS == OSType.WINDOWS:
187
- return self._construct_scraper_command_windows()
188
- else:
189
- # TODO: Implement for Linux
190
- return ""
191
-
192
- def scrape_prices(self):
193
- """Scrape prices from the configured sources, print the total, and save the
194
- results to a file.
195
- """
196
- if OS == OSType.WINDOWS:
197
- scraper_cmd = self._construct_scraper_command()
198
- Popen(scraper_cmd, shell=True)
199
- else:
200
- # TODO: implement external window for Linux
201
- self.scraper.scrape_prices()
202
-
203
- def _edit_config(self):
204
- """Edit the configuration file using the specified text editor."""
205
- _popen_and_call(
206
- popen_args={"args": [TEXT_EDITOR, CONFIG_FILE], "shell": True},
207
- callback=self.scraper.parse_config,
208
- )
209
-
210
- def _confirm_reset_config(self):
211
- confirm = messagebox.askokcancel(
212
- "Reset Config", "Are you sure you want to reset the config file?"
213
- )
214
- if confirm:
215
- self._reset_config()
216
-
217
- def _reset_config(self):
218
- """Reset the configuration file to its default state."""
219
- copy(CONFIG_FILE_BACKUP, CONFIG_FILE)
220
- self.scraper.parse_config()
221
-
222
- def _draw_plot(self):
223
- """Draw a plot of the scraped prices over time."""
224
- dates, dollars, euros = self.scraper.read_price_log()
225
-
226
- fig, ax_raw = plt.subplots(figsize=(10, 8), num="CS2Tracker Price History")
227
- fig.suptitle("CS2Tracker Price History", fontsize=16)
228
- fig.autofmt_xdate()
229
-
230
- ax = cast(Axes, ax_raw)
231
- ax.plot(dates, dollars, label="Dollars")
232
- ax.plot(dates, euros, label="Euros")
233
- ax.legend()
234
- date_formatter = DateFormatter("%d-%m-%Y")
235
- ax.xaxis.set_major_formatter(date_formatter)
236
-
237
- plt.show()
238
-
239
- def _edit_log_file(self):
240
- """Opens the file containing past price calculations."""
241
- Popen([TEXT_EDITOR, OUTPUT_FILE], shell=True)
242
-
243
- def _toggle_background_task(self, enabled: bool):
244
- """Toggle whether a daily price calculation should run in the background."""
245
- self.scraper.toggle_background_task(enabled)
246
-
247
- def _toggle_use_proxy(self, enabled: bool):
248
- """Toggle whether the scraper should use proxy servers for requests."""
249
- self.scraper.toggle_use_proxy(enabled)
250
-
251
- def _toggle_discord_webhook(self, enabled: bool):
252
- """Toggle whether the scraper should send notifications to a Discord webhook."""
253
- self.scraper.toggle_discord_webhook(enabled)
254
-
255
-
256
- def _popen_and_call(popen_args, callback):
257
- """
258
- Runs the given args in a subprocess.Popen, and then calls the function callback when
259
- the subprocess completes.
260
-
261
- Source: https://stackoverflow.com/questions/2581817/python-subprocess-callback-when-cmd-exits
262
- """
263
-
264
- def process_and_callback(popen_args, callback):
265
- process = Popen(**popen_args)
266
- process.wait()
267
- callback()
268
-
269
- thread = Thread(target=process_and_callback, args=(popen_args, callback), daemon=True)
270
- thread.start()