GameSentenceMiner 2.9.7__py3-none-any.whl → 2.9.8__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
@@ -82,10 +82,7 @@ def update_anki_card(last_note: AnkiCard, note=None, audio_path='', video_path='
82
82
  for key, value in get_config().anki.anki_custom_fields.items():
83
83
  note['fields'][key] = str(value)
84
84
 
85
- selected_notes = invoke("guiSelectedNotes")
86
- if last_note.noteId in selected_notes:
87
- notification.open_browser_window(1)
88
- invoke("updateNoteFields", note=note)
85
+
89
86
  tags = []
90
87
  if get_config().anki.custom_tags:
91
88
  tags.extend(get_config().anki.custom_tags)
@@ -94,19 +91,26 @@ def update_anki_card(last_note: AnkiCard, note=None, audio_path='', video_path='
94
91
  if tags:
95
92
  tag_string = " ".join(tags)
96
93
  invoke("addTags", tags=tag_string, notes=[last_note.noteId])
97
- logger.info(f"UPDATED ANKI CARD FOR {last_note.noteId}")
94
+
95
+ check_and_update_note(last_note, note, tags)
96
+
98
97
  if get_config().features.notify_on_update:
99
98
  notification.send_note_updated(tango)
99
+ if get_config().audio.external_tool and get_config().audio.external_tool_enabled and update_audio:
100
+ open_audio_in_external(f"{get_config().audio.anki_media_collection}/{audio_in_anki}")
101
+
102
+ def check_and_update_note(last_note, note, tags=[]):
103
+ selected_notes = invoke("guiSelectedNotes")
104
+ if last_note.noteId in selected_notes:
105
+ notification.open_browser_window(1)
106
+ invoke("updateNoteFields", note=note)
107
+
108
+ logger.info(f"UPDATED ANKI CARD FOR {last_note.noteId}")
100
109
  if last_note.noteId in selected_notes or get_config().features.open_anki_in_browser:
101
110
  notification.open_browser_window(last_note.noteId, get_config().features.browser_query)
102
111
  if get_config().features.open_anki_edit:
103
112
  notification.open_anki_card(last_note.noteId)
104
113
 
105
-
106
- if get_config().audio.external_tool and get_config().audio.external_tool_enabled and update_audio:
107
- open_audio_in_external(f"{get_config().audio.anki_media_collection}/{audio_in_anki}")
108
-
109
-
110
114
  def open_audio_in_external(fileabspath, shell=False):
111
115
  logger.info(f"Opening audio in external program...")
112
116
  if shell:
@@ -131,7 +135,7 @@ def add_image_to_card(last_note: AnkiCard, image_path):
131
135
  if update_picture:
132
136
  note['fields'][get_config().anki.picture_field] = image_html
133
137
 
134
- invoke("updateNoteFields", note=note)
138
+ check_and_update_note(last_note, note)
135
139
 
136
140
  logger.info(f"UPDATED IMAGE FOR ANKI CARD {last_note.noteId}")
137
141
 
GameSentenceMiner/gsm.py CHANGED
@@ -32,7 +32,7 @@ try:
32
32
  from GameSentenceMiner.util.configuration import *
33
33
  from GameSentenceMiner.util.ffmpeg import get_audio_and_trim, get_video_timings
34
34
  from GameSentenceMiner.obs import check_obs_folder_is_correct
35
- from GameSentenceMiner.util.text_log import GameLine, get_text_event, get_mined_line, get_all_lines
35
+ from GameSentenceMiner.util.text_log import GameLine, get_text_event, get_mined_line, get_all_lines, game_log
36
36
  from GameSentenceMiner.util import *
37
37
  from GameSentenceMiner.web import texthooking_page
38
38
  from GameSentenceMiner.web.texthooking_page import run_text_hooker_page
@@ -197,7 +197,24 @@ class VideoToAudioHandler(FileSystemEventHandler):
197
197
  gsm_state.line_for_screenshot = None
198
198
  gsm_state.previous_line_for_screenshot = line
199
199
  screenshot = ffmpeg.get_screenshot_for_line(video_path, line, True)
200
- os.startfile(screenshot)
200
+ if gsm_state.anki_note_for_screenshot:
201
+ gsm_state.anki_note_for_screenshot = None
202
+ encoded_image = ffmpeg.process_image(screenshot)
203
+ if get_config().anki.update_anki and get_config().screenshot.screenshot_hotkey_updates_anki:
204
+ last_note = anki.get_last_anki_card()
205
+ if get_config().features.backfill_audio:
206
+ last_note = anki.get_cards_by_sentence(gametext.current_line)
207
+ if last_note:
208
+ anki.add_image_to_card(last_note, encoded_image)
209
+ notification.send_screenshot_updated(last_note.get_field(get_config().anki.word_field))
210
+ if get_config().features.open_anki_edit:
211
+ notification.open_anki_card(last_note.noteId)
212
+ else:
213
+ notification.send_screenshot_saved(encoded_image)
214
+ else:
215
+ notification.send_screenshot_saved(encoded_image)
216
+ else:
217
+ os.startfile(screenshot)
201
218
  return
202
219
  except Exception as e:
203
220
  logger.error(f"Error Playing Audio/Video: {e}")
@@ -303,27 +320,30 @@ def register_hotkeys():
303
320
 
304
321
 
305
322
  def get_screenshot():
306
- try:
307
- image = obs.get_screenshot()
308
- wait_for_stable_file(image, timeout=3)
309
- if not image:
310
- raise Exception("Failed to get Screenshot from OBS")
311
- encoded_image = ffmpeg.process_image(image)
312
- if get_config().anki.update_anki and get_config().screenshot.screenshot_hotkey_updates_anki:
313
- last_note = anki.get_last_anki_card()
314
- if get_config().features.backfill_audio:
315
- last_note = anki.get_cards_by_sentence(gametext.current_line)
316
- if last_note:
317
- anki.add_image_to_card(last_note, encoded_image)
318
- notification.send_screenshot_updated(last_note.get_field(get_config().anki.word_field))
319
- if get_config().features.open_anki_edit:
320
- notification.open_anki_card(last_note.noteId)
321
- else:
322
- notification.send_screenshot_saved(encoded_image)
323
- else:
324
- notification.send_screenshot_saved(encoded_image)
325
- except Exception as e:
326
- logger.error(f"Failed to get Screenshot: {e}")
323
+ # try:
324
+ gsm_state.line_for_screenshot = game_log.get_last_line()
325
+ gsm_state.anki_note_for_screenshot = anki.get_last_anki_card()
326
+ obs.save_replay_buffer()
327
+ # image = obs.get_screenshot()
328
+ # wait_for_stable_file(image, timeout=3)
329
+ # if not image:
330
+ # raise Exception("Failed to get Screenshot from OBS")
331
+ # encoded_image = ffmpeg.process_image(image)
332
+ # if get_config().anki.update_anki and get_config().screenshot.screenshot_hotkey_updates_anki:
333
+ # last_note = anki.get_last_anki_card()
334
+ # if get_config().features.backfill_audio:
335
+ # last_note = anki.get_cards_by_sentence(gametext.current_line)
336
+ # if last_note:
337
+ # anki.add_image_to_card(last_note, encoded_image)
338
+ # notification.send_screenshot_updated(last_note.get_field(get_config().anki.word_field))
339
+ # if get_config().features.open_anki_edit:
340
+ # notification.open_anki_card(last_note.noteId)
341
+ # else:
342
+ # notification.send_screenshot_saved(encoded_image)
343
+ # else:
344
+ # notification.send_screenshot_saved(encoded_image)
345
+ # except Exception as e:
346
+ # logger.error(f"Failed to get Screenshot: {e}")
327
347
 
328
348
 
329
349
  # def create_image():
@@ -641,6 +641,7 @@ class GsmAppState:
641
641
  def __init__(self):
642
642
  self.line_for_audio = None
643
643
  self.line_for_screenshot = None
644
+ self.anki_note_for_screenshot = None
644
645
  self.previous_line_for_audio = None
645
646
  self.previous_line_for_screenshot = None
646
647
  self.previous_audio = None
@@ -75,7 +75,7 @@ def display_images(image_paths, golden_frame):
75
75
 
76
76
  for i, path in enumerate(image_paths):
77
77
  img = Image.open(path)
78
- img.thumbnail((450, 450))
78
+ img.thumbnail((img.width / 8, img.height / 8))
79
79
  img_tk = ImageTk.PhotoImage(img)
80
80
  if golden_frame and path == golden_frame:
81
81
  label = tk.Label(window, image=img_tk, borderwidth=5, relief="solid")
@@ -90,8 +90,13 @@ class GameText:
90
90
  return True
91
91
  return False
92
92
 
93
+ def get_last_line(self):
94
+ if self.values:
95
+ return self.values[-1]
96
+ return None
97
+
93
98
 
94
- text_log = GameText()
99
+ game_log = GameText()
95
100
 
96
101
 
97
102
  def similar(a, b):
@@ -109,7 +114,7 @@ def lines_match(a, b):
109
114
 
110
115
 
111
116
  def get_text_event(last_note) -> GameLine:
112
- lines = text_log.values
117
+ lines = game_log.values
113
118
 
114
119
  if not lines:
115
120
  raise Exception("No lines in history. Text is required from either clipboard or websocket for GSM to work. Please check your setup/config.")
@@ -137,7 +142,7 @@ def get_line_and_future_lines(last_note):
137
142
  found_lines = []
138
143
  if sentence:
139
144
  found = False
140
- for line in text_log.values:
145
+ for line in game_log.values:
141
146
  if found:
142
147
  found_lines.append(line.text)
143
148
  if lines_match(line.text, remove_html_and_cloze_tags(sentence)): # 80% similarity threshold
@@ -160,18 +165,18 @@ def get_mined_line(last_note: AnkiCard, lines):
160
165
 
161
166
 
162
167
  def get_time_of_line(line):
163
- return text_log.get_time(line)
168
+ return game_log.get_time(line)
164
169
 
165
170
 
166
171
  def get_all_lines():
167
- return text_log.values
172
+ return game_log.values
168
173
 
169
174
 
170
175
  def get_text_log() -> GameText:
171
- return text_log
176
+ return game_log
172
177
 
173
178
  def add_line(current_line_after_regex, line_time):
174
- text_log.add_line(current_line_after_regex, line_time)
179
+ game_log.add_line(current_line_after_regex, line_time)
175
180
 
176
181
  def get_line_by_id(line_id: str) -> Optional[GameLine]:
177
182
  """
@@ -183,4 +188,4 @@ def get_line_by_id(line_id: str) -> Optional[GameLine]:
183
188
  Returns:
184
189
  Optional[GameLine]: The GameLine object if found, otherwise None.
185
190
  """
186
- return text_log.get_by_id(line_id)
191
+ return game_log.get_by_id(line_id)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GameSentenceMiner
3
- Version: 2.9.7
3
+ Version: 2.9.8
4
4
  Summary: A tool for mining sentences from games.
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -1,8 +1,8 @@
1
1
  GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- GameSentenceMiner/anki.py,sha256=CuzVqzuFtZnbMbU2Zk-sxNGwSgyCpv5RLL7lOOX0Meg,14972
2
+ GameSentenceMiner/anki.py,sha256=OPamV4p5mSEkfrUdflauzDJ4Uh2rLYtHq9F7D1aMyhY,15077
3
3
  GameSentenceMiner/config_gui.py,sha256=r-ASCXVNS4Io6Ej3svwC8aJEWc9Rc7u-pzfsAwD4ru8,82079
4
4
  GameSentenceMiner/gametext.py,sha256=mM-gw1d7c2EEvMUznaAevTQFLswNZavCuxMXhA9pV4g,6251
5
- GameSentenceMiner/gsm.py,sha256=SHvT3JZlYpZgKeJnVXrtk8ve4ubiM7YPv-9FDF7rVM4,27724
5
+ GameSentenceMiner/gsm.py,sha256=QYc2AovzwlhVGtPmwWkNKHgo6CsFdT37ACXMbsmPAu8,29061
6
6
  GameSentenceMiner/obs.py,sha256=O9NYOGu7kwp4flq8LLXp8YJQg0JTZ8qBqiQNQ6u4ku4,14724
7
7
  GameSentenceMiner/vad.py,sha256=Gk_VthD7mDp3-wM_S6bEv8ykGmqzCDbbcRiaEBzAE_o,14835
8
8
  GameSentenceMiner/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -28,15 +28,15 @@ GameSentenceMiner/owocr/owocr/ocr.py,sha256=y8RHHaJw8M4BG4CbbtIw0DrV8KP9RjbJNJxj
28
28
  GameSentenceMiner/owocr/owocr/run.py,sha256=jFN7gYYriHgfqORJiBTz8mPkQsDJ6ZugA0_ATWUxk-U,54750
29
29
  GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py,sha256=Na6XStbQBtpQUSdbN3QhEswtKuU1JjReFk_K8t5ezQE,3395
30
30
  GameSentenceMiner/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- GameSentenceMiner/util/configuration.py,sha256=Qk5V4HA2FJbdMTa9jYZfNVQ_4rzvjbUtJgPejwQ3vwk,25856
31
+ GameSentenceMiner/util/configuration.py,sha256=VCIDRjulbWu-xgU2B_k2i8POVrP-Lw5dN3ghatDcxGs,25901
32
32
  GameSentenceMiner/util/electron_config.py,sha256=ZZf54QifdNHbII-JDsMZmdT8nTyrq-7gVvalyLRecfw,9792
33
33
  GameSentenceMiner/util/ffmpeg.py,sha256=qaCXkfK2fd-1NRqbm7burrdBYgnGx07kBuyenee8Mtk,18697
34
34
  GameSentenceMiner/util/gsm_utils.py,sha256=RoOTvWCVpmfYA7fLDdIPcgH1c6TZK4jDZq98BectPhg,8272
35
35
  GameSentenceMiner/util/model.py,sha256=iDtLTfR6D-ZC0gCiDqYno6-gA6Z07PZTM4B5MAA6xZI,5704
36
36
  GameSentenceMiner/util/notification.py,sha256=euTnnNDJm0izr0Z5AhZGV2wrrioCASeKUtm5aZFO5zU,3462
37
37
  GameSentenceMiner/util/package.py,sha256=u1ym5z869lw5EHvIviC9h9uH97bzUXSXXA8KIn8rUvk,1157
38
- GameSentenceMiner/util/ss_selector.py,sha256=ATgwDXi4-TLv0hB21NV79FZnXgidiM0z7TgvO7eBnhw,4472
39
- GameSentenceMiner/util/text_log.py,sha256=XOq8tpJUpNa-mKJPui40P5aUTX2yzMHPnHgJ2obagw0,5201
38
+ GameSentenceMiner/util/ss_selector.py,sha256=oCzmDbpEGvVselF-oDPIrBcQktGIZT0Zt16uDLDAHMQ,4493
39
+ GameSentenceMiner/util/text_log.py,sha256=JQS0JpcdaTvcdKgfKs3lWskG4dk6NPjqjMJpm2--37I,5310
40
40
  GameSentenceMiner/util/communication/__init__.py,sha256=xh__yn2MhzXi9eLi89PeZWlJPn-cbBSjskhi1BRraXg,643
41
41
  GameSentenceMiner/util/communication/send.py,sha256=Wki9qIY2CgYnuHbmnyKVIYkcKAN_oYS4up93XMikBaI,222
42
42
  GameSentenceMiner/util/communication/websocket.py,sha256=gPgxA2R2U6QZJjPqbUgODC87gtacPhmuC8lCprIkSmA,3287
@@ -59,9 +59,9 @@ GameSentenceMiner/web/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
59
59
  GameSentenceMiner/web/templates/index.html,sha256=HZKiIjiGJV8PGQ9T2aLDUNSfJn71qOwbYCjbRuSIjpY,213583
60
60
  GameSentenceMiner/web/templates/text_replacements.html,sha256=tV5c8mCaWSt_vKuUpbdbLAzXZ3ATZeDvQ9PnnAfqY0M,8598
61
61
  GameSentenceMiner/web/templates/utility.html,sha256=3flZinKNqUJ7pvrZk6xu__v67z44rXnaK7UTZ303R-8,16946
62
- gamesentenceminer-2.9.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
63
- gamesentenceminer-2.9.7.dist-info/METADATA,sha256=yhuKCbDJ0sP8Nd8TSl4UGVYOLGtq7VzrQaaOJti6INw,7250
64
- gamesentenceminer-2.9.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
65
- gamesentenceminer-2.9.7.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
66
- gamesentenceminer-2.9.7.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
67
- gamesentenceminer-2.9.7.dist-info/RECORD,,
62
+ gamesentenceminer-2.9.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
63
+ gamesentenceminer-2.9.8.dist-info/METADATA,sha256=gzdjSH0FVBCWr47uvp9aBkGbHrxrHcmMBmYJky9csO0,7250
64
+ gamesentenceminer-2.9.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
65
+ gamesentenceminer-2.9.8.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
66
+ gamesentenceminer-2.9.8.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
67
+ gamesentenceminer-2.9.8.dist-info/RECORD,,