GameSentenceMiner 2.16.13__tar.gz → 2.17.1__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.
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/anki.py +7 -2
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/config_gui.py +7 -1
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/gametext.py +6 -4
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/gsm.py +11 -10
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/obs.py +42 -7
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/owocr_area_selector.py +1 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/owocr_helper.py +10 -7
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/run.py +9 -3
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/ffmpeg.py +5 -2
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/vad.py +5 -2
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/database_api.py +4 -4
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/shared.js +4 -4
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/PKG-INFO +1 -1
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/PKG-INFO +1 -1
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/pyproject.toml +3 -3
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ai/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ai/ai_prompting.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/assets/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/assets/icon.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/assets/icon128.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/assets/icon256.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/assets/icon32.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/assets/icon512.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/assets/icon64.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/assets/pickaxe.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/locales/en_us.json +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/locales/ja_jp.json +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/locales/zh_cn.json +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/gsm_ocr_config.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/ocrconfig.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/ss_picker.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/__main__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/config.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/lens_betterproto.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/ocr.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/tools/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/tools/audio_offset_selector.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/tools/furigana_filter_preview.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/tools/ss_selector.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/tools/window_transparency.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/communication/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/communication/send.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/communication/websocket.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/configuration.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/db.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/downloader/Untitled_json.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/downloader/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/downloader/download_tools.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/downloader/oneocr_dl.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/electron_config.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/get_overlay_coords.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/gsm_utils.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/model.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/notification.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/text_log.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/win10toast/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/win10toast/__main__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/events.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/gsm_websocket.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/service.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/__init__.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/apple-touch-icon.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/css/kanji-grid.css +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/css/search.css +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/css/shared.css +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/css/stats.css +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/favicon-96x96.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/favicon.ico +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/favicon.svg +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/anki_stats.js +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/database.js +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/kanji-grid.js +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/search.js +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/stats.js +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/site.webmanifest +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/style.css +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/web-app-manifest-192x192.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/web-app-manifest-512x512.png +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/stats.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/anki_stats.html +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/components/navigation.html +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/components/theme-styles.html +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/database.html +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/index.html +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/search.html +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/stats.html +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/utility.html +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/texthooking_page.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/wip/__init___.py +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/SOURCES.txt +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/dependency_links.txt +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/entry_points.txt +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/requires.txt +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/top_level.txt +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/LICENSE +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/README.md +0 -0
- {gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/setup.cfg +0 -0
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import copy
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import threading
|
|
2
6
|
from pathlib import Path
|
|
3
7
|
import queue
|
|
4
8
|
import time
|
|
@@ -15,8 +19,8 @@ from GameSentenceMiner.util.db import GameLinesTable
|
|
|
15
19
|
from GameSentenceMiner.util.gsm_utils import make_unique, sanitize_filename, wait_for_stable_file, remove_html_and_cloze_tags, combine_dialogue, \
|
|
16
20
|
run_new_thread, open_audio_in_external
|
|
17
21
|
from GameSentenceMiner.util import ffmpeg, notification
|
|
18
|
-
from GameSentenceMiner.util.configuration import
|
|
19
|
-
|
|
22
|
+
from GameSentenceMiner.util.configuration import get_config, AnkiUpdateResult, logger, anki_results, gsm_status, \
|
|
23
|
+
gsm_state
|
|
20
24
|
from GameSentenceMiner.util.model import AnkiCard
|
|
21
25
|
from GameSentenceMiner.util.text_log import get_all_lines, get_text_event, get_mined_line, lines_match
|
|
22
26
|
from GameSentenceMiner.obs import get_current_game
|
|
@@ -490,6 +494,7 @@ def update_card_from_same_sentence(last_card, lines, game_line):
|
|
|
490
494
|
card_queue.pop(0)
|
|
491
495
|
logger.error(f"Error saving replay buffer: {e}")
|
|
492
496
|
return
|
|
497
|
+
return
|
|
493
498
|
anki_result = anki_results[game_line.id]
|
|
494
499
|
if anki_result.success:
|
|
495
500
|
note, last_card = get_initial_card_info(last_card, lines)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import copy
|
|
3
3
|
import json
|
|
4
|
+
import os
|
|
4
5
|
import subprocess
|
|
6
|
+
import sys
|
|
5
7
|
import time
|
|
6
8
|
import tkinter as tk
|
|
7
9
|
from tkinter import filedialog, messagebox, simpledialog, scrolledtext, font
|
|
@@ -12,7 +14,11 @@ import ttkbootstrap as ttk
|
|
|
12
14
|
from GameSentenceMiner import obs
|
|
13
15
|
from GameSentenceMiner.util import configuration
|
|
14
16
|
from GameSentenceMiner.util.communication.send import send_restart_signal
|
|
15
|
-
from GameSentenceMiner.util.configuration import
|
|
17
|
+
from GameSentenceMiner.util.configuration import Config, Locale, logger, CommonLanguages, ProfileConfig, General, Paths, \
|
|
18
|
+
Anki, Features, Screenshot, Audio, OBS, Hotkeys, VAD, Overlay, Ai, Advanced, OverlayEngine, get_app_directory, \
|
|
19
|
+
get_config, is_beangate, AVAILABLE_LANGUAGES, WHSIPER_LARGE, WHISPER_TINY, WHISPER_BASE, WHISPER_SMALL, \
|
|
20
|
+
WHISPER_MEDIUM, WHISPER_TURBO, SILERO, WHISPER, OFF, gsm_state, DEFAULT_CONFIG, get_latest_version, \
|
|
21
|
+
get_current_version, AI_GEMINI, AI_GROQ, AI_OPENAI, save_full_config, get_default_anki_media_collection_path
|
|
16
22
|
from GameSentenceMiner.util.db import AIModelsTable
|
|
17
23
|
from GameSentenceMiner.util.downloader.download_tools import download_ocenaudio_if_needed
|
|
18
24
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import json
|
|
2
3
|
import re
|
|
4
|
+
from datetime import datetime
|
|
3
5
|
|
|
4
6
|
import pyperclip
|
|
5
7
|
import requests
|
|
@@ -7,12 +9,11 @@ import websockets
|
|
|
7
9
|
from websockets import InvalidStatus
|
|
8
10
|
from rapidfuzz import fuzz
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
from GameSentenceMiner.util.configuration import get_config, gsm_status, logger, gsm_state
|
|
11
13
|
from GameSentenceMiner.util.db import GameLinesTable
|
|
12
14
|
from GameSentenceMiner.util.gsm_utils import do_text_replacements, TEXT_REPLACEMENTS_FILE, run_new_thread
|
|
13
|
-
from GameSentenceMiner.util.configuration import *
|
|
14
|
-
from GameSentenceMiner.util.text_log import *
|
|
15
15
|
from GameSentenceMiner import obs
|
|
16
|
+
from GameSentenceMiner.util.text_log import add_line, get_text_log
|
|
16
17
|
from GameSentenceMiner.web.texthooking_page import add_event_to_texthooker, overlay_server_thread
|
|
17
18
|
|
|
18
19
|
from GameSentenceMiner.util.get_overlay_coords import OverlayProcessor
|
|
@@ -83,6 +84,7 @@ async def listen_websockets():
|
|
|
83
84
|
line_time = None
|
|
84
85
|
while True:
|
|
85
86
|
message = await websocket.recv()
|
|
87
|
+
message_received_time = datetime.now()
|
|
86
88
|
if not message:
|
|
87
89
|
continue
|
|
88
90
|
logger.debug(message)
|
|
@@ -97,7 +99,7 @@ async def listen_websockets():
|
|
|
97
99
|
logger.info
|
|
98
100
|
if current_clipboard != current_line:
|
|
99
101
|
try:
|
|
100
|
-
await handle_new_text_event(current_clipboard, line_time if line_time else
|
|
102
|
+
await handle_new_text_event(current_clipboard, line_time if line_time else message_received_time)
|
|
101
103
|
except Exception as e:
|
|
102
104
|
logger.error(f"Error handling new text event: {e}", exc_info=True)
|
|
103
105
|
except (websockets.ConnectionClosed, ConnectionError, InvalidStatus, ConnectionResetError, Exception) as e:
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import tempfile
|
|
2
|
-
import time
|
|
3
1
|
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
4
|
import subprocess
|
|
5
5
|
import sys
|
|
6
|
-
|
|
7
|
-
import
|
|
6
|
+
import tempfile
|
|
7
|
+
import threading
|
|
8
|
+
import time
|
|
8
9
|
import warnings
|
|
9
10
|
|
|
10
11
|
import requests
|
|
@@ -42,7 +43,10 @@ try:
|
|
|
42
43
|
import psutil
|
|
43
44
|
|
|
44
45
|
start_time = time.time()
|
|
45
|
-
from GameSentenceMiner.util.configuration import
|
|
46
|
+
from GameSentenceMiner.util.configuration import logger, gsm_state, get_config, anki_results, AnkiUpdateResult, \
|
|
47
|
+
get_temporary_directory, get_log_path, get_master_config, switch_profile_and_save, get_app_directory, gsm_status, \
|
|
48
|
+
is_windows, is_linux
|
|
49
|
+
|
|
46
50
|
logger.debug(f"[Import] configuration: {time.time() - start_time:.3f}s")
|
|
47
51
|
|
|
48
52
|
start_time = time.time()
|
|
@@ -113,10 +117,6 @@ try:
|
|
|
113
117
|
logger.debug(
|
|
114
118
|
f"[Import] util.text_log (GameLine, get_text_event, get_mined_line, get_all_lines, game_log): {time.time() - start_time:.3f}s")
|
|
115
119
|
|
|
116
|
-
start_time = time.time()
|
|
117
|
-
from GameSentenceMiner.util import *
|
|
118
|
-
logger.debug(f"[Import] util *: {time.time() - start_time:.3f}s")
|
|
119
|
-
|
|
120
120
|
start_time = time.time()
|
|
121
121
|
from GameSentenceMiner.web import texthooking_page
|
|
122
122
|
logger.debug(
|
|
@@ -675,6 +675,7 @@ def initialize_async():
|
|
|
675
675
|
|
|
676
676
|
|
|
677
677
|
def handle_websocket_message(message: Message):
|
|
678
|
+
logger.info(f"WebSocket Message Received: {message.to_json()}")
|
|
678
679
|
try:
|
|
679
680
|
match FunctionName(message.function):
|
|
680
681
|
case FunctionName.QUIT:
|
|
@@ -683,7 +684,7 @@ def handle_websocket_message(message: Message):
|
|
|
683
684
|
case FunctionName.QUIT_OBS:
|
|
684
685
|
close_obs()
|
|
685
686
|
case FunctionName.START_OBS:
|
|
686
|
-
obs.start_obs()
|
|
687
|
+
obs.start_obs(force_restart=not gsm_status.obs_connected)
|
|
687
688
|
case FunctionName.OPEN_SETTINGS:
|
|
688
689
|
open_settings()
|
|
689
690
|
case FunctionName.OPEN_TEXTHOOKER:
|
|
@@ -6,6 +6,7 @@ import threading
|
|
|
6
6
|
import time
|
|
7
7
|
import logging
|
|
8
8
|
import contextlib
|
|
9
|
+
import shutil
|
|
9
10
|
|
|
10
11
|
import psutil
|
|
11
12
|
|
|
@@ -164,38 +165,57 @@ class OBSConnectionManager(threading.Thread):
|
|
|
164
165
|
self.counter = 0
|
|
165
166
|
return
|
|
166
167
|
start_replay_buffer()
|
|
167
|
-
|
|
168
|
+
|
|
168
169
|
def get_obs_path():
|
|
169
170
|
return os.path.join(configuration.get_app_directory(), 'obs-studio/bin/64bit/obs64.exe')
|
|
170
171
|
|
|
171
172
|
def is_process_running(pid):
|
|
172
173
|
try:
|
|
173
174
|
process = psutil.Process(pid)
|
|
174
|
-
return 'obs' in process.exe()
|
|
175
|
+
return 'obs' in process.exe().lower()
|
|
175
176
|
except (psutil.NoSuchProcess, psutil.AccessDenied, OSError):
|
|
176
177
|
if os.path.exists(OBS_PID_FILE):
|
|
177
178
|
os.remove(OBS_PID_FILE)
|
|
178
179
|
return False
|
|
179
180
|
|
|
180
|
-
def start_obs():
|
|
181
|
+
def start_obs(force_restart=False):
|
|
181
182
|
global obs_process_pid
|
|
182
183
|
if os.path.exists(OBS_PID_FILE):
|
|
183
184
|
with open(OBS_PID_FILE, "r") as f:
|
|
184
185
|
try:
|
|
185
186
|
obs_process_pid = int(f.read().strip())
|
|
186
187
|
if is_process_running(obs_process_pid):
|
|
187
|
-
|
|
188
|
-
|
|
188
|
+
if force_restart:
|
|
189
|
+
try:
|
|
190
|
+
process = psutil.Process(obs_process_pid)
|
|
191
|
+
process.terminate()
|
|
192
|
+
process.wait(timeout=10)
|
|
193
|
+
print("OBS process terminated for restart.")
|
|
194
|
+
except Exception as e:
|
|
195
|
+
print(f"Error terminating OBS process: {e}")
|
|
196
|
+
else:
|
|
197
|
+
return obs_process_pid
|
|
189
198
|
except ValueError:
|
|
190
199
|
print("Invalid PID found in file. Launching new OBS instance.")
|
|
191
200
|
except OSError:
|
|
192
|
-
print("No process found with the stored PID. Launching new OBS instance.")
|
|
201
|
+
print("No process found with the stored PID. Launching new OBS instance.")
|
|
193
202
|
|
|
194
203
|
obs_path = get_obs_path()
|
|
195
204
|
if not os.path.exists(obs_path):
|
|
196
205
|
print(f"OBS not found at {obs_path}. Please install OBS.")
|
|
197
206
|
return None
|
|
198
207
|
try:
|
|
208
|
+
sentinel_folder = os.path.join(configuration.get_app_directory(), 'obs-studio', 'config', 'obs-studio', '.sentinel')
|
|
209
|
+
if os.path.exists(sentinel_folder):
|
|
210
|
+
try:
|
|
211
|
+
if os.path.isdir(sentinel_folder):
|
|
212
|
+
shutil.rmtree(sentinel_folder)
|
|
213
|
+
else:
|
|
214
|
+
os.remove(sentinel_folder)
|
|
215
|
+
print(f"Deleted sentinel folder: {sentinel_folder}")
|
|
216
|
+
except Exception as e:
|
|
217
|
+
print(f"Failed to delete sentinel folder: {e}")
|
|
218
|
+
|
|
199
219
|
obs_process = subprocess.Popen([obs_path, '--disable-shutdown-check', '--portable', '--startreplaybuffer', ], cwd=os.path.dirname(obs_path))
|
|
200
220
|
obs_process_pid = obs_process.pid
|
|
201
221
|
with open(OBS_PID_FILE, "w") as f:
|
|
@@ -663,8 +683,23 @@ def main():
|
|
|
663
683
|
update_current_game()
|
|
664
684
|
print("Testing `get_current_game`:", get_current_game())
|
|
665
685
|
disconnect_from_obs()
|
|
686
|
+
|
|
687
|
+
def create_scene():
|
|
688
|
+
with connection_pool.get_client() as client:
|
|
689
|
+
# Extract fields from request_json
|
|
690
|
+
request_json = r'{"sceneName":"SILENT HILL f","inputName":"SILENT HILL f - Capture","inputKind":"window_capture","inputSettings":{"mode":"window","window":"SILENT HILL f :UnrealWindow:SHf-Win64-Shipping.exe","capture_audio":true,"cursor":false,"method":"2"}}'
|
|
691
|
+
request_dict = json.loads(request_json)
|
|
692
|
+
scene_name = request_dict.get('sceneName')
|
|
693
|
+
input_name = request_dict.get('inputName')
|
|
694
|
+
input_kind = request_dict.get('inputKind')
|
|
695
|
+
input_settings = request_dict.get('inputSettings')
|
|
696
|
+
input_settings['method'] = 2
|
|
697
|
+
# Remove sceneName from request_dict if needed for create_input
|
|
698
|
+
request_dict.pop('sceneName', None)
|
|
699
|
+
response = client.create_input(inputName=input_name, inputKind=input_kind, sceneName=scene_name, inputSettings=input_settings, sceneItemEnabled=True)
|
|
666
700
|
|
|
667
701
|
if __name__ == '__main__':
|
|
668
702
|
logging.basicConfig(level=logging.INFO)
|
|
669
703
|
connect_to_obs_sync()
|
|
670
|
-
set_fit_to_screen_for_scene_items(get_current_scene())
|
|
704
|
+
# set_fit_to_screen_for_scene_items(get_current_scene())
|
|
705
|
+
create_scene()
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/owocr_area_selector.py
RENAMED
|
@@ -328,6 +328,7 @@ class ScreenSelector:
|
|
|
328
328
|
"How to Use:\n"
|
|
329
329
|
" • Left Click + Drag: Create a capture area (green).\n"
|
|
330
330
|
" • Shift + Left Click + Drag: Create an exclusion area (orange).\n"
|
|
331
|
+
" • Ctrl + Left Click + Drag: Create a secondary (menu) area (purple).\n"
|
|
331
332
|
" • Right-Click on a box: Delete it.\n\n"
|
|
332
333
|
"Hotkeys:\n"
|
|
333
334
|
" • Ctrl + S: Save and Quit\n"
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/owocr_helper.py
RENAMED
|
@@ -19,13 +19,15 @@ from PIL import Image
|
|
|
19
19
|
from rapidfuzz import fuzz
|
|
20
20
|
|
|
21
21
|
from GameSentenceMiner import obs
|
|
22
|
-
from GameSentenceMiner.util.electron_config import *
|
|
23
22
|
from GameSentenceMiner.ocr.ss_picker import ScreenCropper
|
|
24
23
|
from GameSentenceMiner.owocr.owocr.run import TextFiltering
|
|
25
24
|
from GameSentenceMiner.util.configuration import get_config, get_app_directory, get_temporary_directory
|
|
26
25
|
from GameSentenceMiner.ocr.gsm_ocr_config import OCRConfig, has_config_changed, set_dpi_awareness, get_window, get_ocr_config_path
|
|
27
|
-
from GameSentenceMiner.owocr.owocr import
|
|
28
|
-
from GameSentenceMiner.util.
|
|
26
|
+
from GameSentenceMiner.owocr.owocr import run
|
|
27
|
+
from GameSentenceMiner.util.electron_config import get_ocr_ocr2, get_ocr_send_to_clipboard, get_ocr_scan_rate, \
|
|
28
|
+
has_ocr_config_changed, reload_electron_config, get_ocr_two_pass_ocr, get_ocr_optimize_second_scan, \
|
|
29
|
+
get_ocr_language, get_ocr_manual_ocr_hotkey
|
|
30
|
+
from GameSentenceMiner.util.gsm_utils import sanitize_filename
|
|
29
31
|
import threading
|
|
30
32
|
import time
|
|
31
33
|
|
|
@@ -420,7 +422,7 @@ def get_ocr2_image(crop_coords, og_image: Image.Image, ocr2_engine=None):
|
|
|
420
422
|
Logic is unchanged, but code is refactored for clarity and maintainability.
|
|
421
423
|
"""
|
|
422
424
|
def return_original_image():
|
|
423
|
-
logger.
|
|
425
|
+
logger.debug("Returning original image for OCR2 (no cropping or optimization).")
|
|
424
426
|
if not crop_coords or not get_ocr_optimize_second_scan():
|
|
425
427
|
return og_image
|
|
426
428
|
x1, y1, x2, y2 = crop_coords
|
|
@@ -546,9 +548,10 @@ def add_ss_hotkey(ss_hotkey="ctrl+shift+g"):
|
|
|
546
548
|
ocr_config = get_ocr_config()
|
|
547
549
|
img = obs.get_screenshot_PIL(compression=80, img_format="jpg")
|
|
548
550
|
ocr_config.scale_to_custom_size(img.width, img.height)
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
551
|
+
for rectangle in [rectangle for rectangle in ocr_config.rectangles if rectangle.is_secondary]:
|
|
552
|
+
new_img = run.apply_ocr_config_to_image(img, ocr_config, is_secondary=True, rectangles=[rectangle])
|
|
553
|
+
do_second_ocr("", datetime.now(), new_img, TextFiltering(lang=get_ocr_language()), ignore_furigana_filter=True, ignore_previous_result=True)
|
|
554
|
+
|
|
552
555
|
filtering = TextFiltering(lang=get_ocr_language())
|
|
553
556
|
cropper = ScreenCropper()
|
|
554
557
|
def capture():
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
1
4
|
from GameSentenceMiner.ocr.gsm_ocr_config import set_dpi_awareness, get_scene_ocr_config
|
|
2
|
-
from GameSentenceMiner.util.electron_config import * # noqa: F403
|
|
3
5
|
from GameSentenceMiner.util.gsm_utils import do_text_replacements, OCR_REPLACEMENTS_FILE
|
|
6
|
+
from GameSentenceMiner.util.electron_config import get_ocr_language, get_ocr_requires_open_window, \
|
|
7
|
+
has_ocr_config_changed, reload_electron_config, get_ocr_scan_rate, get_ocr_two_pass_ocr, get_ocr_keep_newline, \
|
|
8
|
+
get_ocr_ocr1, get_furigana_filter_sensitivity
|
|
4
9
|
|
|
5
10
|
try:
|
|
6
11
|
import win32gui
|
|
@@ -1135,14 +1140,15 @@ def scale_down_width_height(width, height):
|
|
|
1135
1140
|
return width, height
|
|
1136
1141
|
|
|
1137
1142
|
|
|
1138
|
-
def apply_ocr_config_to_image(img, ocr_config, is_secondary=False):
|
|
1143
|
+
def apply_ocr_config_to_image(img, ocr_config, is_secondary=False, rectangles=None):
|
|
1139
1144
|
for rectangle in ocr_config.rectangles:
|
|
1140
1145
|
if rectangle.is_excluded:
|
|
1141
1146
|
left, top, width, height = rectangle.coordinates
|
|
1142
1147
|
draw = ImageDraw.Draw(img)
|
|
1143
1148
|
draw.rectangle((left, top, left + width, top + height), fill=(0, 0, 0, 0))
|
|
1144
1149
|
|
|
1145
|
-
|
|
1150
|
+
if not rectangles:
|
|
1151
|
+
rectangles = [r for r in ocr_config.rectangles if not r.is_excluded and r.is_secondary == is_secondary]
|
|
1146
1152
|
|
|
1147
1153
|
# Sort top to bottom
|
|
1148
1154
|
if rectangles:
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
1
3
|
import subprocess
|
|
4
|
+
import sys
|
|
2
5
|
import tempfile
|
|
3
6
|
import time
|
|
4
7
|
from pathlib import Path
|
|
5
8
|
|
|
6
9
|
from GameSentenceMiner import obs
|
|
10
|
+
from GameSentenceMiner.util.configuration import get_app_directory, is_windows, logger, get_config, \
|
|
11
|
+
get_temporary_directory, gsm_state, is_linux
|
|
7
12
|
from GameSentenceMiner.util.gsm_utils import make_unique_file_name, get_file_modification_time
|
|
8
13
|
from GameSentenceMiner.util import configuration
|
|
9
|
-
from GameSentenceMiner.util.configuration import *
|
|
10
|
-
from GameSentenceMiner.util.model import VADResult
|
|
11
14
|
from GameSentenceMiner.util.text_log import initial_time
|
|
12
15
|
|
|
13
16
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
1
5
|
import tempfile
|
|
2
6
|
import time
|
|
3
7
|
import warnings
|
|
4
|
-
import requests
|
|
5
8
|
from abc import abstractmethod, ABC
|
|
6
9
|
|
|
7
10
|
from GameSentenceMiner.util import configuration, ffmpeg
|
|
8
|
-
from GameSentenceMiner.util.configuration import
|
|
11
|
+
from GameSentenceMiner.util.configuration import get_config, get_temporary_directory, logger, SILERO, WHISPER
|
|
9
12
|
from GameSentenceMiner.util.ffmpeg import get_audio_length
|
|
10
13
|
from GameSentenceMiner.util.gsm_utils import make_unique_file_name, run_new_thread
|
|
11
14
|
from GameSentenceMiner.util.model import VADResult
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/database_api.py
RENAMED
|
@@ -335,8 +335,8 @@ def register_database_api_routes(app):
|
|
|
335
335
|
if afk_timer is not None:
|
|
336
336
|
try:
|
|
337
337
|
afk_timer = int(afk_timer)
|
|
338
|
-
if afk_timer <
|
|
339
|
-
return jsonify({'error': 'AFK timer must be between
|
|
338
|
+
if afk_timer < 0 or afk_timer > 600:
|
|
339
|
+
return jsonify({'error': 'AFK timer must be between 0 and 600 seconds'}), 400
|
|
340
340
|
settings_to_update['afk_timer_seconds'] = afk_timer
|
|
341
341
|
except (ValueError, TypeError):
|
|
342
342
|
return jsonify({'error': 'AFK timer must be a valid integer'}), 400
|
|
@@ -344,8 +344,8 @@ def register_database_api_routes(app):
|
|
|
344
344
|
if session_gap is not None:
|
|
345
345
|
try:
|
|
346
346
|
session_gap = int(session_gap)
|
|
347
|
-
if session_gap <
|
|
348
|
-
return jsonify({'error': 'Session gap must be between
|
|
347
|
+
if session_gap < 0 or session_gap > 7200:
|
|
348
|
+
return jsonify({'error': 'Session gap must be between 0 and 7200 seconds (0 to 2 hours)'}), 400
|
|
349
349
|
settings_to_update['session_gap_seconds'] = session_gap
|
|
350
350
|
except (ValueError, TypeError):
|
|
351
351
|
return jsonify({'error': 'Session gap must be a valid integer'}), 400
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/shared.js
RENAMED
|
@@ -392,8 +392,8 @@ class SettingsManager {
|
|
|
392
392
|
|
|
393
393
|
if (this.afkTimerInput) {
|
|
394
394
|
const afkTimer = parseInt(this.afkTimerInput.value);
|
|
395
|
-
if (isNaN(afkTimer) || afkTimer <
|
|
396
|
-
this.showError('AFK timer must be between
|
|
395
|
+
if (isNaN(afkTimer) || afkTimer < 0 || afkTimer > 600) {
|
|
396
|
+
this.showError('AFK timer must be between 0 and 600 seconds');
|
|
397
397
|
return;
|
|
398
398
|
}
|
|
399
399
|
settings.afk_timer_seconds = afkTimer;
|
|
@@ -401,8 +401,8 @@ class SettingsManager {
|
|
|
401
401
|
|
|
402
402
|
if (this.sessionGapInput) {
|
|
403
403
|
const sessionGap = parseInt(this.sessionGapInput.value);
|
|
404
|
-
if (isNaN(sessionGap) || sessionGap <
|
|
405
|
-
this.showError('Session gap must be between
|
|
404
|
+
if (isNaN(sessionGap) || sessionGap < 0 || sessionGap > 7200) {
|
|
405
|
+
this.showError('Session gap must be between 0 and 7200 seconds (0 to 2 hours)');
|
|
406
406
|
return;
|
|
407
407
|
}
|
|
408
408
|
settings.session_gap_seconds = sessionGap;
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "GameSentenceMiner"
|
|
10
|
-
version = "2.
|
|
10
|
+
version = "2.17.1"
|
|
11
11
|
description = "A tool for mining sentences from games. Update: Overlay?"
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.10"
|
|
@@ -61,8 +61,8 @@ dependencies = [
|
|
|
61
61
|
]
|
|
62
62
|
|
|
63
63
|
# This creates a command-line script named `gamesentenceminer` that will
|
|
64
|
-
# call the `main()` function defined in the package
|
|
65
|
-
# you
|
|
64
|
+
# call the `main()` function defined in the package's __main__.py (or wherever
|
|
65
|
+
# you've placed your entry function). Adjust the import path as needed.
|
|
66
66
|
[project.scripts]
|
|
67
67
|
gamesentenceminer = "GameSentenceMiner.gsm:main"
|
|
68
68
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/ocr/gsm_ocr_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/__init__.py
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/__main__.py
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/owocr/owocr/config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/tools/ss_selector.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/communication/send.py
RENAMED
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/configuration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/downloader/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/electron_config.py
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/get_overlay_coords.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/notification.py
RENAMED
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/win10toast/__init__.py
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/util/win10toast/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/gsm_websocket.py
RENAMED
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/css/search.css
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/css/shared.css
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/css/stats.css
RENAMED
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/favicon.ico
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/favicon.svg
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/anki_stats.js
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/database.js
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/kanji-grid.js
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/search.js
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/js/stats.js
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/site.webmanifest
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/static/style.css
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/database.html
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/index.html
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/search.html
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/stats.html
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/templates/utility.html
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner/web/texthooking_page.py
RENAMED
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/requires.txt
RENAMED
|
File without changes
|
{gamesentenceminer-2.16.13 → gamesentenceminer-2.17.1}/GameSentenceMiner.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|