Chat monitors stream to end
This commit is contained in:
parent
b50a4bad02
commit
38d51636af
4 changed files with 89 additions and 1 deletions
|
|
@ -365,6 +365,7 @@ class ContentDownloader:
|
|||
max_messages: Optional[int] = None,
|
||||
timeout: Optional[float] = None,
|
||||
shutdown_check: Optional[callable] = None,
|
||||
stream_monitor = None,
|
||||
verbose: bool = False) -> bool:
|
||||
"""
|
||||
Download live chat using chat_downloader library as fallback.
|
||||
|
|
@ -376,6 +377,7 @@ class ContentDownloader:
|
|||
max_messages: Maximum messages to download (None = unlimited)
|
||||
timeout: Stop after this many seconds (None = until stream ends)
|
||||
shutdown_check: Optional callback function that returns True when shutdown requested
|
||||
stream_monitor: Optional stream monitor to check if stream is still live
|
||||
verbose: Show chat message previews
|
||||
|
||||
Returns:
|
||||
|
|
@ -414,7 +416,10 @@ class ContentDownloader:
|
|||
# The get_chat with output parameter writes to file automatically
|
||||
# We just need to iterate to trigger the download
|
||||
message_count = 0
|
||||
print(f'{Fore.CYAN}Receiving chat messages (press Ctrl+C to stop)...{Style.RESET_ALL}')
|
||||
last_check_time = time.time()
|
||||
check_interval = 10.0 # Check if stream is still live every 10 seconds
|
||||
|
||||
print(f'{Fore.CYAN}Receiving chat messages (will stop when stream ends)...{Style.RESET_ALL}')
|
||||
try:
|
||||
for message in chat:
|
||||
# Check for shutdown request
|
||||
|
|
@ -422,6 +427,19 @@ class ContentDownloader:
|
|||
print(f'\n{Fore.YELLOW}⚠ Chat download stopped by shutdown request{Style.RESET_ALL}')
|
||||
break
|
||||
|
||||
# Periodically check if stream is still live
|
||||
current_time = time.time()
|
||||
if stream_monitor and (current_time - last_check_time) >= check_interval:
|
||||
last_check_time = current_time
|
||||
try:
|
||||
is_live = stream_monitor.is_user_live()
|
||||
if not is_live:
|
||||
print(f'\n{Fore.YELLOW}⚠ Stream ended, stopping chat download{Style.RESET_ALL}')
|
||||
break
|
||||
except Exception as check_error:
|
||||
print(f'\n{Fore.YELLOW}⚠ Could not check stream status: {check_error}{Style.RESET_ALL}')
|
||||
# Continue downloading to avoid false positives from API errors
|
||||
|
||||
message_count += 1
|
||||
|
||||
# Show progress every 100 messages
|
||||
|
|
@ -467,6 +485,7 @@ class ContentDownloader:
|
|||
|
||||
def start_chat_downloader_thread(self, username: str, json_path: str,
|
||||
shutdown_check: Optional[callable] = None,
|
||||
stream_monitor = None,
|
||||
verbose: bool = False) -> threading.Thread:
|
||||
"""
|
||||
Start chat_downloader in a background thread.
|
||||
|
|
@ -475,6 +494,7 @@ class ContentDownloader:
|
|||
username: Twitch username
|
||||
json_path: Path to save chat JSON
|
||||
shutdown_check: Callback to check for shutdown
|
||||
stream_monitor: Optional stream monitor to check if stream is still live
|
||||
verbose: Show chat previews
|
||||
|
||||
Returns:
|
||||
|
|
@ -485,6 +505,7 @@ class ContentDownloader:
|
|||
self.chat_thread_success = self.download_live_chat_with_chat_downloader(
|
||||
username, json_path,
|
||||
shutdown_check=shutdown_check,
|
||||
stream_monitor=stream_monitor,
|
||||
verbose=verbose
|
||||
)
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -115,6 +115,34 @@ class StreamMonitor:
|
|||
print(f'{Fore.YELLOW} {str(e)}{Style.RESET_ALL}')
|
||||
sys.exit(1)
|
||||
|
||||
def is_user_live(self) -> bool:
|
||||
"""
|
||||
Check if the configured user is currently live.
|
||||
|
||||
Returns:
|
||||
bool: True if user is live, False if offline
|
||||
|
||||
Raises:
|
||||
Exception: If API request fails (caller should handle)
|
||||
"""
|
||||
query = f'query{{user(login: "{self.username}") {{stream{{id title}}}}}}'
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
TWITCH_GQL_URL,
|
||||
json={'query': query},
|
||||
headers={"Client-ID": TWITCH_GQL_CLIENT_ID},
|
||||
timeout=15
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
stream_data = data.get('data', {}).get('user', {}).get('stream')
|
||||
return stream_data is not None
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
# Don't exit, let caller handle this
|
||||
raise Exception(f"Failed to check if user is live: {str(e)}")
|
||||
|
||||
def get_latest_vod(self) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Get the most recent VOD for the configured user.
|
||||
|
|
|
|||
37
run_tests.ps1
Normal file
37
run_tests.ps1
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# PowerShell script to run Twitch Archive unit tests
|
||||
# Run this script to execute all unit tests
|
||||
|
||||
Write-Host "======================================================================" -ForegroundColor Cyan
|
||||
Write-Host "TWITCH ARCHIVE - Running Unit Tests" -ForegroundColor Cyan
|
||||
Write-Host "======================================================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Check if virtual environment exists and activate it
|
||||
$venvPath = ".\venv314\Scripts\Activate.ps1"
|
||||
if (Test-Path $venvPath) {
|
||||
Write-Host "✓ Activating virtual environment..." -ForegroundColor Green
|
||||
& $venvPath
|
||||
} else {
|
||||
Write-Host "⚠ Virtual environment not found at $venvPath" -ForegroundColor Yellow
|
||||
Write-Host " Continuing with system Python..." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
|
||||
# Run the tests
|
||||
Write-Host "Running unit tests..." -ForegroundColor Cyan
|
||||
python test_twitch_archive_simple.py
|
||||
|
||||
# Check exit code
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host ""
|
||||
Write-Host "======================================================================" -ForegroundColor Green
|
||||
Write-Host "✓ ALL TESTS PASSED" -ForegroundColor Green
|
||||
Write-Host "======================================================================" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host ""
|
||||
Write-Host "======================================================================" -ForegroundColor Red
|
||||
Write-Host "✗ SOME TESTS FAILED" -ForegroundColor Red
|
||||
Write-Host "======================================================================" -ForegroundColor Red
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
|
@ -1088,6 +1088,7 @@ class TwitchArchiveManager:
|
|||
archiver.downloader.start_chat_downloader_thread(
|
||||
archiver.username, chat_json_path,
|
||||
shutdown_check=lambda: self.shutdown_requested or archiver.shutdown_requested,
|
||||
stream_monitor=archiver.stream_monitor,
|
||||
verbose=self.verbose
|
||||
)
|
||||
except Exception as e:
|
||||
|
|
@ -1116,6 +1117,7 @@ class TwitchArchiveManager:
|
|||
archiver.downloader.start_chat_downloader_thread(
|
||||
archiver.username, chat_json_path,
|
||||
shutdown_check=lambda: self.shutdown_requested or archiver.shutdown_requested,
|
||||
stream_monitor=archiver.stream_monitor,
|
||||
verbose=self.verbose or self.chat_only
|
||||
)
|
||||
# Wait for completion
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue