GameSentenceMiner 2.4.4__py3-none-any.whl → 2.4.5__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.
GameSentenceMiner/anki.py CHANGED
@@ -3,6 +3,7 @@ import subprocess
3
3
  import threading
4
4
  import time
5
5
  import urllib.request
6
+ from datetime import datetime, timedelta
6
7
 
7
8
  import requests as req
8
9
 
@@ -197,15 +198,18 @@ def get_cards_by_sentence(sentence):
197
198
 
198
199
  return last_notes
199
200
 
201
+ last_connection_error = datetime.now()
200
202
 
201
203
  # Check for new Anki cards and save replay buffer if detected
202
204
  def check_for_new_cards():
203
- global previous_note_ids, first_run
205
+ global previous_note_ids, first_run, last_connection_error
204
206
  current_note_ids = set()
205
207
  try:
206
208
  current_note_ids = get_note_ids()
207
209
  except Exception as e:
208
- logger.error(f"Error fetching Anki notes: {e}")
210
+ if datetime.now() - last_connection_error > timedelta(seconds=10):
211
+ logger.error(f"Error fetching Anki notes, Make sure Anki is running, ankiconnect add-on is installed, and url/port is configured correctly in GSM Settings")
212
+ last_connection_error = datetime.now()
209
213
  return
210
214
  new_card_ids = current_note_ids - previous_note_ids
211
215
  if new_card_ids and not first_run:
@@ -6,6 +6,7 @@ import ttkbootstrap as ttk
6
6
 
7
7
  from GameSentenceMiner import obs, configuration
8
8
  from GameSentenceMiner.configuration import *
9
+ from GameSentenceMiner.electron_messaging import signal_restart_settings_change
9
10
  from GameSentenceMiner.package import get_current_version, get_latest_version
10
11
 
11
12
  settings_saved = False
@@ -187,7 +188,7 @@ class ConfigApp:
187
188
  )
188
189
 
189
190
  current_profile = self.profile_combobox.get()
190
-
191
+ prev_config = self.master_config.get_config()
191
192
  if profile_change:
192
193
  self.master_config.current_profile = current_profile
193
194
  else:
@@ -198,7 +199,11 @@ class ConfigApp:
198
199
  with open(get_config_path(), 'w') as file:
199
200
  file.write(self.master_config.to_json(indent=4))
200
201
 
201
- print("Settings saved successfully!")
202
+ logger.info("Settings saved successfully!")
203
+
204
+ if self.master_config.get_config().restart_required(prev_config):
205
+ logger.info("Restart Required for some settings to take affect!")
206
+ signal_restart_settings_change()
202
207
  settings_saved = True
203
208
  configuration.reload_config()
204
209
  for func in on_save:
@@ -233,6 +233,19 @@ class ProfileConfig:
233
233
 
234
234
  return self
235
235
 
236
+ def restart_required(self, previous):
237
+ previous: ProfileConfig
238
+ if any([previous.general.use_websocket != self.general.use_websocket,
239
+ previous.general.websocket_uri != self.general.websocket_uri,
240
+ previous.paths.folder_to_watch != self.paths.folder_to_watch,
241
+ previous.obs.open_obs != self.obs.open_obs,
242
+ previous.obs.host != self.obs.host,
243
+ previous.obs.port != self.obs.port
244
+ ]):
245
+ return True
246
+ return False
247
+
248
+
236
249
  @dataclass_json
237
250
  @dataclass
238
251
  class Config:
@@ -8,6 +8,8 @@ import zipfile
8
8
 
9
9
  from GameSentenceMiner.downloader.Untitled_json import scenes
10
10
  from GameSentenceMiner.configuration import get_app_directory, logger
11
+ from GameSentenceMiner.ffmpeg import get_ffmpeg_path, get_ffprobe_path
12
+ from GameSentenceMiner.obs import get_obs_path
11
13
 
12
14
  script_dir = os.path.dirname(os.path.abspath(__file__))
13
15
 
@@ -29,11 +31,15 @@ def copy_obs_settings(src, dest):
29
31
 
30
32
  def download_obs_if_needed():
31
33
  obs_path = os.path.join(get_app_directory(), 'obs-studio')
32
- if os.path.exists(obs_path):
34
+ obs_exe_path = get_obs_path()
35
+ if os.path.exists(obs_path) and os.path.exists(obs_exe_path):
33
36
  logger.debug(f"OBS already installed at {obs_path}.")
34
37
  return
35
38
 
36
- os.makedirs(obs_path, exist_ok=True)
39
+ if os.path.exists(obs_path) and not os.path.exists(obs_exe_path):
40
+ logger.info("OBS directory exists but executable is missing. Re-downloading OBS...")
41
+ shutil.rmtree(obs_path)
42
+
37
43
  latest_release_url = "https://api.github.com/repos/obsproject/obs-studio/releases/latest"
38
44
  with urllib.request.urlopen(latest_release_url) as response:
39
45
  latest_release = json.load(response)
@@ -54,11 +60,10 @@ def download_obs_if_needed():
54
60
  os.makedirs(download_dir, exist_ok=True)
55
61
  obs_installer = os.path.join(download_dir, "OBS.zip")
56
62
 
57
- if os.path.exists(obs_installer):
58
- logger.debug("OBS installer already exists. Skipping download.")
59
- else:
60
- logger.info(f"Downloading OBS from {obs_url}...")
61
- urllib.request.urlretrieve(obs_url, obs_installer)
63
+ logger.info(f"Downloading OBS from {obs_url}...")
64
+ urllib.request.urlretrieve(obs_url, obs_installer)
65
+
66
+ os.makedirs(obs_path, exist_ok=True)
62
67
 
63
68
  if platform.system() == "Windows":
64
69
 
@@ -103,13 +108,17 @@ def download_obs_if_needed():
103
108
  logger.error(f"Please install OBS manually from {obs_installer}")
104
109
 
105
110
  def download_ffmpeg_if_needed():
106
- ffmpeg_path = os.path.join(get_app_directory(), 'ffmpeg')
111
+ ffmpeg_dir = os.path.join(get_app_directory(), 'ffmpeg')
112
+ ffmpeg_exe_path = get_ffmpeg_path()
113
+ ffprobe_exe_path = get_ffprobe_path()
107
114
 
108
- if os.path.exists(ffmpeg_path):
109
- logger.debug(f"FFmpeg already installed at {ffmpeg_path}.")
115
+ if os.path.exists(ffmpeg_dir) and os.path.exists(ffmpeg_exe_path) and os.path.exists(ffprobe_exe_path):
116
+ logger.debug(f"FFmpeg already installed at {ffmpeg_dir}.")
110
117
  return
111
118
 
112
- os.makedirs(ffmpeg_path, exist_ok=True)
119
+ if os.path.exists(ffmpeg_dir) and (not os.path.exists(ffmpeg_exe_path) or not os.path.exists(ffprobe_exe_path)):
120
+ logger.info("FFmpeg directory exists but executables are missing. Re-downloading FFmpeg...")
121
+ shutil.rmtree(ffmpeg_dir)
113
122
 
114
123
  ffmpeg_url = {
115
124
  "Windows": "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip",
@@ -125,21 +134,21 @@ def download_ffmpeg_if_needed():
125
134
  os.makedirs(download_dir, exist_ok=True)
126
135
  ffmpeg_archive = os.path.join(download_dir, "ffmpeg.zip")
127
136
 
128
- if os.path.exists(ffmpeg_archive):
129
- logger.debug("FFmpeg archive already exists. Skipping download.")
130
- else:
131
- logger.info(f"Downloading FFmpeg from {ffmpeg_url}...")
132
- urllib.request.urlretrieve(ffmpeg_url, ffmpeg_archive)
133
- logger.info(f"FFmpeg downloaded. Extracting to {ffmpeg_path}...")
137
+ logger.info(f"Downloading FFmpeg from {ffmpeg_url}...")
138
+ urllib.request.urlretrieve(ffmpeg_url, ffmpeg_archive)
139
+ logger.info(f"FFmpeg downloaded. Extracting to {ffmpeg_dir}...")
140
+
141
+ os.makedirs(ffmpeg_dir, exist_ok=True)
142
+
134
143
  with zipfile.ZipFile(ffmpeg_archive, 'r') as zip_ref:
135
144
  for member in zip_ref.namelist():
136
145
  filename = os.path.basename(member)
137
146
  if filename: # Skip directories
138
147
  source = zip_ref.open(member)
139
- target = open(os.path.join(ffmpeg_path, filename), "wb")
148
+ target = open(os.path.join(ffmpeg_dir, filename), "wb")
140
149
  with source, target:
141
150
  shutil.copyfileobj(source, target)
142
- logger.info(f"FFmpeg extracted to {ffmpeg_path}.")
151
+ logger.info(f"FFmpeg extracted to {ffmpeg_dir}.")
143
152
  def main():
144
153
  # Run dependency checks
145
154
  download_obs_if_needed()
@@ -0,0 +1,6 @@
1
+ from GameSentenceMiner.configuration import logger
2
+
3
+
4
+ def signal_restart_settings_change():
5
+ logger.info("restart_for_settings_change")
6
+
@@ -118,7 +118,7 @@ async def listen_websocket():
118
118
  handle_new_text_event(current_clipboard)
119
119
  except (websockets.ConnectionClosed, ConnectionError) as e:
120
120
  if not reconnecting:
121
- logger.warning(f"Texthooker WebSocket connection lost: {e}. Attempting to Reconnect...")
121
+ logger.warning(f"Texthooker WebSocket connection lost: {e}. IF USING CLIPBOARD, WEBSOCKET NEEDS TO BE TURNED OFF IN SETTINGS. Attempting to Reconnect...")
122
122
  reconnecting = True
123
123
  await asyncio.sleep(5)
124
124
 
GameSentenceMiner/gsm.py CHANGED
@@ -21,6 +21,7 @@ from GameSentenceMiner import util
21
21
  from GameSentenceMiner import utility_gui
22
22
  from GameSentenceMiner.configuration import *
23
23
  from GameSentenceMiner.downloader.download_tools import download_obs_if_needed, download_ffmpeg_if_needed
24
+ from GameSentenceMiner.electron_messaging import signal_restart_settings_change
24
25
  from GameSentenceMiner.ffmpeg import get_audio_and_trim
25
26
  from GameSentenceMiner.gametext import get_text_event, get_mined_line
26
27
  from GameSentenceMiner.util import *
@@ -321,6 +322,7 @@ def switch_profile(icon, item):
321
322
  switch_profile_and_save(item.text)
322
323
  settings_window.reload_settings()
323
324
  update_icon()
325
+ signal_restart_settings_change()
324
326
 
325
327
 
326
328
  def run_tray():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: GameSentenceMiner
3
- Version: 2.4.4
3
+ Version: 2.4.5
4
4
  Summary: A tool for mining sentences from games. Update: Multi-Line Mining! Fixed!
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -1,10 +1,11 @@
1
1
  GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- GameSentenceMiner/anki.py,sha256=QBrA-WVQfK4KjKB2Wm1WDW7BlVy8MF6-1ByTApVzPVA,10576
3
- GameSentenceMiner/config_gui.py,sha256=RCZJwg5FQpx_J-8jS7v54ivKPBkjicHKpmzN2zh9yAA,51975
4
- GameSentenceMiner/configuration.py,sha256=fQNBQjmJn2ViBSYMFNuyC5CSklBk0xgMDSXC47CwDe0,14463
2
+ GameSentenceMiner/anki.py,sha256=YSz5gUTsKOdbogwHKtgFM7v7pREjdAwl7A0Wa_CXnKg,10918
3
+ GameSentenceMiner/config_gui.py,sha256=-V-GPyHFiN0EI-ZQLXq2yDVfCR_sP7afcjOZKsnGiO8,52312
4
+ GameSentenceMiner/configuration.py,sha256=mbyIs0h9xh85_ZJkuqTgspkdfl7jeifpvlYofu1e0mE,15001
5
+ GameSentenceMiner/electron_messaging.py,sha256=fBk9Ipo0jg2OZwYaKe1Qsm05P2ftrdTRGgFYob7ZA-k,139
5
6
  GameSentenceMiner/ffmpeg.py,sha256=P7rTOXYnwg2LWkXqC-pRNhoRIRUEU8EpV8IAfXFcFC4,11215
6
- GameSentenceMiner/gametext.py,sha256=OA7kLGTYj-GDhumZvzFgzEZ5cDpYHPhTANjUSciOKIY,6753
7
- GameSentenceMiner/gsm.py,sha256=t6hGJZKfMgiwgYUy7zWHlfmwyyLD-_eOEBeiTPpMFxk,19331
7
+ GameSentenceMiner/gametext.py,sha256=VjWNdjHwWXWIwNOfYxud7EwIyg7t6zZ3IkmMhh8Vc0c,6819
8
+ GameSentenceMiner/gsm.py,sha256=xLzeGYf0S0cNIdGdWN_eU_0JicVbz-yfXK1wyh7OvsA,19448
8
9
  GameSentenceMiner/model.py,sha256=oh8VVT8T1UKekbmP6MGNgQ8jIuQ_7Rg4GPzDCn2kJo8,1999
9
10
  GameSentenceMiner/notification.py,sha256=WBaQWoPNhW4XqdPBUmxPBgjk0ngzH_4v9zMQ-XQAKC8,2010
10
11
  GameSentenceMiner/obs.py,sha256=8ImXAVUWa4JdzwcBOEFShlZRZzh1dCvdpD1aEGhQfbU,6566
@@ -13,14 +14,14 @@ GameSentenceMiner/util.py,sha256=MITweiFYaefWQF5nR8tZ9yE6vd_b-fLuP0MP1Y1U4K0,472
13
14
  GameSentenceMiner/utility_gui.py,sha256=EtQUnCgTTdzKJE0iCJiHjjc_c6tc7JtI09LRg4_iy8Y,4555
14
15
  GameSentenceMiner/downloader/Untitled_json.py,sha256=RUUl2bbbCpUDUUS0fP0tdvf5FngZ7ILdA_J5TFYAXUQ,15272
15
16
  GameSentenceMiner/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- GameSentenceMiner/downloader/download_tools.py,sha256=584QVsv-btpJowMRrqSbWpKDCMhInQM0iGe-Yw0Q2p0,6298
17
+ GameSentenceMiner/downloader/download_tools.py,sha256=1x57nzktdlsUruTJxCPNpmHDDlhZ589NwRyAMP0Pq7E,6818
17
18
  GameSentenceMiner/vad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
19
  GameSentenceMiner/vad/silero_trim.py,sha256=syDJX_KbFmdyFFtnQqYTD0tICsUCJizYhs-atPgXtxA,1549
19
20
  GameSentenceMiner/vad/vosk_helper.py,sha256=HifeXKbEMrs81ZuuGxS67yAghu8TMXUP6Oan9i9dTxw,5938
20
21
  GameSentenceMiner/vad/whisper_helper.py,sha256=bpR1HVnJRn9H5u8XaHBqBJ6JwIjzqn-Fajps8QmQ4zc,3411
21
- gamesentenceminer-2.4.4.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
22
- gamesentenceminer-2.4.4.dist-info/METADATA,sha256=tjgtg86q80_uZz6ZDFx90kN0r-RfB9PEbENBSEVp8wg,10324
23
- gamesentenceminer-2.4.4.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
24
- gamesentenceminer-2.4.4.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
25
- gamesentenceminer-2.4.4.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
26
- gamesentenceminer-2.4.4.dist-info/RECORD,,
22
+ gamesentenceminer-2.4.5.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
23
+ gamesentenceminer-2.4.5.dist-info/METADATA,sha256=IApzmOm4iQV-UvU6U5uLFP0pJvVu3coMZlE8LxUfBLU,10324
24
+ gamesentenceminer-2.4.5.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
25
+ gamesentenceminer-2.4.5.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
26
+ gamesentenceminer-2.4.5.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
27
+ gamesentenceminer-2.4.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5