GameSentenceMiner 2.8.27__py3-none-any.whl → 2.8.29__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.
@@ -99,7 +99,7 @@ class GeminiAI(AIManager):
99
99
  genai.configure(api_key=self.ai_config.api_key)
100
100
  model_name = self.ai_config.model
101
101
  self.model = genai.GenerativeModel(model_name)
102
- self.logger.info(f"GeminiAIManager initialized with model: {model_name}")
102
+ self.logger.debug(f"GeminiAIManager initialized with model: {model_name}")
103
103
  except Exception as e:
104
104
  self.logger.error(f"Failed to initialize Gemini API: {e}")
105
105
  self.model = None
@@ -134,7 +134,7 @@ class GroqAI(AIManager):
134
134
  self.model_name = self.ai_config.model
135
135
  try:
136
136
  self.client = Groq(api_key=self.api_key)
137
- self.logger.info(f"GroqAIManager initialized with model: {self.model_name}")
137
+ self.logger.debug(f"GroqAIManager initialized with model: {self.model_name}")
138
138
  except Exception as e:
139
139
  self.logger.error(f"Failed to initialize Groq client: {e}")
140
140
  self.client = None
@@ -187,7 +187,7 @@ def get_ai_prompt_result(lines: List[GameLine], sentence: str, current_line: Gam
187
187
  return ""
188
188
  return ai_manager.process(lines, sentence, current_line, game_title)
189
189
  except Exception as e:
190
- logger.info("Error caught while trying to get AI prompt result. Check logs for more details.")
190
+ logger.error("Error caught while trying to get AI prompt result. Check logs for more details.")
191
191
  logger.debug(e)
192
192
  return ""
193
193
 
GameSentenceMiner/anki.py CHANGED
@@ -45,10 +45,13 @@ def update_anki_card(last_note: AnkiCard, note=None, audio_path='', video_path='
45
45
  if get_config().paths.remove_screenshot:
46
46
  os.remove(screenshot)
47
47
  if get_config().anki.previous_image_field:
48
- try:
49
- prev_screenshot = ffmpeg.get_screenshot(video_path, prev_ss_timing)
50
- except Exception as e:
51
- logger.error(f"Error getting previous screenshot based on VAD, Falling back to previous logic: {e}")
48
+ if prev_ss_timing != 0:
49
+ try:
50
+ prev_screenshot = ffmpeg.get_screenshot(video_path, prev_ss_timing)
51
+ except Exception as e:
52
+ logger.error(f"Error getting previous screenshot based on VAD, Falling back to previous logic: {e}")
53
+ prev_screenshot = ffmpeg.get_screenshot(video_path, ffmpeg.get_screenshot_time(video_path, selected_lines[0].prev if selected_lines else game_line.prev))
54
+ else:
52
55
  prev_screenshot = ffmpeg.get_screenshot(video_path, ffmpeg.get_screenshot_time(video_path, selected_lines[0].prev if selected_lines else game_line.prev))
53
56
  prev_screenshot_in_anki = store_media_file(prev_screenshot)
54
57
  if get_config().paths.remove_screenshot:
@@ -73,7 +76,7 @@ def update_anki_card(last_note: AnkiCard, note=None, audio_path='', video_path='
73
76
  get_config().anki.sentence_field)
74
77
  translation = get_ai_prompt_result(get_all_lines(), sentence_to_translate,
75
78
  game_line, get_current_game())
76
- logger.info(translation)
79
+ logger.info(f"AI prompt Result: {translation}")
77
80
  note['fields'][get_config().ai.anki_field] = translation
78
81
 
79
82
  if prev_screenshot_in_anki:
@@ -103,7 +106,7 @@ def update_anki_card(last_note: AnkiCard, note=None, audio_path='', video_path='
103
106
 
104
107
 
105
108
  def open_audio_in_external(fileabspath, shell=False):
106
- logger.info(f"Opening audio: {fileabspath} in external Program: {get_config().audio.external_tool}")
109
+ logger.info(f"Opening audio in external program...")
107
110
  if shell:
108
111
  subprocess.Popen(f' "{get_config().audio.external_tool}" "{fileabspath}" ', shell=True)
109
112
  else:
@@ -275,8 +278,8 @@ def update_new_card():
275
278
  if not last_card or not check_tags_for_should_update(last_card):
276
279
  return
277
280
  use_prev_audio = sentence_is_same_as_previous(last_card)
278
- logger.info(f"last mined line: {util.get_last_mined_line()}, current sentence: {get_sentence(last_card)}")
279
- logger.info(f"use previous audio: {use_prev_audio}")
281
+ logger.debug(f"last mined line: {util.get_last_mined_line()}, current sentence: {get_sentence(last_card)}")
282
+ logger.info(f"New card using previous audio: {use_prev_audio}")
280
283
  if get_config().obs.get_game_from_scene:
281
284
  obs.update_current_game()
282
285
  if use_prev_audio:
@@ -42,7 +42,7 @@ def get_screenshot(video_file, screenshot_timing):
42
42
  # Run the command
43
43
  subprocess.run(ffmpeg_command)
44
44
 
45
- logger.info(f"Screenshot saved to: {output_image}")
45
+ logger.debug(f"Screenshot saved to: {output_image}")
46
46
 
47
47
  return output_image
48
48
 
@@ -50,14 +50,16 @@ def get_screenshot_for_line(video_file, game_line):
50
50
  return get_screenshot(video_file, get_screenshot_time(video_file, game_line))
51
51
 
52
52
 
53
- def get_screenshot_time(video_path, game_line, default_beginning=False, vad_result=None, doing_multi_line=False):
53
+ def get_screenshot_time(video_path, game_line, default_beginning=False, vad_result=None, doing_multi_line=False, previous_line=False):
54
54
  if game_line:
55
55
  line_time = game_line.time
56
56
  else:
57
57
  # Assuming initial_time is defined elsewhere if game_line is None
58
58
  line_time = initial_time
59
-
60
- logger.info("Calculating screenshot time for line: " + str(game_line.text))
59
+ if previous_line:
60
+ logger.debug(f"Calculating screenshot time for previous line: {str(game_line.text)}")
61
+ else:
62
+ logger.debug("Calculating screenshot time for line: " + str(game_line.text))
61
63
 
62
64
  file_length = get_video_duration(video_path)
63
65
  file_mod_time = get_file_modification_time(video_path)
@@ -69,27 +71,23 @@ def get_screenshot_time(video_path, game_line, default_beginning=False, vad_resu
69
71
 
70
72
  # Calculate screenshot time from the beginning by adding the offset
71
73
  if vad_result and vad_result.success and not doing_multi_line:
72
- logger.debug("Using VAD to determine screenshot time")
73
- screenshot_time_from_beginning = line_timestamp_in_video + vad_result.end - 0.1
74
+ screenshot_time_from_beginning = line_timestamp_in_video + vad_result.end - 1
75
+ logger.info(f"Using VAD result {vad_result} for screenshot time: {screenshot_time_from_beginning} seconds from beginning of replay")
74
76
  elif get_config().screenshot.screenshot_timing_setting == "beginning":
75
- logger.debug("Using beginning of line for screenshot")
76
77
  screenshot_time_from_beginning = line_timestamp_in_video + screenshot_offset
78
+ logger.info(f"Using 'beginning' setting for screenshot time: {screenshot_time_from_beginning} seconds from beginning of replay")
77
79
  elif get_config().screenshot.screenshot_timing_setting == "middle":
78
80
  if game_line.next:
79
- logger.debug("Finding time between lines for screenshot")
80
81
  screenshot_time_from_beginning = line_timestamp_in_video + ((game_line.next.time - game_line.time).total_seconds() / 2) + screenshot_offset
81
82
  else:
82
- logger.debug("Using end of line for screenshot")
83
83
  screenshot_time_from_beginning = file_length - abs(screenshot_offset)
84
+ logger.info(f"Using 'middle' setting for screenshot time: {screenshot_time_from_beginning} seconds from beginning of replay")
84
85
  elif get_config().screenshot.screenshot_timing_setting == "end":
85
- logger.debug("Using end of line for screenshot")
86
86
  if game_line.next:
87
- logger.debug("Finding time between lines for screenshot")
88
87
  screenshot_time_from_beginning = line_timestamp_in_video + (game_line.next.time - game_line.time).total_seconds() - screenshot_offset
89
88
  else:
90
- logger.debug("Using end of video for screenshot")
91
- # If no next line, use the end of the video
92
89
  screenshot_time_from_beginning = file_length - screenshot_offset
90
+ logger.info(f"Using 'end' setting for screenshot time: {screenshot_time_from_beginning} seconds from beginning of replay")
93
91
  else:
94
92
  logger.error(f"Invalid screenshot timing setting: {get_config().screenshot.screenshot_timing_setting}")
95
93
  screenshot_time_from_beginning = line_timestamp_in_video + screenshot_offset
@@ -100,14 +98,9 @@ def get_screenshot_time(video_path, game_line, default_beginning=False, vad_resu
100
98
  f"Calculated screenshot time ({screenshot_time_from_beginning:.2f}s) is out of bounds for video (length {file_length:.2f}s)."
101
99
  )
102
100
  if default_beginning:
103
- logger.info("Defaulting to using the beginning of the video (1.0s)")
104
- # Return time for the start of the video
105
101
  return 1.0
106
- logger.info(f"Defaulting to using the end of the video ({file_length:.2f}s)")
107
102
  return file_length - screenshot_offset
108
103
 
109
- logger.info("Screenshot time from beginning: " + str(screenshot_time_from_beginning))
110
-
111
104
  # Return the calculated time from the beginning
112
105
  return screenshot_time_from_beginning
113
106
 
@@ -178,10 +171,10 @@ def get_audio_and_trim(video_path, game_line, next_line_time, anki_card_creation
178
171
 
179
172
  if codec == get_config().audio.extension:
180
173
  codec_command = ['-c:a', 'copy']
181
- logger.info(f"Extracting {get_config().audio.extension} from video")
174
+ logger.debug(f"Extracting {get_config().audio.extension} from video")
182
175
  else:
183
176
  codec_command = ["-c:a", f"{supported_formats[get_config().audio.extension]}"]
184
- logger.info(f"Re-encoding {codec} to {get_config().audio.extension}")
177
+ logger.debug(f"Re-encoding {codec} to {get_config().audio.extension}")
185
178
 
186
179
  untrimmed_audio = tempfile.NamedTemporaryFile(dir=configuration.get_temporary_directory(),
187
180
  suffix=f"_untrimmed.{get_config().audio.extension}").name
@@ -231,7 +224,7 @@ def trim_audio_based_on_last_line(untrimmed_audio, video_path, game_line, next_l
231
224
  minutes, seconds = divmod(remainder, 60)
232
225
  end_trim_time = "{:02}:{:02}:{:06.3f}".format(int(hours), int(minutes), seconds)
233
226
  ffmpeg_command.extend(['-to', end_trim_time])
234
- logger.info(
227
+ logger.debug(
235
228
  f"Looks Like this is mining from History, or Multiple Lines were selected Trimming end of audio to {end_trim_time}")
236
229
 
237
230
  ffmpeg_command.extend([
@@ -244,7 +237,7 @@ def trim_audio_based_on_last_line(untrimmed_audio, video_path, game_line, next_l
244
237
 
245
238
  logger.info(f"{total_seconds_after_offset} trimmed off of beginning")
246
239
 
247
- logger.info(f"Audio trimmed and saved to {trimmed_audio}")
240
+ logger.debug(f"Audio trimmed and saved to {trimmed_audio}")
248
241
  return trimmed_audio
249
242
 
250
243
  def get_video_timings(video_path, game_line, anki_card_creation_time=None):
@@ -269,7 +262,7 @@ def get_video_timings(video_path, game_line, anki_card_creation_time=None):
269
262
 
270
263
 
271
264
  def reencode_file_with_user_config(input_file, final_output_audio, user_ffmpeg_options):
272
- logger.info(f"Re-encode running with settings: {user_ffmpeg_options}")
265
+ logger.debug(f"Re-encode running with settings: {user_ffmpeg_options}")
273
266
  temp_file = create_temp_file_with_same_name(input_file)
274
267
  command = ffmpeg_base_command_list + [
275
268
  "-i", input_file,
@@ -297,7 +290,6 @@ def replace_file_with_retry(temp_file, input_file, retries=5, delay=1):
297
290
  for attempt in range(retries):
298
291
  try:
299
292
  shutil.move(temp_file, input_file)
300
- logger.info(f'Re-encode Finished!')
301
293
  return
302
294
  except OSError as e:
303
295
  if attempt < retries - 1:
GameSentenceMiner/gsm.py CHANGED
@@ -151,8 +151,14 @@ class VideoToAudioHandler(FileSystemEventHandler):
151
151
  logger.info("No SentenceAudio Field in config, skipping audio processing!")
152
152
 
153
153
  ss_timing = ffmpeg.get_screenshot_time(video_path, mined_line, vad_result=vad_result, doing_multi_line=bool(selected_lines))
154
- if get_config().anki.previous_image_field:
155
- prev_ss_timing = ffmpeg.get_screenshot_time(video_path, mined_line.prev, vad_result=VideoToAudioHandler.get_audio(mined_line.prev, mined_line.time, video_path, anki_card_creation_time=anki_card_creation_time, timing_only=True) ,doing_multi_line=bool(selected_lines))
154
+ prev_ss_timing = 0
155
+ if get_config().anki.previous_image_field and get_config().vad.do_vad_postprocessing:
156
+ prev_ss_timing = ffmpeg.get_screenshot_time(video_path, mined_line.prev,
157
+ vad_result=VideoToAudioHandler.get_audio(game_line=mined_line.prev,
158
+ next_line_time=mined_line.time,
159
+ video_path=video_path,
160
+ anki_card_creation_time=anki_card_creation_time,
161
+ timing_only=True) ,doing_multi_line=bool(selected_lines), previous_line=True)
156
162
 
157
163
  if get_config().anki.update_anki and last_note:
158
164
  anki.update_anki_card(last_note, note, audio_path=final_audio_output, video_path=video_path,
@@ -31,7 +31,6 @@ def process_audio_with_silero(input_audio, output_audio):
31
31
  voice_activity = detect_voice_with_silero(input_audio)
32
32
 
33
33
  if not voice_activity:
34
- logger.info("No voice activity detected in the audio.")
35
34
  return VADResult(False, 0, 0)
36
35
 
37
36
  # Trim based on the first and last speech detected
@@ -40,5 +39,4 @@ def process_audio_with_silero(input_audio, output_audio):
40
39
 
41
40
  # Trim the audio using FFmpeg
42
41
  ffmpeg.trim_audio(input_audio, start_time + get_config().vad.beginning_offset, end_time + get_config().audio.end_offset, output_audio)
43
- logger.info(f"Trimmed audio saved to: {output_audio}")
44
42
  return VADResult(True, start_time + get_config().vad.beginning_offset, end_time + get_config().audio.end_offset)
@@ -135,14 +135,13 @@ def process_audio_with_vosk(input_audio, output_audio):
135
135
  end_time = voice_activity[-1]['end'] if voice_activity else total_duration
136
136
 
137
137
  if get_config().vad.trim_beginning:
138
- logger.info(f"Trimmed Beginning of Audio to {start_time}")
138
+ logger.info(f"VAD Trimmed Beginning of Audio to {start_time}")
139
139
 
140
140
  # Print detected speech details with timestamps
141
- logger.info(f"Trimmed End of Audio to {end_time} seconds:")
141
+ logger.info(f"VAD Trimmed End of Audio to {end_time} seconds:")
142
142
 
143
143
  # Trim the audio using FFmpeg
144
144
  ffmpeg.trim_audio(input_audio, start_time + get_config().vad.beginning_offset, end_time + get_config().audio.end_offset, output_audio)
145
- logger.info(f"Trimmed audio saved to: {output_audio}")
146
145
  return VADResult(True, start_time + get_config().vad.beginning_offset, end_time + get_config().audio.end_offset)
147
146
 
148
147
 
@@ -82,14 +82,13 @@ def process_audio_with_whisper(input_audio, output_audio):
82
82
  end_time = voice_activity[-1]['end']
83
83
 
84
84
  if get_config().vad.trim_beginning:
85
- logger.info(f"Trimmed Beginning of Audio to {start_time}")
85
+ logger.info(f"VAD Trimmed Beginning of Audio to {start_time}")
86
86
 
87
87
  # Print detected speech details with timestamps
88
- logger.info(f"Trimmed End of Audio to {end_time} seconds:")
88
+ logger.info(f"VAD Trimmed End of Audio to {end_time} seconds:")
89
89
 
90
90
  # Trim the audio using FFmpeg
91
91
  ffmpeg.trim_audio(input_audio, start_time + get_config().vad.beginning_offset, end_time + get_config().audio.end_offset, output_audio)
92
- logger.info(f"Trimmed audio saved to: {output_audio}")
93
92
  return VADResult(True, start_time + get_config().vad.beginning_offset, end_time + get_config().audio.end_offset)
94
93
 
95
94
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GameSentenceMiner
3
- Version: 2.8.27
3
+ Version: 2.8.29
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,11 +1,11 @@
1
1
  GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- GameSentenceMiner/anki.py,sha256=I1rvmQry5mtdJHFqNYvG8dyV1A-mwgkCANXTtU-bRuQ,14491
2
+ GameSentenceMiner/anki.py,sha256=I98bvdxgZornaV1cnYux0-6AHnpEKkc4W56KCzOWC0s,14722
3
3
  GameSentenceMiner/config_gui.py,sha256=R7pUJDXCP7unGtBpuUjL0-8iWvY6LXRCYckHIrwkvF8,74207
4
4
  GameSentenceMiner/configuration.py,sha256=ndnxuQbLfhMruHld-yK3UjWt1DcXlVhaLRZD8l6SJ0E,22562
5
5
  GameSentenceMiner/electron_config.py,sha256=dGcPYCISPehXubYSzsDuI2Gl092MYK0u3bTnkL9Jh1Y,9787
6
- GameSentenceMiner/ffmpeg.py,sha256=oYhWJgFMmW84vcYNw7sYLICZAX24KpgZbrR0VjuVqXQ,14672
6
+ GameSentenceMiner/ffmpeg.py,sha256=Gcx45ZwUTDjQ3fQkz1xm0Hcd4pT0X0n7AlADFlL-Srg,14509
7
7
  GameSentenceMiner/gametext.py,sha256=VogQDs-VQ4dorqy8uvoklweeS58r3Th_yP-zn36e0u4,5556
8
- GameSentenceMiner/gsm.py,sha256=-aAaCiIjoNK4G-XLUhj5kP3XKoc14GHr7JLka54pQT0,25611
8
+ GameSentenceMiner/gsm.py,sha256=iMVaAEEaMP8Vfzxiiz-2PR1y5bl1wde2DC-MwA0e3uw,26069
9
9
  GameSentenceMiner/model.py,sha256=JdnkT4VoPOXmOpRgFdvERZ09c9wLN6tUJxdrKlGZcqo,5305
10
10
  GameSentenceMiner/notification.py,sha256=FY39ChSRK0Y8TQ6lBGsLnpZUFPtFpSy2tweeXVoV7kc,2809
11
11
  GameSentenceMiner/obs.py,sha256=-tzVHejaGDXyERaDrRqrKmbgwT13oJKxTivGwfUij7Y,10284
@@ -13,7 +13,7 @@ GameSentenceMiner/package.py,sha256=YlS6QRMuVlm6mdXx0rlXv9_3erTGS21jaP3PNNWfAH0,
13
13
  GameSentenceMiner/text_log.py,sha256=MD7LB5D-v4G0Bnm3uGvZQ0aV38Fcj4E0vgq7mmyQ7_4,5157
14
14
  GameSentenceMiner/util.py,sha256=LzWGIDZb8NLv-RyrE_d6ycoQEwM1zpaDhWp0LKb6_Zc,8928
15
15
  GameSentenceMiner/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- GameSentenceMiner/ai/ai_prompting.py,sha256=uTtXIDRpcQqPT4EC-R_pwRP9pBmZ64I6vMDOexhJRp8,9505
16
+ GameSentenceMiner/ai/ai_prompting.py,sha256=O1QBgCL6AkkDyhzxZuW8FPCKgUDfkl_ZlKGcEUfbRnk,9508
17
17
  GameSentenceMiner/communication/__init__.py,sha256=_jGn9PJxtOAOPtJ2rI-Qu9hEHVZVpIvWlxKvqk91_zI,638
18
18
  GameSentenceMiner/communication/send.py,sha256=oOJdCS6-LNX90amkRn5FL2xqx6THGm56zHR2ntVIFTE,229
19
19
  GameSentenceMiner/communication/websocket.py,sha256=pTcUe_ZZRp9REdSU4qalhPmbT_1DKa7w18j6RfFLELA,3074
@@ -35,9 +35,9 @@ GameSentenceMiner/owocr/owocr/run.py,sha256=f59MhlV9JVpzFAq7aW-_0I3FGnzKyw0OLOAg
35
35
  GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py,sha256=Na6XStbQBtpQUSdbN3QhEswtKuU1JjReFk_K8t5ezQE,3395
36
36
  GameSentenceMiner/vad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  GameSentenceMiner/vad/result.py,sha256=C08HsYH4qVjTRh_dvrWrskmXHJ950w0GWxPjGx_BfGY,275
38
- GameSentenceMiner/vad/silero_trim.py,sha256=c9T7td5kaSA0fokRHl84LiRXUtETyMULUw4UfSjZisA,1754
39
- GameSentenceMiner/vad/vosk_helper.py,sha256=ZrR3WLX8PC4pl9ONzkkalUVyiDexjKrmf9hqsDG-ej0,6143
40
- GameSentenceMiner/vad/whisper_helper.py,sha256=G164s1SE5k_W9bPXKsKTIAG68pzisgzTJ8ByvBmhSQg,3616
38
+ GameSentenceMiner/vad/silero_trim.py,sha256=L5OYAPi-L4uDn4nVAmTmdyrD_mVbmMbEXgQ7U16Kyjw,1631
39
+ GameSentenceMiner/vad/vosk_helper.py,sha256=0NoqzuMjcl3ueZv_KAcLt92el-38g-aTpl1fLs91PrA,6092
40
+ GameSentenceMiner/vad/whisper_helper.py,sha256=ulWDJypfBC6nEZyWp5j5nVCNeEukKvMiqWthMvIzvp4,3565
41
41
  GameSentenceMiner/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
42
  GameSentenceMiner/web/texthooking_page.py,sha256=AtVV9RS7HC3XnOq4X0FIMqJrzFoGlfSHFvS_CfhuzuA,13558
43
43
  GameSentenceMiner/web/static/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -52,9 +52,9 @@ GameSentenceMiner/web/static/web-app-manifest-512x512.png,sha256=wyqgCWCrLEUxSRX
52
52
  GameSentenceMiner/web/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  GameSentenceMiner/web/templates/text_replacements.html,sha256=tV5c8mCaWSt_vKuUpbdbLAzXZ3ATZeDvQ9PnnAfqY0M,8598
54
54
  GameSentenceMiner/web/templates/utility.html,sha256=NUp4Yjs6_j7YeqsM2rcF0LzwS6nXSBUWJDl-k2E8BbM,16270
55
- gamesentenceminer-2.8.27.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
56
- gamesentenceminer-2.8.27.dist-info/METADATA,sha256=YyFsH_0pIvAzqRYC0srO-cFN4xHyvT5GBdmfiSt3PBg,7165
57
- gamesentenceminer-2.8.27.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
58
- gamesentenceminer-2.8.27.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
59
- gamesentenceminer-2.8.27.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
60
- gamesentenceminer-2.8.27.dist-info/RECORD,,
55
+ gamesentenceminer-2.8.29.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
56
+ gamesentenceminer-2.8.29.dist-info/METADATA,sha256=kaomSNGLEqPQVqAqSrIRv9CvGhU4FOrpZ2gCmdBlwiQ,7165
57
+ gamesentenceminer-2.8.29.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
58
+ gamesentenceminer-2.8.29.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
59
+ gamesentenceminer-2.8.29.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
60
+ gamesentenceminer-2.8.29.dist-info/RECORD,,