GameSentenceMiner 2.11.3__tar.gz → 2.11.4__tar.gz

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.
Files changed (76) hide show
  1. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/text_log.py +6 -3
  2. gamesentenceminer-2.11.4/GameSentenceMiner/util/window_transparency.py +168 -0
  3. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/vad.py +13 -11
  4. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner.egg-info/PKG-INFO +1 -1
  5. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner.egg-info/SOURCES.txt +1 -0
  6. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/PKG-INFO +1 -1
  7. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/pyproject.toml +1 -1
  8. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/__init__.py +0 -0
  9. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/ai/__init__.py +0 -0
  10. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/ai/ai_prompting.py +0 -0
  11. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/anki.py +0 -0
  12. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/assets/__init__.py +0 -0
  13. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/assets/icon.png +0 -0
  14. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/assets/icon128.png +0 -0
  15. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/assets/icon256.png +0 -0
  16. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/assets/icon32.png +0 -0
  17. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/assets/icon512.png +0 -0
  18. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/assets/icon64.png +0 -0
  19. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/assets/pickaxe.png +0 -0
  20. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/config_gui.py +0 -0
  21. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/gametext.py +0 -0
  22. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/gsm.py +0 -0
  23. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/obs.py +0 -0
  24. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/ocr/__init__.py +0 -0
  25. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/ocr/gsm_ocr_config.py +0 -0
  26. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/ocr/ocrconfig.py +0 -0
  27. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/ocr/owocr_area_selector.py +0 -0
  28. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/ocr/owocr_helper.py +0 -0
  29. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/ocr/ss_picker.py +0 -0
  30. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/owocr/owocr/__init__.py +0 -0
  31. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/owocr/owocr/__main__.py +0 -0
  32. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/owocr/owocr/config.py +0 -0
  33. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/owocr/owocr/lens_betterproto.py +0 -0
  34. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/owocr/owocr/ocr.py +0 -0
  35. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/owocr/owocr/run.py +0 -0
  36. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py +0 -0
  37. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/__init__.py +0 -0
  38. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/audio_offset_selector.py +0 -0
  39. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/communication/__init__.py +0 -0
  40. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/communication/send.py +0 -0
  41. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/communication/websocket.py +0 -0
  42. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/configuration.py +0 -0
  43. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/downloader/Untitled_json.py +0 -0
  44. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/downloader/__init__.py +0 -0
  45. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/downloader/download_tools.py +0 -0
  46. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/downloader/oneocr_dl.py +0 -0
  47. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/electron_config.py +0 -0
  48. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/ffmpeg.py +0 -0
  49. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/gsm_utils.py +0 -0
  50. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/model.py +0 -0
  51. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/notification.py +0 -0
  52. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/package.py +0 -0
  53. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/util/ss_selector.py +0 -0
  54. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/__init__.py +0 -0
  55. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/service.py +0 -0
  56. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/__init__.py +0 -0
  57. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/apple-touch-icon.png +0 -0
  58. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/favicon-96x96.png +0 -0
  59. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/favicon.ico +0 -0
  60. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/favicon.svg +0 -0
  61. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/site.webmanifest +0 -0
  62. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/style.css +0 -0
  63. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/web-app-manifest-192x192.png +0 -0
  64. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/static/web-app-manifest-512x512.png +0 -0
  65. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/templates/__init__.py +0 -0
  66. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/templates/index.html +0 -0
  67. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/templates/text_replacements.html +0 -0
  68. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/templates/utility.html +0 -0
  69. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner/web/texthooking_page.py +0 -0
  70. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner.egg-info/dependency_links.txt +0 -0
  71. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner.egg-info/entry_points.txt +0 -0
  72. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner.egg-info/requires.txt +0 -0
  73. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/GameSentenceMiner.egg-info/top_level.txt +0 -0
  74. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/LICENSE +0 -0
  75. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/README.md +0 -0
  76. {gamesentenceminer-2.11.3 → gamesentenceminer-2.11.4}/setup.cfg +0 -0
@@ -35,6 +35,9 @@ class GameLine:
35
35
  def set_TL(self, tl: str):
36
36
  self.TL = tl
37
37
 
38
+ def get_stripped_text(self):
39
+ return self.text.replace('\n', '').strip()
40
+
38
41
  def __str__(self):
39
42
  return str({"text": self.text, "time": self.time})
40
43
 
@@ -151,10 +154,10 @@ def get_line_and_future_lines(last_note):
151
154
  found = False
152
155
  for line in game_log.values:
153
156
  if found:
154
- found_lines.append(line.text)
157
+ found_lines.append(line)
155
158
  if lines_match(line.text, remove_html_and_cloze_tags(sentence)): # 80% similarity threshold
156
159
  found = True
157
- found_lines.append(line.text)
160
+ found_lines.append(line)
158
161
  return found_lines
159
162
 
160
163
 
@@ -168,7 +171,7 @@ def get_mined_line(last_note: AnkiCard, lines=None):
168
171
 
169
172
  sentence = last_note.get_field(get_config().anki.sentence_field)
170
173
  for line in reversed(lines):
171
- if lines_match(line.text, remove_html_and_cloze_tags(sentence)):
174
+ if lines_match(line.get_stripped_text(), remove_html_and_cloze_tags(sentence)):
172
175
  return line
173
176
  return lines[-1]
174
177
 
@@ -0,0 +1,168 @@
1
+ import win32gui
2
+ import win32con
3
+ import win32api
4
+ import keyboard
5
+ import time
6
+ import threading
7
+
8
+ from GameSentenceMiner.util.configuration import logger
9
+
10
+ # --- Configuration (equivalent to AHK top-level variables) ---
11
+ TRANSPARENT_LEVEL = 1 # Almost invisible (0-255 scale)
12
+ OPAQUE_LEVEL = 255 # Fully opaque
13
+ HOTKEY = 'ctrl+alt+y'
14
+
15
+ # --- Global State Variables (equivalent to AHK global variables) ---
16
+ is_toggled = False
17
+ target_hwnd = None
18
+ # A lock to prevent race conditions when accessing global state from different threads
19
+ state_lock = threading.Lock()
20
+
21
+ # --- Core Functions (equivalent to AHK functions) ---
22
+
23
+ def set_window_transparency(hwnd, transparency):
24
+ """
25
+ Sets the transparency of a window.
26
+ This is the Python equivalent of WinSetTransparent.
27
+ """
28
+ if not hwnd or not win32gui.IsWindow(hwnd):
29
+ return
30
+ try:
31
+ # Get the current window style
32
+ style = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
33
+ # Add the WS_EX_LAYERED style, which is required for transparency
34
+ win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, style | win32con.WS_EX_LAYERED)
35
+ # Set the transparency
36
+ win32gui.SetLayeredWindowAttributes(hwnd, 0, transparency, win32con.LWA_ALPHA)
37
+ except Exception as e:
38
+ # Some windows (like system or elevated ones) might deny permission
39
+ # logger.info(f"Error setting transparency for HWND {hwnd}: {e}")
40
+ pass
41
+
42
+ def set_always_on_top(hwnd, is_on_top):
43
+ """
44
+ Sets or removes the "Always on Top" status for a window.
45
+ This is the Python equivalent of WinSetAlwaysOnTop.
46
+ """
47
+ if not hwnd or not win32gui.IsWindow(hwnd):
48
+ return
49
+ try:
50
+ rect = win32gui.GetWindowRect(hwnd)
51
+ position = win32con.HWND_TOPMOST if is_on_top else win32con.HWND_NOTOPMOST
52
+ # Set the window position without moving or resizing it
53
+ win32gui.SetWindowPos(hwnd, position, rect[0], rect[1], 0, 0,
54
+ win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)
55
+ except Exception as e:
56
+ # logger.info(f"Error setting always-on-top for HWND {hwnd}: {e}")
57
+ pass
58
+
59
+ def reset_window_state(hwnd):
60
+ """A helper to reset a window to its default state."""
61
+ set_window_transparency(hwnd, OPAQUE_LEVEL)
62
+ set_always_on_top(hwnd, False)
63
+
64
+ # --- Hotkey Callback (equivalent to AHK ^!y::) ---
65
+
66
+ def toggle_functionality():
67
+ """
68
+ This function is called when the hotkey is pressed.
69
+ It manages the toggling logic.
70
+ """
71
+ global is_toggled, target_hwnd
72
+
73
+ # Get the currently focused window (equivalent to WinGetID("A"))
74
+ current_hwnd = win32gui.GetForegroundWindow()
75
+ if not current_hwnd:
76
+ logger.info("No window is currently active!")
77
+ return
78
+
79
+ with state_lock:
80
+ # Case 1: The hotkey is pressed on the currently toggled window to disable it.
81
+ if is_toggled and target_hwnd == current_hwnd:
82
+ logger.info(f"Disabling functionality for window: {win32gui.GetWindowText(current_hwnd)}")
83
+ reset_window_state(current_hwnd)
84
+ is_toggled = False
85
+ target_hwnd = None
86
+ # Case 2: Enable functionality for a new window, or switch to a new one.
87
+ else:
88
+ # If another window was already toggled, reset it first.
89
+ if is_toggled and target_hwnd is not None:
90
+ logger.info(f"Resetting old window: {win32gui.GetWindowText(target_hwnd)}")
91
+ reset_window_state(target_hwnd)
92
+
93
+ # Enable functionality for the new window.
94
+ logger.info(f"Enabling functionality for window: {win32gui.GetWindowText(current_hwnd)}")
95
+ is_toggled = True
96
+ target_hwnd = current_hwnd
97
+ set_always_on_top(target_hwnd, True)
98
+ # The mouse_monitor_loop will handle setting the initial transparency
99
+
100
+ # --- Mouse Monitoring (equivalent to AHK Loop) ---
101
+
102
+ def mouse_monitor_loop():
103
+ """
104
+ A loop that runs in a separate thread to monitor the mouse position.
105
+ """
106
+ global is_toggled, target_hwnd
107
+
108
+ while True:
109
+ # We check the state without a lock first for performance,
110
+ # then use the lock when we need to read the shared variable.
111
+ if is_toggled:
112
+ with state_lock:
113
+ # Make a local copy of the target handle to work with
114
+ monitored_hwnd = target_hwnd
115
+
116
+ if monitored_hwnd:
117
+ # Get mouse position and the window handle under the cursor
118
+ pos = win32gui.GetCursorPos()
119
+ hwnd_under_mouse = win32gui.WindowFromPoint(pos)
120
+
121
+ # WindowFromPoint can return a child window (like a button).
122
+ # We need to walk up the parent chain to see if it belongs to our target window.
123
+ is_mouse_over_target = False
124
+ current_hwnd = hwnd_under_mouse
125
+ while current_hwnd != 0:
126
+ if current_hwnd == monitored_hwnd:
127
+ is_mouse_over_target = True
128
+ break
129
+ current_hwnd = win32gui.GetParent(current_hwnd)
130
+
131
+ # Apply transparency based on mouse position
132
+ if is_mouse_over_target:
133
+ set_window_transparency(monitored_hwnd, OPAQUE_LEVEL)
134
+ else:
135
+ set_window_transparency(monitored_hwnd, TRANSPARENT_LEVEL)
136
+
137
+ # A small delay to reduce CPU usage
138
+ time.sleep(0.1)
139
+
140
+ # --- Main Execution Block ---
141
+
142
+ if __name__ == "__main__":
143
+ import argparse
144
+ # Start the mouse monitor in a separate, non-blocking thread.
145
+ # daemon=True ensures the thread will exit when the main script does.
146
+ monitor_thread = threading.Thread(target=mouse_monitor_loop, daemon=True)
147
+ monitor_thread.start()
148
+
149
+ # get hotkey from args
150
+ parser = argparse.ArgumentParser(description="Window Transparency Toggle Script")
151
+ parser.add_argument('--hotkey', type=str, default=HOTKEY, help='Hotkey to toggle transparency (default: ctrl+alt+y)')
152
+
153
+ hotkey = parser.parse_args().hotkey.lower()
154
+
155
+ # Register the global hotkey
156
+ keyboard.add_hotkey(hotkey, toggle_functionality)
157
+
158
+ logger.info(f"Script running. Press '{hotkey}' on a window to toggle transparency.")
159
+ logger.info("Press Ctrl+C in this console to exit.")
160
+
161
+ # Keep the script running to listen for the hotkey.
162
+ # keyboard.wait() is a blocking call that waits indefinitely.
163
+ try:
164
+ keyboard.wait()
165
+ except KeyboardInterrupt:
166
+ if is_toggled and target_hwnd:
167
+ reset_window_state(target_hwnd)
168
+ logger.info("\nScript terminated by user.")
@@ -53,18 +53,10 @@ class VADSystem:
53
53
  match model:
54
54
  case configuration.OFF:
55
55
  return VADResult(False, 0, 0, "OFF")
56
- # case configuration.GROQ:
57
- # if not self.groq:
58
- # self.groq = GroqVADProcessor()
59
- # return self.groq.process_audio(input_audio, output_audio, game_line)
60
56
  case configuration.SILERO:
61
57
  if not self.silero:
62
58
  self.silero = SileroVADProcessor()
63
59
  return self.silero.process_audio(input_audio, output_audio, game_line)
64
- # case configuration.VOSK:
65
- # if not self.vosk:
66
- # self.vosk = VoskVADProcessor()
67
- # return self.vosk.process_audio(input_audio, output_audio, game_line)
68
60
  case configuration.WHISPER:
69
61
  if not self.whisper:
70
62
  self.whisper = WhisperVADProcessor()
@@ -121,8 +113,6 @@ class VADProcessor(ABC):
121
113
  logger.info("No voice activity detected in the audio.")
122
114
  return VADResult(False, 0, 0, self.vad_system_name)
123
115
 
124
- print(voice_activity)
125
-
126
116
  start_time = voice_activity[0]['start'] if voice_activity else 0
127
117
  end_time = voice_activity[-1]['end'] if voice_activity else 0
128
118
 
@@ -132,6 +122,17 @@ class VADProcessor(ABC):
132
122
  if 0 > audio_length - voice_activity[-1]['start'] + get_config().audio.beginning_offset:
133
123
  end_time = voice_activity[-2]['end']
134
124
 
125
+ # if detected text is much shorter than game_line.text, if no text, guess based on length
126
+ if 'text' in voice_activity[0]:
127
+ dectected_text = ''.join([item['text'] for item in voice_activity])
128
+ if game_line and game_line.text and len(dectected_text) < len(game_line.text) / 2:
129
+ logger.info(f"Detected text '{dectected_text}' is much shorter than expected '{game_line.text}', skipping.")
130
+ return VADResult(False, 0, 0, self.vad_system_name)
131
+ else:
132
+ if game_line and game_line.text and (end_time - start_time) < max(0.5, len(game_line.text) * 0.05):
133
+ logger.info(f"Detected audio length {end_time - start_time} is much shorter than expected for text '{game_line.text}', skipping.")
134
+ return VADResult(False, 0, 0, self.vad_system_name)
135
+
135
136
  if get_config().vad.cut_and_splice_segments:
136
137
  self.extract_audio_and_combine_segments(input_audio, voice_activity, output_audio, padding=get_config().vad.splice_padding)
137
138
  else:
@@ -186,7 +187,7 @@ class WhisperVADProcessor(VADProcessor):
186
187
 
187
188
  # Process the segments to extract tokens, timestamps, and confidence
188
189
  for i, segment in enumerate(result.segments):
189
- if len(segment.text) == 1 and (i > 1 and segment.start - result.segments[i - 1].end > 1.0) or (i < len(result.segments) - 1 and result.segments[i + 1].start - segment.end > 1.0):
190
+ if len(segment.text) <= 2 and ((i > 1 and segment.start - result.segments[i - 1].end > 1.0) or (i < len(result.segments) - 1 and result.segments[i + 1].start - segment.end > 1.0)):
190
191
  if segment.text in ['えー', 'ん']:
191
192
  logger.debug(f"Skipping filler segment: {segment.text} at {segment.start}-{segment.end}")
192
193
  continue
@@ -194,6 +195,7 @@ class WhisperVADProcessor(VADProcessor):
194
195
  logger.info(
195
196
  "Unknown single character segment, not skipping, but logging, please report if this is a mistake: " + segment.text)
196
197
 
198
+
197
199
  logger.debug(segment.to_dict())
198
200
  voice_activity.append({
199
201
  'text': segment.text,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GameSentenceMiner
3
- Version: 2.11.3
3
+ Version: 2.11.4
4
4
  Summary: A tool for mining sentences from games. Update: Full UI Re-design
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -48,6 +48,7 @@ GameSentenceMiner/util/notification.py
48
48
  GameSentenceMiner/util/package.py
49
49
  GameSentenceMiner/util/ss_selector.py
50
50
  GameSentenceMiner/util/text_log.py
51
+ GameSentenceMiner/util/window_transparency.py
51
52
  GameSentenceMiner/util/communication/__init__.py
52
53
  GameSentenceMiner/util/communication/send.py
53
54
  GameSentenceMiner/util/communication/websocket.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GameSentenceMiner
3
- Version: 2.11.3
3
+ Version: 2.11.4
4
4
  Summary: A tool for mining sentences from games. Update: Full UI Re-design
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "GameSentenceMiner"
10
- version = "2.11.3"
10
+ version = "2.11.4"
11
11
  description = "A tool for mining sentences from games. Update: Full UI Re-design"
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.10"