"""Read-only deployed API checks; never requests any returned media URL.""" import argparse import hashlib import json from pathlib import Path import sqlite3 import time from urllib.error import HTTPError from urllib.request import Request, urlopen def main(): parser = argparse.ArgumentParser() parser.add_argument('--origin', default='https://reelbox.dartty.top:8443') parser.add_argument('--database', default='/root/moviebox-export/catalog.sqlite') parser.add_argument('--output', required=True) args = parser.parse_args() db = sqlite3.connect(Path(args.database).resolve().as_uri() + '?mode=ro', uri=True) timings = {} def get(path): start = time.monotonic() with urlopen(args.origin + path, timeout=40) as response: assert response.status == 200 assert 'application/json' in response.headers['Content-Type'] value = json.load(response) timings[path.split('?')[0]] = round(time.monotonic() - start, 3) return value health = get('/api/health') assert health['status'] == 'ok' and health['media_proxy'] is False and health['offline'] is True for table in ('titles', 'episodes', 'seasons', 'movie_sources', 'episode_sources'): assert health['counts'][table] == db.execute('SELECT count(*) FROM ' + table).fetchone()[0] home = get('/api/first/public/') assert home['genres'][0]['posters'] movies = get('/api/movie/by/filtres/0/created/0/public/') series = get('/api/serie/by/filtres/0/created/0/public/') assert movies and series movie = next((get('/api/movie/by/' + str(row['id']) + '/public/') for row in movies if db.execute('SELECT 1 FROM movie_sources WHERE title_id=? LIMIT 1', (row['id'],)).fetchone()), None) assert movie and movie['sources'] expected = [json.loads(r[0]) for r in db.execute('SELECT raw_json FROM movie_sources WHERE title_id=? ORDER BY source_index', (movie['id'],))] assert movie['sources'] == expected, 'Movie source records changed' seasons = get('/api/season/by/serie/' + str(series[0]['id']) + '/public/') expected_seasons = [json.loads(r[0]) for r in db.execute('SELECT raw_json FROM seasons WHERE series_id=? ORDER BY season_index', (series[0]['id'],))] actual_urls = [source['url'] for season in seasons for ep in season.get('episodes', []) for source in ep.get('sources', [])] expected_urls = [source['url'] for season in expected_seasons for ep in season.get('episodes', []) for source in ep.get('sources', [])] assert actual_urls and actual_urls == expected_urls, 'Episode source URLs changed' for url in actual_urls + [source['url'] for source in movie['sources']]: from urllib.parse import urlsplit assert urlsplit(url).hostname not in {'reelbox.dartty.top', '87.107.110.187'} search = get('/api-user/newapi/like.php?action=search-movie-en&q=Matrix&pageno=1') assert search assert get('/api-user/newapi/filter.php?action=pishnahad&garid=2&pageno=1') assert get('/api/genre/all/public/') and get('/api/country/all/public/') assert get('/api-user/newapi/pishnahad.php') rejected = {} for method, path in [('GET', '/api/proxy?url=https://media.example/movie.mkv'), ('GET', '/api/movie.mkv'), ('GET', '/api/comments/by/poster/1/public/'), ('GET', '/api-user/newapi/like.php?action=search-movie&url=http://127.0.0.1/'), ('GET', '/catalog.sqlite'), ('POST', '/api/health')]: try: with urlopen(Request(args.origin + path, method=method), timeout=15) as response: raise AssertionError('Unexpected accepted request: ' + path + ' status=' + str(response.status)) except HTTPError as error: assert error.code in {400, 403, 404, 405} rejected[method + ' ' + path] = error.code error.close() with urlopen(args.origin + '/', timeout=15) as response: assert response.status == 200 and b'Reelbox' in response.read() report = {'passed': True, 'origin': args.origin, 'health': health, 'movie_id': movie['id'], 'series_id': series[0]['id'], 'movie_source_records_match_snapshot': len(expected), 'episode_source_urls_match_snapshot': len(actual_urls), 'search_matches': len(search), 'rejected_routes': rejected, 'website_still_available': True, 'media_downloaded': False, 'seconds_by_route': timings} output = Path(args.output) output.parent.mkdir(parents=True, exist_ok=True) output.write_text(json.dumps(report, indent=2) + '\n') print(json.dumps(report, indent=2)) db.close() if __name__ == '__main__': main()