Skip to content

Commit e221361

Browse files
authored
Merge pull request #1146 from tcely/patch-14
Create `yt_dlp_plugins`
2 parents b11d7d4 + 9fe40cd commit e221361

File tree

3 files changed

+117
-2
lines changed

3 files changed

+117
-2
lines changed

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,9 @@ HEALTHCHECK --interval=1m --timeout=10s --start-period=3m CMD ["/app/healthcheck
534534
ENV PYTHONPATH="/app" \
535535
PYTHONPYCACHEPREFIX="/config/cache/pycache" \
536536
S6_CMD_WAIT_FOR_SERVICES_MAXTIME="0" \
537-
XDG_CACHE_HOME="/config/cache"
537+
XDG_CACHE_HOME="/config/cache" \
538+
XDG_CONFIG_HOME="/config/tubesync" \
539+
XDG_STATE_HOME="/config/state"
538540
EXPOSE 4848
539541

540542
# Volumes

config/root/etc/s6-overlay/s6-rc.d/tubesync-init/run

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ groupmod -o -g "${PGID:=911}" app
55
usermod -o -u "${PUID:=911}" app
66

77
# Ensure /config directories exist
8-
mkdir -v -p /config/{cache,media,tasks,tubesync}
8+
mkdir -v -p /config/{cache,media,state,tasks,tubesync}
99

1010
# Copy local_settings.py for the user
1111
if [ -f /config/tubesync/local_settings.py ]
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
from collections.abc import Generator
2+
from common.utils import getenv
3+
from datetime import datetime, timezone
4+
from pathlib import Path
5+
from yt_dlp.extractor.youtube.pot.cache import (
6+
PoTokenCacheProvider,
7+
register_preference,
8+
register_provider
9+
)
10+
11+
from yt_dlp.extractor.youtube.pot.provider import PoTokenRequest
12+
13+
14+
@register_provider
15+
class TubeSyncFileSystemPCP(PoTokenCacheProvider): # Provider class name must end with "PCP"
16+
PROVIDER_VERSION = '0.0.1'
17+
# Define a unique display name for the provider
18+
PROVIDER_NAME = 'TubeSync-fs'
19+
BUG_REPORT_LOCATION = 'https://github.com/meeb/tubesync/issues'
20+
21+
def _now(self) -> datetime:
22+
return datetime.now(timezone.utc)
23+
24+
def _make_filename(self, key: str, expires_at: int) -> str:
25+
return f'{expires_at or "*"}-{key}'
26+
27+
def _expires(self, expires_at: int) -> datetime:
28+
return datetime.utcfromtimestamp(expires_at).astimezone(timezone.utc)
29+
30+
def _files(self, key: str) -> Generator[Path]:
31+
return Path(self._storage_directory).glob(self._make_filename(key, 0))
32+
33+
def is_available(self) -> bool:
34+
"""
35+
Check if the provider is available (e.g. all required dependencies are available)
36+
This is used to determine if the provider should be used and to provide debug information.
37+
38+
IMPORTANT: This method SHOULD NOT make any network requests or perform any expensive operations.
39+
40+
Since this is called multiple times, we recommend caching the result.
41+
"""
42+
cache_home = getenv('XDG_CACHE_HOME')
43+
if not cache_home:
44+
return False
45+
# TODO: check the actual setting: cookiefile
46+
cookie_file = Path(cache_home) / '../cookies.txt'
47+
if not cookie_file.is_file():
48+
return False
49+
directory = Path(cache_home) / 'yt-dlp/youtube-pot'
50+
if directory.exists() and directory.is_dir():
51+
self._storage_directory = directory
52+
return True
53+
return False
54+
55+
def get(self, key: str):
56+
self.logger.trace(f'fs-get: {key=}')
57+
# ℹ️ Similar to PO Token Providers, Cache Providers and Cache Spec Providers
58+
# are passed down extractor args matching key youtubepot-<PROVIDER_KEY>.
59+
# some_setting = self._configuration_arg('some_setting', default=['default_value'])[0]
60+
found = None
61+
now = self._now()
62+
for file in sorted(self._files(key)):
63+
if not file.is_file():
64+
continue
65+
try:
66+
expires_at = int(file.name.partition('-')[0])
67+
except ValueError:
68+
continue
69+
else:
70+
if self._expires(expires_at) < now:
71+
self.logger.trace(f'fs-get: unlinking: {file.name}')
72+
file.unlink()
73+
else:
74+
self.logger.trace(f'fs-get: found: {file.name}')
75+
found = file
76+
77+
self.logger.trace(f'fs-get: {found=}')
78+
return None if found is None else found.read_bytes().decode()
79+
80+
def store(self, key: str, value: str, expires_at: int):
81+
self.logger.trace(f'fs-store: {expires_at=} {key=}')
82+
# ⚠ expires_at MUST be respected.
83+
# Cache entries should not be returned if they have expired.
84+
if self._expires(expires_at) > self._now():
85+
dst = Path(self._storage_directory) / self._make_filename(key, expires_at)
86+
self.logger.trace(f'fs-store: writing: {dst.name}')
87+
dst.write_bytes(value.encode())
88+
89+
def delete(self, key: str):
90+
self.logger.trace(f'fs-delete: {key=}')
91+
for file in self._files(key):
92+
if not file.is_file():
93+
continue
94+
self.logger.trace(f'fs-delete: unlinking: {file.name}')
95+
file.unlink()
96+
97+
def close(self):
98+
# Optional close hook, called when the YoutubeDL instance is closed.
99+
pass
100+
101+
# If there are multiple PO Token Cache Providers available, you can
102+
# define a preference function to increase/decrease the priority of providers.
103+
104+
# IMPORTANT: Providers should be in preference of cache lookup time.
105+
# For example, a memory cache should have a higher preference than a disk cache.
106+
107+
# VERY IMPORTANT: yt-dlp has a built-in memory cache with a priority of 10000.
108+
# Your cache provider should be lower than this.
109+
110+
111+
@register_preference(TubeSyncFileSystemPCP)
112+
def filesystem_cache_preference(provider: PoTokenCacheProvider, request: PoTokenRequest) -> int:
113+
return 10

0 commit comments

Comments
 (0)