GameSentenceMiner 2.4.10__py3-none-any.whl → 2.4.12__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/config_gui.py +13 -1
- GameSentenceMiner/configuration.py +3 -1
- GameSentenceMiner/gametext.py +28 -15
- {gamesentenceminer-2.4.10.dist-info → gamesentenceminer-2.4.12.dist-info}/METADATA +1 -1
- {gamesentenceminer-2.4.10.dist-info → gamesentenceminer-2.4.12.dist-info}/RECORD +9 -9
- {gamesentenceminer-2.4.10.dist-info → gamesentenceminer-2.4.12.dist-info}/LICENSE +0 -0
- {gamesentenceminer-2.4.10.dist-info → gamesentenceminer-2.4.12.dist-info}/WHEEL +0 -0
- {gamesentenceminer-2.4.10.dist-info → gamesentenceminer-2.4.12.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.4.10.dist-info → gamesentenceminer-2.4.12.dist-info}/top_level.txt +0 -0
GameSentenceMiner/config_gui.py
CHANGED
@@ -103,6 +103,7 @@ class ConfigApp:
|
|
103
103
|
config = ProfileConfig(
|
104
104
|
general=General(
|
105
105
|
use_websocket=self.websocket_enabled.get(),
|
106
|
+
use_clipboard=self.clipboard_enabled.get(),
|
106
107
|
websocket_uri=self.websocket_uri.get(),
|
107
108
|
open_config_on_startup=self.open_config_on_startup.get(),
|
108
109
|
texthook_replacement_regex=self.texthook_replacement_regex.get()
|
@@ -191,6 +192,10 @@ class ConfigApp:
|
|
191
192
|
messagebox.showerror("Configuration Error", "Cannot have Full Auto and Backfill mode on at the same time! Note: Backfill is a very niche workflow.")
|
192
193
|
return
|
193
194
|
|
195
|
+
if not config.general.use_websocket and not config.general.use_clipboard:
|
196
|
+
messagebox.showerror("Configuration Error", "Cannot have both Clipboard and Websocket Disabled.")
|
197
|
+
return
|
198
|
+
|
194
199
|
current_profile = self.profile_combobox.get()
|
195
200
|
prev_config = self.master_config.get_config()
|
196
201
|
if profile_change:
|
@@ -256,13 +261,20 @@ class ConfigApp:
|
|
256
261
|
general_frame = ttk.Frame(self.notebook)
|
257
262
|
self.notebook.add(general_frame, text='General')
|
258
263
|
|
259
|
-
ttk.Label(general_frame, text="Websocket Enabled
|
264
|
+
ttk.Label(general_frame, text="Websocket Enabled:").grid(row=self.current_row, column=0, sticky='W')
|
260
265
|
self.websocket_enabled = tk.BooleanVar(value=self.settings.general.use_websocket)
|
261
266
|
ttk.Checkbutton(general_frame, variable=self.websocket_enabled).grid(row=self.current_row, column=1,
|
262
267
|
sticky='W')
|
263
268
|
self.add_label_and_increment_row(general_frame, "Enable or disable WebSocket communication. Enabling this will disable the clipboard monitor. RESTART REQUIRED.",
|
264
269
|
row=self.current_row, column=2)
|
265
270
|
|
271
|
+
ttk.Label(general_frame, text="Clipboard Enabled:").grid(row=self.current_row, column=0, sticky='W')
|
272
|
+
self.clipboard_enabled = tk.BooleanVar(value=self.settings.general.use_clipboard)
|
273
|
+
ttk.Checkbutton(general_frame, variable=self.clipboard_enabled).grid(row=self.current_row, column=1,
|
274
|
+
sticky='W')
|
275
|
+
self.add_label_and_increment_row(general_frame, "Enable to allow GSM to see clipboard for text and line timing.",
|
276
|
+
row=self.current_row, column=2)
|
277
|
+
|
266
278
|
ttk.Label(general_frame, text="Websocket URI:").grid(row=self.current_row, column=0, sticky='W')
|
267
279
|
self.websocket_uri = ttk.Entry(general_frame)
|
268
280
|
self.websocket_uri.insert(0, self.settings.general.websocket_uri)
|
@@ -39,6 +39,7 @@ current_game = ''
|
|
39
39
|
@dataclass
|
40
40
|
class General:
|
41
41
|
use_websocket: bool = True
|
42
|
+
use_clipboard: bool = True
|
42
43
|
websocket_uri: str = 'localhost:6677'
|
43
44
|
open_config_on_startup: bool = False
|
44
45
|
texthook_replacement_regex: str = ""
|
@@ -63,7 +64,7 @@ class Anki:
|
|
63
64
|
sentence_field: str = "Sentence"
|
64
65
|
sentence_audio_field: str = "SentenceAudio"
|
65
66
|
picture_field: str = "Picture"
|
66
|
-
word_field: str = '
|
67
|
+
word_field: str = 'Expression'
|
67
68
|
previous_sentence_field: str = ''
|
68
69
|
previous_image_field: str = ''
|
69
70
|
custom_tags: List[str] = None # Initialize to None and set it in __post_init__
|
@@ -236,6 +237,7 @@ class ProfileConfig:
|
|
236
237
|
def restart_required(self, previous):
|
237
238
|
previous: ProfileConfig
|
238
239
|
if any([previous.general.use_websocket != self.general.use_websocket,
|
240
|
+
previous.general.use_clipboard != self.general.use_clipboard,
|
239
241
|
previous.general.websocket_uri != self.general.websocket_uri,
|
240
242
|
previous.paths.folder_to_watch != self.paths.folder_to_watch,
|
241
243
|
previous.obs.open_obs != self.obs.open_obs,
|
GameSentenceMiner/gametext.py
CHANGED
@@ -21,6 +21,7 @@ current_line_after_regex = ''
|
|
21
21
|
current_line_time = datetime.now()
|
22
22
|
|
23
23
|
reconnecting = False
|
24
|
+
websocket_connected = False
|
24
25
|
multi_mine_event_bus: Callable[[str, datetime], None] = None
|
25
26
|
|
26
27
|
@dataclass
|
@@ -89,6 +90,9 @@ class ClipboardMonitor(threading.Thread):
|
|
89
90
|
current_line = pyperclip.paste()
|
90
91
|
|
91
92
|
while True:
|
93
|
+
if websocket_connected:
|
94
|
+
time.sleep(1)
|
95
|
+
continue
|
92
96
|
current_clipboard = pyperclip.paste()
|
93
97
|
|
94
98
|
if current_clipboard != current_line:
|
@@ -98,13 +102,14 @@ class ClipboardMonitor(threading.Thread):
|
|
98
102
|
|
99
103
|
|
100
104
|
async def listen_websocket():
|
101
|
-
global current_line, current_line_time, line_history, reconnecting
|
105
|
+
global current_line, current_line_time, line_history, reconnecting, websocket_connected
|
102
106
|
while True:
|
103
107
|
try:
|
104
108
|
async with websockets.connect(f'ws://{get_config().general.websocket_uri}', ping_interval=None) as websocket:
|
105
109
|
if reconnecting:
|
106
|
-
logger.info(f"Texthooker WebSocket connected Successfully!")
|
110
|
+
logger.info(f"Texthooker WebSocket connected Successfully!" + " Disabling Clipboard Monitor." if get_config().general.use_clipboard else "")
|
107
111
|
reconnecting = False
|
112
|
+
websocket_connected = True
|
108
113
|
while True:
|
109
114
|
message = await websocket.recv()
|
110
115
|
|
@@ -117,8 +122,9 @@ async def listen_websocket():
|
|
117
122
|
if current_clipboard != current_line:
|
118
123
|
handle_new_text_event(current_clipboard)
|
119
124
|
except (websockets.ConnectionClosed, ConnectionError) as e:
|
125
|
+
websocket_connected = False
|
120
126
|
if not reconnecting:
|
121
|
-
logger.warning(f"Texthooker WebSocket connection lost
|
127
|
+
logger.warning(f"Texthooker WebSocket connection lost, Defaulting to clipboard if enabled. Attempting to Reconnect...")
|
122
128
|
reconnecting = True
|
123
129
|
await asyncio.sleep(5)
|
124
130
|
|
@@ -150,15 +156,19 @@ def start_text_monitor(send_to_mine_event_bus):
|
|
150
156
|
global multi_mine_event_bus
|
151
157
|
multi_mine_event_bus = send_to_mine_event_bus
|
152
158
|
if get_config().general.use_websocket:
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
159
|
+
threading.Thread(target=run_websocket_listener, daemon=True).start()
|
160
|
+
if get_config().general.use_clipboard:
|
161
|
+
if get_config().general.use_websocket:
|
162
|
+
logger.info("Both WebSocket and Clipboard monitoring are enabled. WebSocket will take precedence if connected.")
|
163
|
+
ClipboardMonitor().start()
|
157
164
|
|
158
165
|
|
159
166
|
def similar(a, b):
|
160
167
|
return SequenceMatcher(None, a, b).ratio()
|
161
168
|
|
169
|
+
def one_contains_the_other(a, b):
|
170
|
+
return a in b or b in a
|
171
|
+
|
162
172
|
|
163
173
|
def get_text_event(last_note) -> GameLine:
|
164
174
|
lines = line_history.values
|
@@ -166,6 +176,9 @@ def get_text_event(last_note) -> GameLine:
|
|
166
176
|
if not last_note:
|
167
177
|
return lines[-1]
|
168
178
|
|
179
|
+
if not lines:
|
180
|
+
raise Exception("No lines in history. Text is required from either clipboard or websocket for GSM to work. Please check your setup/config.")
|
181
|
+
|
169
182
|
sentence = last_note['fields'][get_config().anki.sentence_field]['value']
|
170
183
|
if not sentence:
|
171
184
|
return lines[-1]
|
@@ -173,7 +186,7 @@ def get_text_event(last_note) -> GameLine:
|
|
173
186
|
for line in reversed(lines):
|
174
187
|
similarity = similar(remove_html_tags(sentence), line.text)
|
175
188
|
logger.debug(f"Comparing: {remove_html_tags(sentence)} with {line.text} - Similarity: {similarity}")
|
176
|
-
if similarity >= 0.60 or line.text
|
189
|
+
if similarity >= 0.60 or one_contains_the_other(line.text, remove_html_tags(sentence)):
|
177
190
|
return line
|
178
191
|
|
179
192
|
logger.debug("Couldn't find a match in history, using last event")
|
@@ -193,21 +206,21 @@ def get_line_and_future_lines(last_note):
|
|
193
206
|
logger.debug(f"Comparing: {remove_html_tags(sentence)} with {line.text} - Similarity: {similarity}")
|
194
207
|
if found:
|
195
208
|
found_lines.append(line.text)
|
196
|
-
if similarity >= 0.60 or line.text
|
209
|
+
if similarity >= 0.60 or one_contains_the_other(line.text, remove_html_tags(sentence)): # 80% similarity threshold
|
197
210
|
found = True
|
198
211
|
found_lines.append(line.text)
|
199
212
|
return found_lines
|
200
213
|
|
201
214
|
def get_mined_line(last_note, lines):
|
202
215
|
if not last_note:
|
203
|
-
return lines[
|
216
|
+
return lines[-1]
|
204
217
|
|
205
218
|
sentence = last_note['fields'][get_config().anki.sentence_field]['value']
|
206
|
-
for
|
207
|
-
similarity = similar(remove_html_tags(sentence),
|
208
|
-
if similarity >= 0.60 or
|
209
|
-
return
|
210
|
-
return lines[
|
219
|
+
for line in lines:
|
220
|
+
similarity = similar(remove_html_tags(sentence), line.text)
|
221
|
+
if similarity >= 0.60 or one_contains_the_other(line.text, remove_html_tags(sentence)):
|
222
|
+
return line
|
223
|
+
return lines[-1]
|
211
224
|
|
212
225
|
|
213
226
|
def get_time_of_line(line):
|
@@ -1,10 +1,10 @@
|
|
1
1
|
GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
GameSentenceMiner/anki.py,sha256=YSz5gUTsKOdbogwHKtgFM7v7pREjdAwl7A0Wa_CXnKg,10918
|
3
|
-
GameSentenceMiner/config_gui.py,sha256=
|
4
|
-
GameSentenceMiner/configuration.py,sha256=
|
3
|
+
GameSentenceMiner/config_gui.py,sha256=s0U0Sj_WvrJ8GecSyj33tWMh-OyOcZ5yY1ddEc1cgwg,53456
|
4
|
+
GameSentenceMiner/configuration.py,sha256=_VxzRHCJPW2iJTW6gheD1d6-oaUbUQQnLsIiHjgjNcY,15186
|
5
5
|
GameSentenceMiner/electron_messaging.py,sha256=fBk9Ipo0jg2OZwYaKe1Qsm05P2ftrdTRGgFYob7ZA-k,139
|
6
6
|
GameSentenceMiner/ffmpeg.py,sha256=vkRvhsuXCL8-tGynobdLBnw4qNHUhTC33ITCCnjfZLM,11468
|
7
|
-
GameSentenceMiner/gametext.py,sha256=
|
7
|
+
GameSentenceMiner/gametext.py,sha256=YXjaZF130lkzU-I2dpZ5HoNrj3GSCG-7X9B04IFnetI,7551
|
8
8
|
GameSentenceMiner/gsm.py,sha256=E9Hpbyzrv8FEFGBs-4Hf60m3sk0ps3OQdvB1n42AhRU,20164
|
9
9
|
GameSentenceMiner/model.py,sha256=oh8VVT8T1UKekbmP6MGNgQ8jIuQ_7Rg4GPzDCn2kJo8,1999
|
10
10
|
GameSentenceMiner/notification.py,sha256=WBaQWoPNhW4XqdPBUmxPBgjk0ngzH_4v9zMQ-XQAKC8,2010
|
@@ -19,9 +19,9 @@ GameSentenceMiner/vad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
19
19
|
GameSentenceMiner/vad/silero_trim.py,sha256=syDJX_KbFmdyFFtnQqYTD0tICsUCJizYhs-atPgXtxA,1549
|
20
20
|
GameSentenceMiner/vad/vosk_helper.py,sha256=HifeXKbEMrs81ZuuGxS67yAghu8TMXUP6Oan9i9dTxw,5938
|
21
21
|
GameSentenceMiner/vad/whisper_helper.py,sha256=bpR1HVnJRn9H5u8XaHBqBJ6JwIjzqn-Fajps8QmQ4zc,3411
|
22
|
-
gamesentenceminer-2.4.
|
23
|
-
gamesentenceminer-2.4.
|
24
|
-
gamesentenceminer-2.4.
|
25
|
-
gamesentenceminer-2.4.
|
26
|
-
gamesentenceminer-2.4.
|
27
|
-
gamesentenceminer-2.4.
|
22
|
+
gamesentenceminer-2.4.12.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
23
|
+
gamesentenceminer-2.4.12.dist-info/METADATA,sha256=fqK1YCT402ptWC4idyZaIqjbCQ38jGDAZGJCuVJ1TAE,5388
|
24
|
+
gamesentenceminer-2.4.12.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
25
|
+
gamesentenceminer-2.4.12.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
|
26
|
+
gamesentenceminer-2.4.12.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
|
27
|
+
gamesentenceminer-2.4.12.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|