diff options
| author | Astounds <kirito@disroot.org> | 2026-04-20 01:22:55 -0400 |
|---|---|---|
| committer | heckyel <heckyel@noreply.git.fridu.us> | 2026-04-20 01:22:55 -0400 |
| commit | a0f315be51ef121618e73d5b450c8616c0d11d21 (patch) | |
| tree | b68f1268a901ded1a7afd2f12a16aed8d9f3d307 /tests/test_shorts.py | |
| parent | 62a028968e6d9b4e821b6014d6658b8317328fcf (diff) | |
| download | yt-local-0.5.0.tar.lz yt-local-0.5.0.tar.xz yt-local-0.5.0.zip | |
feature/hls: Add HLS playback support, and refactors documentation for better usability and maintainability. (#1)HEADv0.5.0master
## 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: https://git.fridu.us/heckyel/yt-local/pulls/1
Co-authored-by: Astounds <kirito@disroot.org>
Co-committed-by: Astounds <kirito@disroot.org>
Diffstat (limited to 'tests/test_shorts.py')
| -rw-r--r-- | tests/test_shorts.py | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/tests/test_shorts.py b/tests/test_shorts.py index edf7d73..c5b7301 100644 --- a/tests/test_shorts.py +++ b/tests/test_shorts.py @@ -11,8 +11,7 @@ import pytest sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) import youtube.proto as proto from youtube.yt_data_extract.common import ( - extract_item_info, extract_items, extract_shorts_lockup_view_model_info, - extract_approx_int, + extract_item_info, extract_items, ) @@ -58,6 +57,59 @@ class TestChannelCtokenV5: assert t_shorts != t_streams assert t_videos != t_streams + def test_include_shorts_false_adds_filter(self): + """Test that include_shorts=False adds the shorts filter (field 104).""" + # Token with shorts included (default) + t_with_shorts = self.channel_ctoken_v5('UCtest', '1', '3', 'videos', include_shorts=True) + # Token with shorts excluded + t_without_shorts = self.channel_ctoken_v5('UCtest', '1', '3', 'videos', include_shorts=False) + + # The tokens should be different because of the shorts filter + assert t_with_shorts != t_without_shorts + + # Decode and verify the filter is present + raw_with_shorts = base64.urlsafe_b64decode(t_with_shorts + '==') + raw_without_shorts = base64.urlsafe_b64decode(t_without_shorts + '==') + + # Parse the outer protobuf structure + import youtube.proto as proto + outer_fields_with = list(proto.read_protobuf(raw_with_shorts)) + outer_fields_without = list(proto.read_protobuf(raw_without_shorts)) + + # Field 80226972 contains the inner data + inner_with = [v for _, fn, v in outer_fields_with if fn == 80226972][0] + inner_without = [v for _, fn, v in outer_fields_without if fn == 80226972][0] + + # Parse the inner data - field 3 contains percent-encoded base64 data + inner_fields_with = list(proto.read_protobuf(inner_with)) + inner_fields_without = list(proto.read_protobuf(inner_without)) + + # Get field 3 data (the encoded inner which is percent-encoded base64) + encoded_inner_with = [v for _, fn, v in inner_fields_with if fn == 3][0] + encoded_inner_without = [v for _, fn, v in inner_fields_without if fn == 3][0] + + # The inner without shorts should contain field 104 + # Decode the percent-encoded base64 data + import urllib.parse + decoded_with = urllib.parse.unquote(encoded_inner_with.decode('ascii')) + decoded_without = urllib.parse.unquote(encoded_inner_without.decode('ascii')) + + # Decode the base64 data + decoded_with_bytes = base64.urlsafe_b64decode(decoded_with + '==') + decoded_without_bytes = base64.urlsafe_b64decode(decoded_without + '==') + + # Parse the decoded protobuf data + fields_with = list(proto.read_protobuf(decoded_with_bytes)) + fields_without = list(proto.read_protobuf(decoded_without_bytes)) + + field_numbers_with = [fn for _, fn, _ in fields_with] + field_numbers_without = [fn for _, fn, _ in fields_without] + + # The 'with' version should NOT have field 104 + assert 104 not in field_numbers_with + # The 'without' version SHOULD have field 104 + assert 104 in field_numbers_without + # --- shortsLockupViewModel parsing --- |
