GameSentenceMiner 2.8.27__py3-none-any.whl → 2.8.28__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/ai/ai_prompting.py +3 -3
- GameSentenceMiner/anki.py +11 -8
- GameSentenceMiner/ffmpeg.py +16 -24
- GameSentenceMiner/gsm.py +7 -2
- GameSentenceMiner/vad/silero_trim.py +0 -2
- GameSentenceMiner/vad/vosk_helper.py +2 -3
- GameSentenceMiner/vad/whisper_helper.py +2 -3
- {gamesentenceminer-2.8.27.dist-info → gamesentenceminer-2.8.28.dist-info}/METADATA +1 -1
- {gamesentenceminer-2.8.27.dist-info → gamesentenceminer-2.8.28.dist-info}/RECORD +13 -13
- {gamesentenceminer-2.8.27.dist-info → gamesentenceminer-2.8.28.dist-info}/WHEEL +0 -0
- {gamesentenceminer-2.8.27.dist-info → gamesentenceminer-2.8.28.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.8.27.dist-info → gamesentenceminer-2.8.28.dist-info}/licenses/LICENSE +0 -0
- {gamesentenceminer-2.8.27.dist-info → gamesentenceminer-2.8.28.dist-info}/top_level.txt +0 -0
@@ -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.
|
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.
|
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.
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
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.
|
279
|
-
logger.info(f"
|
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:
|
GameSentenceMiner/ffmpeg.py
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
73
|
-
screenshot_time_from_beginning
|
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.
|
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.
|
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.
|
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.
|
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.
|
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,13 @@ 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,
|
154
|
+
if get_config().anki.previous_image_field and get_config().vad.do_vad_postprocessing:
|
155
|
+
prev_ss_timing = ffmpeg.get_screenshot_time(video_path, mined_line.prev,
|
156
|
+
vad_result=VideoToAudioHandler.get_audio(game_line=mined_line.prev,
|
157
|
+
next_line_time=mined_line.time,
|
158
|
+
video_path=video_path,
|
159
|
+
anki_card_creation_time=anki_card_creation_time,
|
160
|
+
timing_only=True) ,doing_multi_line=bool(selected_lines), previous_line=True)
|
156
161
|
|
157
162
|
if get_config().anki.update_anki and last_note:
|
158
163
|
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,11 +1,11 @@
|
|
1
1
|
GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
GameSentenceMiner/anki.py,sha256=
|
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=
|
6
|
+
GameSentenceMiner/ffmpeg.py,sha256=Gcx45ZwUTDjQ3fQkz1xm0Hcd4pT0X0n7AlADFlL-Srg,14509
|
7
7
|
GameSentenceMiner/gametext.py,sha256=VogQDs-VQ4dorqy8uvoklweeS58r3Th_yP-zn36e0u4,5556
|
8
|
-
GameSentenceMiner/gsm.py,sha256
|
8
|
+
GameSentenceMiner/gsm.py,sha256=n34QKzyYWW4WxPLcpEzKy1h_emYajPgIVWMnAo-bcPo,26034
|
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=
|
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=
|
39
|
-
GameSentenceMiner/vad/vosk_helper.py,sha256=
|
40
|
-
GameSentenceMiner/vad/whisper_helper.py,sha256=
|
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.
|
56
|
-
gamesentenceminer-2.8.
|
57
|
-
gamesentenceminer-2.8.
|
58
|
-
gamesentenceminer-2.8.
|
59
|
-
gamesentenceminer-2.8.
|
60
|
-
gamesentenceminer-2.8.
|
55
|
+
gamesentenceminer-2.8.28.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
56
|
+
gamesentenceminer-2.8.28.dist-info/METADATA,sha256=_DbgnRKkjL_Or7o4MCvXOhBgWKtCuBNuZzODY_HU_R4,7165
|
57
|
+
gamesentenceminer-2.8.28.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
58
|
+
gamesentenceminer-2.8.28.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
|
59
|
+
gamesentenceminer-2.8.28.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
|
60
|
+
gamesentenceminer-2.8.28.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|