diff --git a/backend/appsettings/serializers.py b/backend/appsettings/serializers.py index 3f145696..f26bc73d 100644 --- a/backend/appsettings/serializers.py +++ b/backend/appsettings/serializers.py @@ -55,7 +55,6 @@ class AppConfigDownloadsSerializer( ) cookie_import = serializers.BooleanField() pot_provider_url = serializers.CharField(allow_null=True) - potoken = serializers.BooleanField() throttledratelimit = serializers.IntegerField(allow_null=True) extractor_lang = serializers.CharField(allow_null=True) integrate_ryd = serializers.BooleanField() @@ -94,12 +93,6 @@ class CookieUpdateSerializer(serializers.Serializer): cookie = serializers.CharField() -class PoTokenSerializer(serializers.Serializer): - """serialize PO token""" - - potoken = serializers.CharField() - - class RescanFileSystemConfig(serializers.Serializer): """serialize rescan filesystem config""" diff --git a/backend/appsettings/src/config.py b/backend/appsettings/src/config.py index f557b459..103a59ab 100644 --- a/backend/appsettings/src/config.py +++ b/backend/appsettings/src/config.py @@ -42,7 +42,6 @@ class DownloadsConfigType(TypedDict): comment_sort: Literal["top", "new"] | None cookie_import: bool pot_provider_url: str | None - potoken: bool throttledratelimit: int | None extractor_lang: str | None integrate_ryd: bool @@ -92,7 +91,6 @@ class AppConfig: "comment_sort": "top", "cookie_import": False, "pot_provider_url": None, - "potoken": False, "throttledratelimit": None, "extractor_lang": None, "integrate_ryd": False, @@ -179,6 +177,34 @@ class AppConfig: return updated + def clear_old_keys(self) -> list[str]: + """clear old unused keys""" + cleared = [] + for key, value in self.config.items(): + if key not in self.CONFIG_DEFAULTS: + # complete key removed + self.config.pop(key) + cleared.append(str({key: value})) + continue + + expected_keys = set( + self.CONFIG_DEFAULTS[key].keys() # type: ignore + ) + is_keys = set(self.config[key].keys()) + + for to_delete in is_keys - expected_keys: + self.config[key].pop(to_delete) + cleared.append(f"{key}.{to_delete}") + + if not cleared: + return [] + + response, status_code = ElasticWrap(self.ES_PATH).post(self.config) + if not status_code == 200: + print(response) + + return cleared + class ReleaseVersion: """compare local version with remote version""" diff --git a/backend/appsettings/urls.py b/backend/appsettings/urls.py index 7a5c3632..104376ad 100644 --- a/backend/appsettings/urls.py +++ b/backend/appsettings/urls.py @@ -34,11 +34,6 @@ urlpatterns = [ views.CookieView.as_view(), name="api-cookie", ), - path( - "potoken/", - views.POTokenView.as_view(), - name="api-potoken", - ), path( "token/", views.TokenView.as_view(), diff --git a/backend/appsettings/views.py b/backend/appsettings/views.py index 83787b02..91b6b89d 100644 --- a/backend/appsettings/views.py +++ b/backend/appsettings/views.py @@ -6,7 +6,6 @@ from appsettings.serializers import ( CookieUpdateSerializer, CookieValidationSerializer, ManualImportConfig, - PoTokenSerializer, RescanFileSystemConfig, SnapshotCreateResponseSerializer, SnapshotItemSerializer, @@ -24,7 +23,7 @@ from common.serializers import ( from common.src.ta_redis import RedisArchivist from common.views_base import AdminOnly, AdminWriteOnly, ApiBaseView from django.conf import settings -from download.src.yt_dlp_base import CookieHandler, POTokenHandler +from download.src.yt_dlp_base import CookieHandler from drf_spectacular.utils import OpenApiResponse, extend_schema from rest_framework.authtoken.models import Token from rest_framework.response import Response @@ -292,73 +291,6 @@ class CookieView(ApiBaseView): return validation -class POTokenView(ApiBaseView): - """resolves to /api/appsettings/potoken/ - GET: get potoken - POST: update potoken - DELETE: revoke potoken - """ - - permission_classes = [AdminOnly] - - @extend_schema( - responses={ - 200: OpenApiResponse(PoTokenSerializer()), - 404: OpenApiResponse( - ErrorResponseSerializer(), description="PO token not found" - ), - } - ) - def get(self, request): - """get PO token""" - config = AppConfig().config - potoken = POTokenHandler(config).get() - if not potoken: - error = ErrorResponseSerializer({"error": "PO token not found"}) - return Response(error.data, status=404) - - serializer = PoTokenSerializer(data={"potoken": potoken}) - serializer.is_valid(raise_exception=True) - - return Response(serializer.data) - - @extend_schema( - responses={ - 200: OpenApiResponse(PoTokenSerializer()), - 400: OpenApiResponse( - ErrorResponseSerializer(), description="Bad request" - ), - } - ) - def post(self, request): - """Update PO token""" - serializer = PoTokenSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - validated_data = serializer.validated_data - if not validated_data: - error = ErrorResponseSerializer( - {"error": "missing PO token key in request data"} - ) - return Response(error.data, status=400) - - config = AppConfig().config - new_token = validated_data["potoken"] - - POTokenHandler(config).set_token(new_token) - return Response(serializer.data) - - @extend_schema( - responses={ - 204: OpenApiResponse(description="PO token revoked"), - }, - ) - def delete(self, request): - """delete PO token""" - config = AppConfig().config - POTokenHandler(config).revoke_token() - return Response(status=204) - - class SnapshotApiListView(ApiBaseView): """resolves to /api/appsettings/snapshot/ GET: returns snapshot config plus list of existing snapshots diff --git a/backend/config/management/commands/ta_startup.py b/backend/config/management/commands/ta_startup.py index a39c5c7f..e65a701a 100644 --- a/backend/config/management/commands/ta_startup.py +++ b/backend/config/management/commands/ta_startup.py @@ -280,6 +280,12 @@ class Command(BaseCommand): self.style.SUCCESS(f" added new default: {new_default}") ) + cleared = AppConfig().clear_old_keys() + for removed_key in cleared: + self.stdout.write( + self.style.SUCCESS(f" removed old key: {removed_key}") + ) + return if status_code != 404: diff --git a/backend/download/src/yt_dlp_base.py b/backend/download/src/yt_dlp_base.py index 383d9166..8c416fbd 100644 --- a/backend/download/src/yt_dlp_base.py +++ b/backend/download/src/yt_dlp_base.py @@ -42,7 +42,6 @@ class YtWrap: deep_merge(self.obs, self.obs_request) if self.config: self._add_cookie() - self._add_potoken() self._add_potoken_url() if getattr(settings, "DEBUG", False): @@ -58,22 +57,6 @@ class YtWrap: self.obs["cookiefile"] = cookie_io - def _add_potoken(self): - """add potoken if enabled""" - if self.config["downloads"].get("potoken"): - potoken = POTokenHandler(self.config).get() - deep_merge( - self.obs, - { - "extractor_args": { - "youtube": { - "po_token": [potoken], - "player-client": ["mweb", "default"], - }, - } - }, - ) - def _add_potoken_url(self): """add bgutils token url""" if pot_provider_url := self.config["downloads"].get( @@ -248,27 +231,3 @@ class CookieHandler: "validated_str": now.strftime("%Y-%m-%d %H:%M"), } RedisArchivist().set_message("cookie:valid", message, expire=3600) - - -class POTokenHandler: - """handle po token""" - - REDIS_KEY = "potoken" - - def __init__(self, config): - self.config = config - - def get(self) -> str | None: - """get PO token""" - potoken = RedisArchivist().get_message_str(self.REDIS_KEY) - return potoken - - def set_token(self, new_token: str) -> None: - """set new PO token""" - RedisArchivist().set_message(self.REDIS_KEY, new_token) - AppConfig().update_config({"downloads": {"potoken": True}}) - - def revoke_token(self) -> None: - """revoke token""" - RedisArchivist().del_message(self.REDIS_KEY) - AppConfig().update_config({"downloads": {"potoken": False}}) diff --git a/frontend/src/api/actions/deletePoToken.ts b/frontend/src/api/actions/deletePoToken.ts deleted file mode 100644 index b8ffc8c5..00000000 --- a/frontend/src/api/actions/deletePoToken.ts +++ /dev/null @@ -1,9 +0,0 @@ -import APIClient from '../../functions/APIClient'; - -const deletePoToken = async () => { - return APIClient('/api/appsettings/potoken/', { - method: 'DELETE', - }); -}; - -export default deletePoToken; diff --git a/frontend/src/api/actions/updatePoToken.ts b/frontend/src/api/actions/updatePoToken.ts deleted file mode 100644 index 1c6355ef..00000000 --- a/frontend/src/api/actions/updatePoToken.ts +++ /dev/null @@ -1,10 +0,0 @@ -import APIClient from '../../functions/APIClient'; - -const updatePoToken = async (potoken: string) => { - return APIClient('/api/appsettings/potoken/', { - method: 'POST', - body: { potoken }, - }); -}; - -export default updatePoToken; diff --git a/frontend/src/api/loader/loadAppsettingsConfig.ts b/frontend/src/api/loader/loadAppsettingsConfig.ts index fb05d00c..47b1ba3a 100644 --- a/frontend/src/api/loader/loadAppsettingsConfig.ts +++ b/frontend/src/api/loader/loadAppsettingsConfig.ts @@ -23,7 +23,6 @@ export type AppSettingsConfigType = { comment_sort: string; cookie_import: boolean; pot_provider_url: string | null; - potoken: boolean; throttledratelimit: number | null; extractor_lang: string | null; integrate_ryd: boolean; diff --git a/frontend/src/pages/SettingsApplication.tsx b/frontend/src/pages/SettingsApplication.tsx index 2d2153a0..5507c107 100644 --- a/frontend/src/pages/SettingsApplication.tsx +++ b/frontend/src/pages/SettingsApplication.tsx @@ -17,8 +17,6 @@ import updateCookie from '../api/actions/updateCookie'; import loadCookie, { CookieStateType } from '../api/loader/loadCookie'; import deleteCookie from '../api/actions/deleteCookie'; import validateCookie from '../api/actions/validateCookie'; -import deletePoToken from '../api/actions/deletePoToken'; -import updatePoToken from '../api/actions/updatePoToken'; import { useUserConfigStore } from '../stores/UserConfigStore'; import MembershipAppsettings from '../components/MembershipAppsettings'; @@ -71,8 +69,6 @@ const SettingsApplication = () => { // Cookie const [cookieFormData, setCookieFormData] = useState(''); const [showCookieForm, setShowCookieForm] = useState(false); - const [poTokenFormData, setPoTokenFormData] = useState('web+'); - const [showPoTokenForm, setShowPoTokenForm] = useState(false); const [potProviderUrl, setPotProviderUrl] = useState(null); // Integrations @@ -172,18 +168,6 @@ const SettingsApplication = () => { setRefresh(true); }; - const handlePoTokenRevoke = async () => { - await deletePoToken(); - setRefresh(true); - }; - - const handlePoTokenUpdate = async () => { - await updatePoToken(poTokenFormData); - setPoTokenFormData('web+'); - setShowPoTokenForm(false); - setRefresh(true); - }; - useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect fetchData(); @@ -765,55 +749,6 @@ const SettingsApplication = () => { )} -
-
-

Add PO Token

-
-
- {response?.appSettingsConfig?.downloads.potoken ? ( - <> -

PO Token enabled.

- - - ) : ( -

PO Token disabled

- )} - {showPoTokenForm ? ( -
- { - setPoTokenFormData(e.target.value); - }} - /> - {poTokenFormData !== 'web+' && ( - - )} - -
- ) : ( -
- -
- )} -
-

PO Token Provider URL

diff --git a/frontend/src/stores/AppSettingsStore.ts b/frontend/src/stores/AppSettingsStore.ts index 9db60607..1f8654e2 100644 --- a/frontend/src/stores/AppSettingsStore.ts +++ b/frontend/src/stores/AppSettingsStore.ts @@ -30,7 +30,6 @@ export const useAppSettingsStore = create(set => ({ comment_sort: 'asc', cookie_import: false, pot_provider_url: null, - potoken: false, throttledratelimit: null, extractor_lang: null, integrate_ryd: false,