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 +6 -2
- GameSentenceMiner/config_gui.py +7 -2
- GameSentenceMiner/configuration.py +13 -0
- GameSentenceMiner/downloader/download_tools.py +28 -19
- GameSentenceMiner/electron_messaging.py +6 -0
- GameSentenceMiner/gametext.py +1 -1
- GameSentenceMiner/gsm.py +2 -0
- {gamesentenceminer-2.4.4.dist-info → gamesentenceminer-2.4.5.dist-info}/METADATA +1 -1
- {gamesentenceminer-2.4.4.dist-info → gamesentenceminer-2.4.5.dist-info}/RECORD +13 -12
- {gamesentenceminer-2.4.4.dist-info → gamesentenceminer-2.4.5.dist-info}/WHEEL +1 -1
- {gamesentenceminer-2.4.4.dist-info → gamesentenceminer-2.4.5.dist-info}/LICENSE +0 -0
- {gamesentenceminer-2.4.4.dist-info → gamesentenceminer-2.4.5.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.4.4.dist-info → gamesentenceminer-2.4.5.dist-info}/top_level.txt +0 -0
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
|
-
|
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:
|
GameSentenceMiner/config_gui.py
CHANGED
@@ -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
|
-
|
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
|
-
|
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.
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
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(
|
109
|
-
logger.debug(f"FFmpeg already installed at {
|
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.
|
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
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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(
|
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 {
|
151
|
+
logger.info(f"FFmpeg extracted to {ffmpeg_dir}.")
|
143
152
|
def main():
|
144
153
|
# Run dependency checks
|
145
154
|
download_obs_if_needed()
|
GameSentenceMiner/gametext.py
CHANGED
@@ -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,10 +1,11 @@
|
|
1
1
|
GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
GameSentenceMiner/anki.py,sha256=
|
3
|
-
GameSentenceMiner/config_gui.py,sha256
|
4
|
-
GameSentenceMiner/configuration.py,sha256=
|
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=
|
7
|
-
GameSentenceMiner/gsm.py,sha256=
|
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=
|
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.
|
22
|
-
gamesentenceminer-2.4.
|
23
|
-
gamesentenceminer-2.4.
|
24
|
-
gamesentenceminer-2.4.
|
25
|
-
gamesentenceminer-2.4.
|
26
|
-
gamesentenceminer-2.4.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|