## Overview This PR introduces HLS playback support, improves the player experience, and refactors documentation for better usability and maintainability. ## Key Features ### HLS Playback Support - Add HLS integration via new JavaScript assets: - `hls.min.js` - `plyr.hls.start.js` - `watch.hls.js` - Separate DASH and HLS logic: - `plyr-start.js` → `plyr.dash.start.js` - `watch.js` → `watch.dash.js` - Update templates (`embed.html`, `watch.html`) for conditional player loading ### Native Storyboard Preview - Add `native_player_storyboard` setting in `settings.py` - Implement hover thumbnail preview for native player modes - Add `storyboard-preview.js` ### UI and Player Adjustments - Update templates and styles (`custom_plyr.css`) - Modify backend modules to support new player modes: - `watch.py`, `channel.py`, `util.py`, and related components ### Internationalization - Update translation files: - `messages.po` - `messages.pot` ### Testing and CI - Add and update tests: - `test_shorts.py` - `test_util.py` - Minor CI and release script improvements ## Documentation ### OpenRC Service Guide Rewrite - Restructure `docs/basic-script-openrc/README.md` into: - Prerequisites - Installation - Service Management - Verification - Troubleshooting - Add admonition blocks: - `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, `[!CAUTION]` - Fix log inspection command: ```bash doas tail -f /var/log/ytlocal.log ```` * Add path placeholders and clarify permission requirements * Remove legacy and duplicate content Reviewed-on: #1 Co-authored-by: Astounds <kirito@disroot.org> Co-committed-by: Astounds <kirito@disroot.org>
78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
from youtube import util
|
|
import settings
|
|
import pytest # overview: https://realpython.com/pytest-python-testing/
|
|
import urllib3
|
|
import io
|
|
import os
|
|
import stem
|
|
|
|
|
|
def load_test_page(name):
|
|
with open(os.path.join('./tests/test_responses', name), 'rb') as f:
|
|
return f.read()
|
|
|
|
|
|
html429 = load_test_page('429.html')
|
|
|
|
|
|
class MockResponse(urllib3.response.HTTPResponse):
|
|
def __init__(self, body='success', headers=None, status=200, reason=''):
|
|
print(body[0:10])
|
|
headers = headers or {}
|
|
if isinstance(body, str):
|
|
body = body.encode('utf-8')
|
|
self.body_io = io.BytesIO(body)
|
|
self.read = self.body_io.read
|
|
urllib3.response.HTTPResponse.__init__(
|
|
self, body=body, headers=headers, status=status,
|
|
preload_content=False, decode_content=False, reason=reason
|
|
)
|
|
|
|
|
|
class NewIdentityState():
|
|
MAX_TRIES = util.TorManager.MAX_TRIES
|
|
def __init__(self, new_identities_till_success):
|
|
self.new_identities_till_success = new_identities_till_success
|
|
|
|
def new_identity(self, *args, **kwargs):
|
|
print('newidentity')
|
|
self.new_identities_till_success -= 1
|
|
|
|
def fetch_url_response(self, *args, **kwargs):
|
|
def cleanup_func(response):
|
|
return None
|
|
if self.new_identities_till_success == 0:
|
|
return MockResponse(), cleanup_func
|
|
return MockResponse(body=html429, status=429), cleanup_func
|
|
|
|
|
|
class MockController():
|
|
def authenticate(self, *args, **kwargs):
|
|
pass
|
|
@classmethod
|
|
def from_port(cls, *args, **kwargs):
|
|
return cls()
|
|
def __enter__(self, *args, **kwargs):
|
|
return self
|
|
def __exit__(self, *args, **kwargs):
|
|
pass
|
|
|
|
|
|
@pytest.mark.parametrize('new_identities_till_success',
|
|
[i for i in range(0, NewIdentityState.MAX_TRIES+2)])
|
|
def test_exit_node_retry(monkeypatch, new_identities_till_success):
|
|
new_identity_state = NewIdentityState(new_identities_till_success)
|
|
# https://docs.pytest.org/en/stable/monkeypatch.html
|
|
monkeypatch.setattr(settings, 'route_tor', 1)
|
|
monkeypatch.setattr(util, 'tor_manager', util.TorManager()) # fresh one
|
|
MockController.signal = new_identity_state.new_identity
|
|
monkeypatch.setattr(stem.control, 'Controller', MockController)
|
|
monkeypatch.setattr(util, 'fetch_url_response',
|
|
new_identity_state.fetch_url_response)
|
|
if new_identities_till_success <= NewIdentityState.MAX_TRIES:
|
|
assert util.fetch_url('url') == b'success'
|
|
else:
|
|
with pytest.raises(util.FetchError) as excinfo:
|
|
util.fetch_url('url')
|
|
assert int(excinfo.value.code) == 429
|